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 "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
52 using namespace ParaMEDMEM;
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
57 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 };
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
62 return new MEDCouplingUMesh;
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
67 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68 ret->setName(meshName);
69 ret->setMeshDimension(meshDim);
74 * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75 * between \a this and the new mesh.
76 * \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77 * delete this mesh using decrRef() as it is no more needed.
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCpy() const
86 * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88 * this mesh are shared by the new mesh.
89 * \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90 * delete this mesh using decrRef() as it is no more needed.
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
94 return new MEDCouplingUMesh(*this,recDeepCpy);
98 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
99 * The coordinates are shared between \a this and the returned instance.
101 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102 * \sa MEDCouplingUMesh::deepCpy
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCpyConnectivityOnly() const
106 checkConnectivityFullyDefined();
107 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
109 ret->setConnectivity(c,ci);
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
116 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
119 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
126 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
132 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133 ret.push_back(_nodal_connec);
134 ret.push_back(_nodal_connec_index);
138 void MEDCouplingUMesh::updateTime() const
140 MEDCouplingPointSet::updateTime();
143 updateTimeWith(*_nodal_connec);
145 if(_nodal_connec_index)
147 updateTimeWith(*_nodal_connec_index);
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
156 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157 * then \a this mesh is most probably is writable, exchangeable and available for most
158 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159 * this method to check that all is in order with \a this mesh.
160 * \throw If the mesh dimension is not set.
161 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
162 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163 * \throw If the connectivity data array has more than one component.
164 * \throw If the connectivity data array has a named component.
165 * \throw If the connectivity index data array has more than one component.
166 * \throw If the connectivity index data array has a named component.
168 void MEDCouplingUMesh::checkCoherency() const
171 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
173 MEDCouplingPointSet::checkCoherency();
174 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
176 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
178 std::ostringstream message;
179 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180 throw INTERP_KERNEL::Exception(message.str().c_str());
185 if(_nodal_connec->getNumberOfComponents()!=1)
186 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187 if(_nodal_connec->getInfoOnComponent(0)!="")
188 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
192 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193 if(_nodal_connec_index)
195 if(_nodal_connec_index->getNumberOfComponents()!=1)
196 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197 if(_nodal_connec_index->getInfoOnComponent(0)!="")
198 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
202 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
206 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207 * then \a this mesh is most probably is writable, exchangeable and available for all
208 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
209 * method thoroughly checks the nodal connectivity.
210 * \param [in] eps - a not used parameter.
211 * \throw If the mesh dimension is not set.
212 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
213 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214 * \throw If the connectivity data array has more than one component.
215 * \throw If the connectivity data array has a named component.
216 * \throw If the connectivity index data array has more than one component.
217 * \throw If the connectivity index data array has a named component.
218 * \throw If number of nodes defining an element does not correspond to the type of element.
219 * \throw If the nodal connectivity includes an invalid node id.
221 void MEDCouplingUMesh::checkCoherency1(double eps) const
226 int meshDim=getMeshDimension();
227 int nbOfNodes=getNumberOfNodes();
228 int nbOfCells=getNumberOfCells();
229 const int *ptr=_nodal_connec->getConstPointer();
230 const int *ptrI=_nodal_connec_index->getConstPointer();
231 for(int i=0;i<nbOfCells;i++)
233 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234 if((int)cm.getDimension()!=meshDim)
236 std::ostringstream oss;
237 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238 throw INTERP_KERNEL::Exception(oss.str().c_str());
240 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
242 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
244 std::ostringstream oss;
245 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
246 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247 throw INTERP_KERNEL::Exception(oss.str().c_str());
249 if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250 if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
252 std::ostringstream oss;
253 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " << nbOfNodesInCell;
254 oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255 throw INTERP_KERNEL::Exception(oss.str().c_str());
257 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
262 if(nodeId>=nbOfNodes)
264 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
270 std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271 throw INTERP_KERNEL::Exception(oss.str().c_str());
275 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
277 std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278 throw INTERP_KERNEL::Exception(oss.str().c_str());
287 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
288 * then \a this mesh is most probably is writable, exchangeable and available for all
289 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
290 * \param [in] eps - a not used parameter.
291 * \throw If the mesh dimension is not set.
292 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
293 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
294 * \throw If the connectivity data array has more than one component.
295 * \throw If the connectivity data array has a named component.
296 * \throw If the connectivity index data array has more than one component.
297 * \throw If the connectivity index data array has a named component.
298 * \throw If number of nodes defining an element does not correspond to the type of element.
299 * \throw If the nodal connectivity includes an invalid node id.
301 void MEDCouplingUMesh::checkCoherency2(double eps) const
303 checkCoherency1(eps);
307 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
308 * elements contained in the mesh. For more info on the mesh dimension see
309 * \ref MEDCouplingUMeshPage.
310 * \param [in] meshDim - a new mesh dimension.
311 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
313 void MEDCouplingUMesh::setMeshDimension(int meshDim)
315 if(meshDim<-1 || meshDim>3)
316 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
322 * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
323 * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
324 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
326 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
328 * \if ENABLE_EXAMPLES
329 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
330 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
333 void MEDCouplingUMesh::allocateCells(int nbOfCells)
336 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
337 if(_nodal_connec_index)
339 _nodal_connec_index->decrRef();
343 _nodal_connec->decrRef();
345 _nodal_connec_index=DataArrayInt::New();
346 _nodal_connec_index->reserve(nbOfCells+1);
347 _nodal_connec_index->pushBackSilent(0);
348 _nodal_connec=DataArrayInt::New();
349 _nodal_connec->reserve(2*nbOfCells);
355 * Appends a cell to the connectivity array. For deeper understanding what is
356 * happening see \ref MEDCouplingUMeshNodalConnectivity.
357 * \param [in] type - type of cell to add.
358 * \param [in] size - number of nodes constituting this cell.
359 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
361 * \if ENABLE_EXAMPLES
362 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
366 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
368 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
369 if(_nodal_connec_index==0)
370 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
371 if((int)cm.getDimension()==_mesh_dim)
374 if(size!=(int)cm.getNumberOfNodes())
376 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
377 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
378 throw INTERP_KERNEL::Exception(oss.str().c_str());
380 int idx=_nodal_connec_index->back();
382 _nodal_connec_index->pushBackSilent(val);
383 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
388 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
389 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
390 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
391 throw INTERP_KERNEL::Exception(oss.str().c_str());
396 * Compacts data arrays to release unused memory. This method is to be called after
397 * finishing cell insertion using \a this->insertNextCell().
399 * \if ENABLE_EXAMPLES
400 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
401 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
404 void MEDCouplingUMesh::finishInsertingCells()
406 _nodal_connec->pack();
407 _nodal_connec_index->pack();
408 _nodal_connec->declareAsNew();
409 _nodal_connec_index->declareAsNew();
414 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
415 * Useful for python users.
417 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
419 return new MEDCouplingUMeshCellIterator(this);
423 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
424 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
425 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
426 * Useful for python users.
428 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
430 if(!checkConsecutiveCellTypes())
431 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
432 return new MEDCouplingUMeshCellByTypeEntry(this);
436 * Returns a set of all cell types available in \a this mesh.
437 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
438 * \warning this method does not throw any exception even if \a this is not defined.
439 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
441 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
447 * This method returns the sorted list of geometric types in \a this.
448 * 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
449 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
451 * \throw if connectivity in \a this is not correctly defined.
453 * \sa MEDCouplingMesh::getAllGeoTypes
455 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
457 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
458 checkConnectivityFullyDefined();
459 int nbOfCells(getNumberOfCells());
462 if(getMeshLength()<1)
463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
464 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
465 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
466 for(int i=1;i<nbOfCells;i++,ci++)
467 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
468 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
473 * This method is a method that compares \a this and \a other.
474 * This method compares \b all attributes, even names and component names.
476 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
479 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
480 std::ostringstream oss; oss.precision(15);
481 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
484 reason="mesh given in input is not castable in MEDCouplingUMesh !";
487 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
489 if(_mesh_dim!=otherC->_mesh_dim)
491 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
495 if(_types!=otherC->_types)
497 oss << "umesh geometric type mismatch :\nThis geometric types are :";
498 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
499 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500 oss << "\nOther geometric types are :";
501 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
502 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
506 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
507 if(_nodal_connec==0 || otherC->_nodal_connec==0)
509 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
512 if(_nodal_connec!=otherC->_nodal_connec)
513 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
515 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
518 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
519 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
521 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
524 if(_nodal_connec_index!=otherC->_nodal_connec_index)
525 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
527 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
534 * Checks if data arrays of this mesh (node coordinates, nodal
535 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
537 * \param [in] other - the mesh to compare with.
538 * \param [in] prec - precision value used to compare node coordinates.
539 * \return bool - \a true if the two meshes are same.
541 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
543 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
546 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
548 if(_mesh_dim!=otherC->_mesh_dim)
550 if(_types!=otherC->_types)
552 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
553 if(_nodal_connec==0 || otherC->_nodal_connec==0)
555 if(_nodal_connec!=otherC->_nodal_connec)
556 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
558 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
559 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
561 if(_nodal_connec_index!=otherC->_nodal_connec_index)
562 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
568 * Checks if \a this and \a other meshes are geometrically equivalent with high
569 * probability, else an exception is thrown. The meshes are considered equivalent if
570 * (1) meshes contain the same number of nodes and the same number of elements of the
571 * same types (2) three cells of the two meshes (first, last and middle) are based
572 * on coincident nodes (with a specified precision).
573 * \param [in] other - the mesh to compare with.
574 * \param [in] prec - the precision used to compare nodes of the two meshes.
575 * \throw If the two meshes do not match.
577 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
579 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
580 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
586 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
587 * cells each node belongs to.
588 * \warning For speed reasons, this method does not check if node ids in the nodal
589 * connectivity correspond to the size of node coordinates array.
590 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
591 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
592 * dividing cell ids in \a revNodal into groups each referring to one
593 * node. Its every element (except the last one) is an index pointing to the
594 * first id of a group of cells. For example cells sharing the node #1 are
595 * described by following range of indices:
596 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
597 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
598 * Number of cells sharing the *i*-th node is
599 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
600 * \throw If the coordinates array is not set.
601 * \throw If the nodal connectivity of cells is not defined.
603 * \if ENABLE_EXAMPLES
604 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
605 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
608 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
611 int nbOfNodes=getNumberOfNodes();
612 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
613 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
614 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
615 const int *conn=_nodal_connec->getConstPointer();
616 const int *connIndex=_nodal_connec_index->getConstPointer();
617 int nbOfCells=getNumberOfCells();
618 int nbOfEltsInRevNodal=0;
619 for(int eltId=0;eltId<nbOfCells;eltId++)
621 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
622 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
623 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
624 if(*iter>=0)//for polyhedrons
626 nbOfEltsInRevNodal++;
627 revNodalIndxPtr[(*iter)+1]++;
630 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
631 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
632 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
633 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
634 for(int eltId=0;eltId<nbOfCells;eltId++)
636 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
637 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
638 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
639 if(*iter>=0)//for polyhedrons
640 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
646 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
651 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
657 if(cm.getOrientationStatus(nb,conn1,conn2))
664 class MinusOneSonsGenerator
667 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670 static const int DELTA=1;
672 const INTERP_KERNEL::CellModel& _cm;
675 class MinusOneSonsGeneratorBiQuadratic
678 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
680 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681 static const int DELTA=1;
683 const INTERP_KERNEL::CellModel& _cm;
686 class MinusTwoSonsGenerator
689 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
690 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
691 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
692 static const int DELTA=2;
694 const INTERP_KERNEL::CellModel& _cm;
700 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
701 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
702 * describing correspondence between cells of \a this and the result meshes are
703 * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
704 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
705 * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
706 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
707 * \warning For speed reasons, this method does not check if node ids in the nodal
708 * connectivity correspond to the size of node coordinates array.
709 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710 * to write this mesh to the MED file, its cells must be sorted using
711 * sortCellsInMEDFileFrmt().
712 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
713 * each cell of \a this mesh.
714 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715 * dividing cell ids in \a desc into groups each referring to one
716 * cell of \a this mesh. Its every element (except the last one) is an index
717 * pointing to the first id of a group of cells. For example cells of the
718 * result mesh bounding the cell #1 of \a this mesh are described by following
720 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725 * by each cell of the result mesh.
726 * \param [in,out] revDescIndx - the array, of length one more than number of cells
727 * in the result mesh,
728 * dividing cell ids in \a revDesc into groups each referring to one
729 * cell of the result mesh the same way as \a descIndx divides \a desc.
730 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
731 * delete this mesh using decrRef() as it is no more needed.
732 * \throw If the coordinates array is not set.
733 * \throw If the nodal connectivity of cells is node defined.
734 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
735 * revDescIndx == NULL.
737 * \if ENABLE_EXAMPLES
738 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
739 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
741 * \sa buildDescendingConnectivity2()
743 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
749 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
750 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
751 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
752 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
753 * \sa MEDCouplingUMesh::buildDescendingConnectivity
755 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
758 if(getMeshDimension()!=3)
759 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
760 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
764 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
765 * this->getMeshDimension(), that bound cells of \a this mesh. In
766 * addition arrays describing correspondence between cells of \a this and the result
767 * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
768 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
769 * mesh. This method differs from buildDescendingConnectivity() in that apart
770 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
771 * result meshes. So a positive id means that order of nodes in corresponding cells
772 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
773 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
774 * i.e. cell ids are one-based.
775 * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
776 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
777 * \warning For speed reasons, this method does not check if node ids in the nodal
778 * connectivity correspond to the size of node coordinates array.
779 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
780 * to write this mesh to the MED file, its cells must be sorted using
781 * sortCellsInMEDFileFrmt().
782 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
783 * each cell of \a this mesh.
784 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
785 * dividing cell ids in \a desc into groups each referring to one
786 * cell of \a this mesh. Its every element (except the last one) is an index
787 * pointing to the first id of a group of cells. For example cells of the
788 * result mesh bounding the cell #1 of \a this mesh are described by following
790 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
791 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
792 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
793 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
794 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
795 * by each cell of the result mesh.
796 * \param [in,out] revDescIndx - the array, of length one more than number of cells
797 * in the result mesh,
798 * dividing cell ids in \a revDesc into groups each referring to one
799 * cell of the result mesh the same way as \a descIndx divides \a desc.
800 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
801 * shares the node coordinates array with \a this mesh. The caller is to
802 * delete this mesh using decrRef() as it is no more needed.
803 * \throw If the coordinates array is not set.
804 * \throw If the nodal connectivity of cells is node defined.
805 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
806 * revDescIndx == NULL.
808 * \if ENABLE_EXAMPLES
809 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
810 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
812 * \sa buildDescendingConnectivity()
814 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
816 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
820 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
821 * For speed reasons no check of this will be done. This method calls
822 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
823 * This method lists cell by cell in \b this which are its neighbors. To compute the result
824 * only connectivities are considered.
825 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
826 * The format of return is hence \ref numbering-indirect.
828 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
829 * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
830 * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
831 * is equal to the last values in \b neighborsIndx.
832 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
833 * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
835 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
841 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
843 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
847 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
848 * of MEDCouplingUMesh::computeNeighborsOfCells.
849 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
850 * typically the case to extract a set a neighbours,
851 * excluding a set of meshdim-1 cells in input descending connectivity.
852 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
853 * the result of MEDCouplingUMesh::buildDescendingConnectivity.
854 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
856 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
858 * \param [in] desc descending connectivity array.
859 * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
860 * \param [in] revDesc reverse descending connectivity array.
861 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
862 * \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
863 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
864 * \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.
866 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
867 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
869 if(!desc || !descIndx || !revDesc || !revDescIndx)
870 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
871 const int *descPtr=desc->getConstPointer();
872 const int *descIPtr=descIndx->getConstPointer();
873 const int *revDescPtr=revDesc->getConstPointer();
874 const int *revDescIPtr=revDescIndx->getConstPointer();
876 int nbCells=descIndx->getNumberOfTuples()-1;
877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
879 int *out1Ptr=out1->getPointer();
881 out0->reserve(desc->getNumberOfTuples());
882 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
884 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
886 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
888 out0->insertAtTheEnd(s.begin(),s.end());
890 *out1Ptr=out0->getNumberOfTuples();
892 neighbors=out0.retn();
893 neighborsIndx=out1.retn();
897 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
898 * For speed reasons no check of this will be done. This method calls
899 * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
900 * This method lists node by node in \b this which are its neighbors. To compute the result
901 * only connectivities are considered.
902 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
904 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
905 * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
906 * parameter allows to select the right part in this array (\ref numbering-indirect).
907 * The number of tuples is equal to the last values in \b neighborsIndx.
908 * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
909 * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
911 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
914 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
916 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
921 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
926 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
931 mesh1D=const_cast<MEDCouplingUMesh *>(this);
937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
940 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
941 mesh1D->getReverseNodalConnectivity(desc,descIndx);
942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
943 ret0->alloc(desc->getNumberOfTuples(),1);
944 int *r0Pt(ret0->getPointer());
945 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
946 for(int i=0;i<nbNodes;i++,rni++)
948 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
949 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
951 neighbors=ret0.retn();
952 neighborsIdx=descIndx.retn();
958 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
959 * For speed reasons no check of this will be done.
961 template<class SonsGenerator>
962 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
964 if(!desc || !descIndx || !revDesc || !revDescIndx)
965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
966 checkConnectivityFullyDefined();
967 int nbOfCells=getNumberOfCells();
968 int nbOfNodes=getNumberOfNodes();
969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
970 int *revNodalIndxPtr=revNodalIndx->getPointer();
971 const int *conn=_nodal_connec->getConstPointer();
972 const int *connIndex=_nodal_connec_index->getConstPointer();
973 std::string name="Mesh constituent of "; name+=getName();
974 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
975 ret->setCoords(getCoords());
976 ret->allocateCells(2*nbOfCells);
977 descIndx->alloc(nbOfCells+1,1);
978 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
979 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
980 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
982 int pos=connIndex[eltId];
983 int posP1=connIndex[eltId+1];
984 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
985 SonsGenerator sg(cm);
986 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
987 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
988 for(unsigned i=0;i<nbOfSons;i++)
990 INTERP_KERNEL::NormalizedCellType cmsId;
991 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
992 for(unsigned k=0;k<nbOfNodesSon;k++)
994 revNodalIndxPtr[tmp[k]+1]++;
995 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
996 revDesc2->pushBackSilent(eltId);
998 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
1000 int nbOfCellsM1=ret->getNumberOfCells();
1001 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1003 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1004 int *revNodalPtr=revNodal->getPointer();
1005 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1006 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1007 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1009 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1010 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1011 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1012 if(*iter>=0)//for polyhedrons
1013 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1016 DataArrayInt *commonCells=0,*commonCellsI=0;
1017 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1019 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1020 int newNbOfCellsM1=-1;
1021 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1022 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1023 std::vector<bool> isImpacted(nbOfCellsM1,false);
1024 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1025 for(int work2=work[0];work2!=work[1];work2++)
1026 isImpacted[commonCellsPtr[work2]]=true;
1027 const int *o2nM1Ptr=o2nM1->getConstPointer();
1028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1029 const int *n2oM1Ptr=n2oM1->getConstPointer();
1030 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1031 ret2->copyTinyInfoFrom(this);
1032 desc->alloc(descIndx->back(),1);
1033 int *descPtr=desc->getPointer();
1034 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1035 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1038 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1041 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1043 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1044 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1047 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1050 revDesc->reserve(newNbOfCellsM1);
1051 revDescIndx->alloc(newNbOfCellsM1+1,1);
1052 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1053 const int *revDesc2Ptr=revDesc2->getConstPointer();
1054 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1056 int oldCellIdM1=n2oM1Ptr[i];
1057 if(!isImpacted[oldCellIdM1])
1059 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1060 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1064 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1065 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1066 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1074 struct MEDCouplingAccVisit
1076 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1077 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1078 int _new_nb_of_nodes;
1084 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1085 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1086 * array of cell ids. Pay attention that after conversion all algorithms work slower
1087 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1088 * conversion due presence of invalid ids in the array of cells to convert, as a
1089 * result \a this mesh contains some already converted elements. In this case the 2D
1090 * mesh remains valid but 3D mesh becomes \b inconsistent!
1091 * \warning This method can significantly modify the order of geometric types in \a this,
1092 * hence, to write this mesh to the MED file, its cells must be sorted using
1093 * sortCellsInMEDFileFrmt().
1094 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1095 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1096 * cellIdsToConvertBg.
1097 * \throw If the coordinates array is not set.
1098 * \throw If the nodal connectivity of cells is node defined.
1099 * \throw If dimension of \a this mesh is not either 2 or 3.
1101 * \if ENABLE_EXAMPLES
1102 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1103 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1106 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1108 checkFullyDefined();
1109 int dim=getMeshDimension();
1111 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1112 int nbOfCells(getNumberOfCells());
1115 const int *connIndex=_nodal_connec_index->getConstPointer();
1116 int *conn=_nodal_connec->getPointer();
1117 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1119 if(*iter>=0 && *iter<nbOfCells)
1121 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1122 if(!cm.isQuadratic())
1123 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1125 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1129 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130 oss << " in range [0," << nbOfCells << ") !";
1131 throw INTERP_KERNEL::Exception(oss.str().c_str());
1137 int *connIndex(_nodal_connec_index->getPointer());
1138 const int *connOld(_nodal_connec->getConstPointer());
1139 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1140 std::vector<bool> toBeDone(nbOfCells,false);
1141 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1143 if(*iter>=0 && *iter<nbOfCells)
1144 toBeDone[*iter]=true;
1147 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1148 oss << " in range [0," << nbOfCells << ") !";
1149 throw INTERP_KERNEL::Exception(oss.str().c_str());
1152 for(int cellId=0;cellId<nbOfCells;cellId++)
1154 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1155 int lgthOld(posP1-pos-1);
1156 if(toBeDone[cellId])
1158 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1159 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1160 int *tmp(new int[nbOfFaces*lgthOld+1]);
1161 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1162 for(unsigned j=0;j<nbOfFaces;j++)
1164 INTERP_KERNEL::NormalizedCellType type;
1165 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1169 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1170 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1171 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1176 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1177 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1180 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1186 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1187 * polyhedrons (if \a this is a 3D mesh).
1188 * \warning As this method is purely for user-friendliness and no optimization is
1189 * done to avoid construction of a useless vector, this method can be costly
1191 * \throw If the coordinates array is not set.
1192 * \throw If the nodal connectivity of cells is node defined.
1193 * \throw If dimension of \a this mesh is not either 2 or 3.
1195 void MEDCouplingUMesh::convertAllToPoly()
1197 int nbOfCells=getNumberOfCells();
1198 std::vector<int> cellIds(nbOfCells);
1199 for(int i=0;i<nbOfCells;i++)
1201 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1205 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1206 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1207 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1208 * base facet of the volume and the second half of nodes describes an opposite facet
1209 * having the same number of nodes as the base one. This method converts such
1210 * connectivity to a valid polyhedral format where connectivity of each facet is
1211 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1212 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1213 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1214 * a correct orientation of the first facet of a polyhedron, else orientation of a
1215 * corrected cell is reverse.<br>
1216 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1217 * it releases the user from boring description of polyhedra connectivity in the valid
1219 * \throw If \a this->getMeshDimension() != 3.
1220 * \throw If \a this->getSpaceDimension() != 3.
1221 * \throw If the nodal connectivity of cells is not defined.
1222 * \throw If the coordinates array is not set.
1223 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1224 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1226 * \if ENABLE_EXAMPLES
1227 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1228 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1231 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1233 checkFullyDefined();
1234 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1235 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1236 int nbOfCells=getNumberOfCells();
1237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1238 newCi->alloc(nbOfCells+1,1);
1239 int *newci=newCi->getPointer();
1240 const int *ci=_nodal_connec_index->getConstPointer();
1241 const int *c=_nodal_connec->getConstPointer();
1243 for(int i=0;i<nbOfCells;i++)
1245 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1246 if(type==INTERP_KERNEL::NORM_POLYHED)
1248 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1250 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1251 throw INTERP_KERNEL::Exception(oss.str().c_str());
1253 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1256 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 !";
1257 throw INTERP_KERNEL::Exception(oss.str().c_str());
1260 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)
1263 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1266 newC->alloc(newci[nbOfCells],1);
1267 int *newc=newC->getPointer();
1268 for(int i=0;i<nbOfCells;i++)
1270 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1271 if(type==INTERP_KERNEL::NORM_POLYHED)
1273 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1274 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1276 for(std::size_t j=0;j<n1;j++)
1278 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1280 newc[n1+5*j+1]=c[ci[i]+1+j];
1281 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1282 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1283 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1288 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1290 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1291 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1296 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1297 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1298 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1299 * to write this mesh to the MED file, its cells must be sorted using
1300 * sortCellsInMEDFileFrmt().
1301 * \return \c true if at least one cell has been converted, \c false else. In the
1302 * last case the nodal connectivity remains unchanged.
1303 * \throw If the coordinates array is not set.
1304 * \throw If the nodal connectivity of cells is not defined.
1305 * \throw If \a this->getMeshDimension() < 0.
1307 bool MEDCouplingUMesh::unPolyze()
1309 checkFullyDefined();
1310 int mdim=getMeshDimension();
1312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1315 int nbOfCells=getNumberOfCells();
1318 int initMeshLgth=getMeshLength();
1319 int *conn=_nodal_connec->getPointer();
1320 int *index=_nodal_connec_index->getPointer();
1325 for(int i=0;i<nbOfCells;i++)
1327 lgthOfCurCell=index[i+1]-posOfCurCell;
1328 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1329 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1330 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1334 switch(cm.getDimension())
1338 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1339 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1340 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1345 int nbOfFaces,lgthOfPolyhConn;
1346 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1347 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1352 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1356 ret=ret || (newType!=type);
1357 conn[newPos]=newType;
1359 posOfCurCell=index[i+1];
1364 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1365 newPos+=lgthOfCurCell;
1366 posOfCurCell+=lgthOfCurCell;
1370 if(newPos!=initMeshLgth)
1371 _nodal_connec->reAlloc(newPos);
1378 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1379 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1380 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1382 * \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
1385 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1387 checkFullyDefined();
1388 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1389 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1390 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1391 coords->recenterForMaxPrecision(eps);
1393 int nbOfCells=getNumberOfCells();
1394 const int *conn=_nodal_connec->getConstPointer();
1395 const int *index=_nodal_connec_index->getConstPointer();
1396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1397 connINew->alloc(nbOfCells+1,1);
1398 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1401 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1403 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1405 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1409 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1410 *connINewPtr=connNew->getNumberOfTuples();
1413 setConnectivity(connNew,connINew,false);
1417 * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1418 * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1419 * the format of the returned DataArrayInt instance.
1421 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1422 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1424 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1426 checkConnectivityFullyDefined();
1427 int nbOfCells=getNumberOfCells();
1428 const int *connIndex=_nodal_connec_index->getConstPointer();
1429 const int *conn=_nodal_connec->getConstPointer();
1430 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1431 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1432 std::vector<bool> retS(maxElt,false);
1433 for(int i=0;i<nbOfCells;i++)
1434 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1438 for(int i=0;i<maxElt;i++)
1441 DataArrayInt *ret=DataArrayInt::New();
1443 int *retPtr=ret->getPointer();
1444 for(int i=0;i<maxElt;i++)
1451 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1452 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1454 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1456 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1457 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1458 for(int i=0;i<nbOfCells;i++)
1459 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1462 if(conn[j]<nbOfNodes)
1463 nodeIdsInUse[conn[j]]=true;
1466 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1467 throw INTERP_KERNEL::Exception(oss.str().c_str());
1473 * Finds nodes not used in any cell and returns an array giving a new id to every node
1474 * by excluding the unused nodes, for which the array holds -1. The result array is
1475 * a mapping in "Old to New" mode.
1476 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1477 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1478 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1479 * if the node is unused or a new id else. The caller is to delete this
1480 * array using decrRef() as it is no more needed.
1481 * \throw If the coordinates array is not set.
1482 * \throw If the nodal connectivity of cells is not defined.
1483 * \throw If the nodal connectivity includes an invalid id.
1485 * \if ENABLE_EXAMPLES
1486 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1487 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1489 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1491 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1494 int nbOfNodes(getNumberOfNodes());
1495 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1496 ret->alloc(nbOfNodes,1);
1497 int *traducer=ret->getPointer();
1498 std::fill(traducer,traducer+nbOfNodes,-1);
1499 int nbOfCells=getNumberOfCells();
1500 const int *connIndex=_nodal_connec_index->getConstPointer();
1501 const int *conn=_nodal_connec->getConstPointer();
1502 for(int i=0;i<nbOfCells;i++)
1503 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1506 if(conn[j]<nbOfNodes)
1507 traducer[conn[j]]=1;
1510 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1511 throw INTERP_KERNEL::Exception(oss.str().c_str());
1514 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1515 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1520 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1521 * For each cell in \b this the number of nodes constituting cell is computed.
1522 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1523 * So for pohyhedrons some nodes can be counted several times in the returned result.
1525 * \return a newly allocated array
1526 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1528 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1530 checkConnectivityFullyDefined();
1531 int nbOfCells=getNumberOfCells();
1532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1533 ret->alloc(nbOfCells,1);
1534 int *retPtr=ret->getPointer();
1535 const int *conn=getNodalConnectivity()->getConstPointer();
1536 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1537 for(int i=0;i<nbOfCells;i++,retPtr++)
1539 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1540 *retPtr=connI[i+1]-connI[i]-1;
1542 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1548 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1549 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1551 * \return DataArrayInt * - new object to be deallocated by the caller.
1552 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1554 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1556 checkConnectivityFullyDefined();
1557 int nbOfCells=getNumberOfCells();
1558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1559 ret->alloc(nbOfCells,1);
1560 int *retPtr=ret->getPointer();
1561 const int *conn=getNodalConnectivity()->getConstPointer();
1562 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1563 for(int i=0;i<nbOfCells;i++,retPtr++)
1565 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1566 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1567 *retPtr=(int)s.size();
1571 *retPtr=(int)s.size();
1578 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1579 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1581 * \return a newly allocated array
1583 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1585 checkConnectivityFullyDefined();
1586 int nbOfCells=getNumberOfCells();
1587 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1588 ret->alloc(nbOfCells,1);
1589 int *retPtr=ret->getPointer();
1590 const int *conn=getNodalConnectivity()->getConstPointer();
1591 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1592 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1594 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1595 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1601 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1602 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1603 * array mean that the corresponding old node is no more used.
1604 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1605 * this->getNumberOfNodes() before call of this method. The caller is to
1606 * delete this array using decrRef() as it is no more needed.
1607 * \throw If the coordinates array is not set.
1608 * \throw If the nodal connectivity of cells is not defined.
1609 * \throw If the nodal connectivity includes an invalid id.
1610 * \sa areAllNodesFetched
1612 * \if ENABLE_EXAMPLES
1613 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1614 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1617 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1619 return MEDCouplingPointSet::zipCoordsTraducer();
1623 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1624 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1626 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1631 return AreCellsEqual0(conn,connI,cell1,cell2);
1633 return AreCellsEqual1(conn,connI,cell1,cell2);
1635 return AreCellsEqual2(conn,connI,cell1,cell2);
1637 return AreCellsEqual3(conn,connI,cell1,cell2);
1639 return AreCellsEqual7(conn,connI,cell1,cell2);
1641 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1645 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1647 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1649 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1650 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1655 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1657 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1659 int sz=connI[cell1+1]-connI[cell1];
1660 if(sz==connI[cell2+1]-connI[cell2])
1662 if(conn[connI[cell1]]==conn[connI[cell2]])
1664 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1665 unsigned dim=cm.getDimension();
1671 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1672 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1673 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1674 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1675 return work!=tmp+sz1?1:0;
1678 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1681 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1688 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1690 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1692 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1694 if(conn[connI[cell1]]==conn[connI[cell2]])
1696 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1697 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1705 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1707 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1709 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1711 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1712 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1719 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1721 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1723 int sz=connI[cell1+1]-connI[cell1];
1724 if(sz==connI[cell2+1]-connI[cell2])
1726 if(conn[connI[cell1]]==conn[connI[cell2]])
1728 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1729 unsigned dim=cm.getDimension();
1735 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1736 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1737 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1738 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1743 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1744 std::reverse_iterator<int *> it2((int *)tmp);
1745 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1751 return work!=tmp+sz1?1:0;
1754 {//case of SEG2 and SEG3
1755 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1757 if(!cm.isQuadratic())
1759 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1760 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1761 if(std::equal(it1,it2,conn+connI[cell2]+1))
1767 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])
1774 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1781 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1782 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1783 * and result remains unchanged.
1784 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1785 * If in 'candidates' pool -1 value is considered as an empty value.
1786 * WARNING this method returns only ONE set of result !
1788 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1790 if(candidates.size()<1)
1793 std::vector<int>::const_iterator iter=candidates.begin();
1794 int start=(*iter++);
1795 for(;iter!=candidates.end();iter++)
1797 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1802 result->pushBackSilent(start);
1806 result->pushBackSilent(*iter);
1808 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1815 * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1817 * This method keeps the coordiantes of \a this. This method is time consuming.
1819 * \param [in] compType input specifying the technique used to compare cells each other.
1820 * - 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.
1821 * - 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)
1822 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1823 * - 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
1824 * can be used for users not sensitive to orientation of cell
1825 * \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.
1826 * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1827 * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1828 * \return the correspondance array old to new in a newly allocated array.
1831 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1834 getReverseNodalConnectivity(revNodal,revNodalI);
1835 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1838 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1839 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1842 int nbOfCells=nodalI->getNumberOfTuples()-1;
1843 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1844 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1845 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1846 std::vector<bool> isFetched(nbOfCells,false);
1849 for(int i=0;i<nbOfCells;i++)
1853 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1854 std::vector<int> v,v2;
1855 if(connOfNode!=connPtr+connIPtr[i+1])
1857 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1858 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1861 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1865 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1866 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1867 v2.resize(std::distance(v2.begin(),it));
1871 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1873 int pos=commonCellsI->back();
1874 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1875 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1876 isFetched[*it]=true;
1884 for(int i=startCellId;i<nbOfCells;i++)
1888 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1889 std::vector<int> v,v2;
1890 if(connOfNode!=connPtr+connIPtr[i+1])
1892 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1895 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1899 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1900 v2.resize(std::distance(v2.begin(),it));
1904 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1906 int pos=commonCellsI->back();
1907 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1908 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1909 isFetched[*it]=true;
1915 commonCellsArr=commonCells.retn();
1916 commonCellsIArr=commonCellsI.retn();
1920 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1921 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1922 * than \a other->getNumberOfCells() in the returned array means that there is no
1923 * corresponding cell in \a this mesh.
1924 * It is expected that \a this and \a other meshes share the same node coordinates
1925 * array, if it is not so an exception is thrown.
1926 * \param [in] other - the mesh to compare with.
1927 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1928 * valid values [0,1,2], see zipConnectivityTraducer().
1929 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1930 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1931 * values. The caller is to delete this array using
1932 * decrRef() as it is no more needed.
1933 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1936 * \if ENABLE_EXAMPLES
1937 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1938 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1940 * \sa checkDeepEquivalOnSameNodesWith()
1941 * \sa checkGeoEquivalWith()
1943 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1945 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946 int nbOfCells=getNumberOfCells();
1947 static const int possibleCompType[]={0,1,2};
1948 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1950 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1951 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1953 throw INTERP_KERNEL::Exception(oss.str().c_str());
1955 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1956 arr=o2n->substr(nbOfCells);
1957 arr->setName(other->getName());
1959 if(other->getNumberOfCells()==0)
1961 return arr->getMaxValue(tmp)<nbOfCells;
1965 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1966 * This method tries to determine if \b other is fully included in \b this.
1967 * The main difference is that this method is not expected to throw exception.
1968 * This method has two outputs :
1970 * \param other other mesh
1971 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1972 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1974 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1976 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1977 DataArrayInt *commonCells=0,*commonCellsI=0;
1978 int thisNbCells=getNumberOfCells();
1979 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1981 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1982 int otherNbCells=other->getNumberOfCells();
1983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1984 arr2->alloc(otherNbCells,1);
1985 arr2->fillWithZero();
1986 int *arr2Ptr=arr2->getPointer();
1987 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1988 for(int i=0;i<nbOfCommon;i++)
1990 int start=commonCellsPtr[commonCellsIPtr[i]];
1991 if(start<thisNbCells)
1993 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1995 int sig=commonCellsPtr[j]>0?1:-1;
1996 int val=std::abs(commonCellsPtr[j])-1;
1997 if(val>=thisNbCells)
1998 arr2Ptr[val-thisNbCells]=sig*(start+1);
2002 arr2->setName(other->getName());
2003 if(arr2->presenceOfValue(0))
2009 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2013 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2016 std::vector<const MEDCouplingUMesh *> ms(2);
2019 return MergeUMeshesOnSameCoords(ms);
2023 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2024 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2025 * cellIds is not given explicitely but by a range python like.
2030 * \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.
2031 * \return a newly allocated
2033 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2034 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2036 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2038 if(getMeshDimension()!=-1)
2039 return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords));
2042 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2044 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2046 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2048 return const_cast<MEDCouplingUMesh *>(this);
2053 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2054 * The result mesh shares or not the node coordinates array with \a this mesh depending
2055 * on \a keepCoords parameter.
2056 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2057 * to write this mesh to the MED file, its cells must be sorted using
2058 * sortCellsInMEDFileFrmt().
2059 * \param [in] begin - an array of cell ids to include to the new mesh.
2060 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2061 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2062 * array of \a this mesh, else "free" nodes are removed from the result mesh
2063 * by calling zipCoords().
2064 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2065 * to delete this mesh using decrRef() as it is no more needed.
2066 * \throw If the coordinates array is not set.
2067 * \throw If the nodal connectivity of cells is not defined.
2068 * \throw If any cell id in the array \a begin is not valid.
2070 * \if ENABLE_EXAMPLES
2071 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2072 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2075 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2077 if(getMeshDimension()!=-1)
2078 return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2082 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2084 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2086 return const_cast<MEDCouplingUMesh *>(this);
2091 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2093 * 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.
2094 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2095 * The number of cells of \b this will remain the same with this method.
2097 * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2098 * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2099 * \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 ).
2100 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2102 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2104 checkConnectivityFullyDefined();
2105 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2106 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2107 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2108 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2110 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2111 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2112 throw INTERP_KERNEL::Exception(oss.str().c_str());
2114 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2115 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2117 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2118 throw INTERP_KERNEL::Exception(oss.str().c_str());
2120 int nbOfCells=getNumberOfCells();
2121 bool easyAssign=true;
2122 const int *connI=_nodal_connec_index->getConstPointer();
2123 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2124 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2126 if(*it>=0 && *it<nbOfCells)
2128 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2132 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2133 throw INTERP_KERNEL::Exception(oss.str().c_str());
2138 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2143 DataArrayInt *arrOut=0,*arrIOut=0;
2144 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2147 setConnectivity(arrOut,arrIOut,true);
2151 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2153 checkConnectivityFullyDefined();
2154 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2155 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2156 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2157 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2159 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2160 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2161 throw INTERP_KERNEL::Exception(oss.str().c_str());
2163 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2164 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2166 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2167 throw INTERP_KERNEL::Exception(oss.str().c_str());
2169 int nbOfCells=getNumberOfCells();
2170 bool easyAssign=true;
2171 const int *connI=_nodal_connec_index->getConstPointer();
2172 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2174 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2176 if(it>=0 && it<nbOfCells)
2178 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2182 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2183 throw INTERP_KERNEL::Exception(oss.str().c_str());
2188 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2193 DataArrayInt *arrOut=0,*arrIOut=0;
2194 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2196 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2197 setConnectivity(arrOut,arrIOut,true);
2202 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2203 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2204 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2205 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2207 * \param [in] begin input start of array of node ids.
2208 * \param [in] end input end of array of node ids.
2209 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2210 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2212 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2215 checkConnectivityFullyDefined();
2217 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2218 std::vector<bool> fastFinder(sz,false);
2219 for(const int *work=begin;work!=end;work++)
2220 if(*work>=0 && *work<sz)
2221 fastFinder[*work]=true;
2222 int nbOfCells=getNumberOfCells();
2223 const int *conn=getNodalConnectivity()->getConstPointer();
2224 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2225 for(int i=0;i<nbOfCells;i++)
2227 int ref=0,nbOfHit=0;
2228 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2232 if(fastFinder[*work2])
2235 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2236 cellIdsKept->pushBackSilent(i);
2238 cellIdsKeptArr=cellIdsKept.retn();
2242 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2243 * this->getMeshDimension(), that bound some cells of \a this mesh.
2244 * The cells of lower dimension to include to the result mesh are selected basing on
2245 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2246 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2247 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2248 * created mesh shares the node coordinates array with \a this mesh.
2249 * \param [in] begin - the array of node ids.
2250 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2251 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2252 * array \a begin are added, else cells whose any node is in the
2253 * array \a begin are added.
2254 * \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2255 * to delete this mesh using decrRef() as it is no more needed.
2256 * \throw If the coordinates array is not set.
2257 * \throw If the nodal connectivity of cells is not defined.
2258 * \throw If any node id in \a begin is not valid.
2260 * \if ENABLE_EXAMPLES
2261 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2262 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2265 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2268 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2269 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2270 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2271 return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2275 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2276 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2277 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2278 * array of \a this mesh, else "free" nodes are removed from the result mesh
2279 * by calling zipCoords().
2280 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2281 * to delete this mesh using decrRef() as it is no more needed.
2282 * \throw If the coordinates array is not set.
2283 * \throw If the nodal connectivity of cells is not defined.
2285 * \if ENABLE_EXAMPLES
2286 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2287 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2290 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2292 DataArrayInt *desc=DataArrayInt::New();
2293 DataArrayInt *descIndx=DataArrayInt::New();
2294 DataArrayInt *revDesc=DataArrayInt::New();
2295 DataArrayInt *revDescIndx=DataArrayInt::New();
2297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2300 descIndx->decrRef();
2301 int nbOfCells=meshDM1->getNumberOfCells();
2302 const int *revDescIndxC=revDescIndx->getConstPointer();
2303 std::vector<int> boundaryCells;
2304 for(int i=0;i<nbOfCells;i++)
2305 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2306 boundaryCells.push_back(i);
2307 revDescIndx->decrRef();
2308 MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2313 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2314 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2315 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2317 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2319 checkFullyDefined();
2320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2325 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2326 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2330 const int *revDescPtr=revDesc->getConstPointer();
2331 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2332 int nbOfCells=getNumberOfCells();
2333 std::vector<bool> ret1(nbOfCells,false);
2335 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2336 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2337 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2339 DataArrayInt *ret2=DataArrayInt::New();
2341 int *ret2Ptr=ret2->getPointer();
2343 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2346 ret2->setName("BoundaryCells");
2351 * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2352 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2353 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2354 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2356 * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2357 * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2358 * equals a cell in \b otherDimM1OnSameCoords.
2360 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2361 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2363 * \param [in] otherDimM1OnSameCoords
2364 * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2365 * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2366 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2368 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2370 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2371 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2372 checkConnectivityFullyDefined();
2373 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2374 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2375 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2378 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2380 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2381 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2382 DataArrayInt *idsOtherInConsti=0;
2383 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2386 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2388 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2389 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2391 s1arr_renum1->sort();
2392 cellIdsRk0=s0arr.retn();
2393 //cellIdsRk1=s_renum1.retn();
2394 cellIdsRk1=s1arr_renum1.retn();
2398 * 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
2399 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2401 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2403 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2410 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2411 revDesc=0; desc=0; descIndx=0;
2412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2414 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2418 * Finds nodes lying on the boundary of \a this mesh.
2419 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2420 * nodes. The caller is to delete this array using decrRef() as it is no
2422 * \throw If the coordinates array is not set.
2423 * \throw If the nodal connectivity of cells is node defined.
2425 * \if ENABLE_EXAMPLES
2426 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2427 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2430 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2432 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2433 return skin->computeFetchedNodeIds();
2436 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2439 return const_cast<MEDCouplingUMesh *>(this);
2443 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2444 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2445 * 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.
2446 * 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.
2447 * 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.
2449 * \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
2450 * parameter is altered during the call.
2451 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2452 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2453 * \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.
2455 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2457 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2458 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2460 typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2462 checkFullyDefined();
2463 otherDimM1OnSameCoords.checkFullyDefined();
2464 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2466 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2468 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2469 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2470 DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2471 DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2472 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2473 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2474 DAInt s1=m0Part->computeFetchedNodeIds();
2475 DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2476 DAInt s3=s2->buildSubstraction(s1);
2477 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2479 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2480 int nCells2 = m0Part2->getNumberOfCells();
2481 DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2482 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2483 // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2484 DataArrayInt *tmp00=0,*tmp11=0;
2485 MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2486 DAInt neighInit00(tmp00);
2487 DAInt neighIInit00(tmp11);
2488 // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2489 DataArrayInt *idsTmp=0;
2490 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2493 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2494 // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2495 // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2496 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2497 DataArrayInt *tmp0=0,*tmp1=0;
2498 // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2499 // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2500 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2501 DAInt neigh00(tmp0);
2502 DAInt neighI00(tmp1);
2504 // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2505 int seed = 0, nIter = 0;
2506 int nIterMax = nCells2+1; // Safety net for the loop
2507 DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2508 hitCells->fillWithValue(-1);
2509 DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2510 cellsToModifyConn0_torenum->alloc(0,1);
2511 while (nIter < nIterMax)
2513 DAInt t = hitCells->getIdsEqual(-1);
2514 if (!t->getNumberOfTuples())
2516 // Connex zone without the crack (to compute the next seed really)
2518 DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2520 for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2521 hitCells->setIJ(*ptr,0,1);
2522 // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2523 DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2524 cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2525 // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2526 DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2527 DAInt nonHitCells = hitCells->getIdsEqual(-1);
2528 DAInt intersec = nonHitCells->buildIntersection(comple);
2529 if (intersec->getNumberOfTuples())
2530 { seed = intersec->getIJ(0,0); }
2535 if (nIter >= nIterMax)
2536 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2538 DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2539 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2540 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2542 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2543 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2544 nodeIdsToDuplicate=s3.retn();
2548 * This method operates a modification of the connectivity and coords in \b this.
2549 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2550 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2551 * 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
2552 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2553 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2555 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2557 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2558 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2560 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2562 int nbOfNodes=getNumberOfNodes();
2563 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2564 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2568 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2569 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2571 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2573 * \sa renumberNodesInConn
2575 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2577 checkConnectivityFullyDefined();
2578 int *conn(getNodalConnectivity()->getPointer());
2579 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2580 int nbOfCells(getNumberOfCells());
2581 for(int i=0;i<nbOfCells;i++)
2582 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2584 int& node=conn[iconn];
2585 if(node>=0)//avoid polyhedron separator
2590 _nodal_connec->declareAsNew();
2595 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2596 * 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
2599 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2601 checkConnectivityFullyDefined();
2602 int *conn(getNodalConnectivity()->getPointer());
2603 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2604 int nbOfCells(getNumberOfCells());
2605 for(int i=0;i<nbOfCells;i++)
2606 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2608 int& node=conn[iconn];
2609 if(node>=0)//avoid polyhedron separator
2611 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2612 if(it!=newNodeNumbersO2N.end())
2618 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2619 throw INTERP_KERNEL::Exception(oss.str().c_str());
2623 _nodal_connec->declareAsNew();
2628 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2629 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2630 * This method is a generalization of shiftNodeNumbersInConn().
2631 * \warning This method performs no check of validity of new ids. **Use it with care !**
2632 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2633 * this->getNumberOfNodes(), in "Old to New" mode.
2634 * See \ref numbering for more info on renumbering modes.
2635 * \throw If the nodal connectivity of cells is not defined.
2637 * \if ENABLE_EXAMPLES
2638 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2639 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2642 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2644 checkConnectivityFullyDefined();
2645 int *conn=getNodalConnectivity()->getPointer();
2646 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2647 int nbOfCells(getNumberOfCells());
2648 for(int i=0;i<nbOfCells;i++)
2649 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2651 int& node=conn[iconn];
2652 if(node>=0)//avoid polyhedron separator
2654 node=newNodeNumbersO2N[node];
2657 _nodal_connec->declareAsNew();
2662 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2663 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2664 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2666 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2668 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2670 checkConnectivityFullyDefined();
2671 int *conn=getNodalConnectivity()->getPointer();
2672 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2673 int nbOfCells=getNumberOfCells();
2674 for(int i=0;i<nbOfCells;i++)
2675 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2677 int& node=conn[iconn];
2678 if(node>=0)//avoid polyhedron separator
2683 _nodal_connec->declareAsNew();
2688 * This method operates a modification of the connectivity in \b this.
2689 * 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.
2690 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2691 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2692 * 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
2693 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2694 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2696 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2697 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2699 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2700 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2701 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2703 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2705 checkConnectivityFullyDefined();
2706 std::map<int,int> m;
2708 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2710 int *conn=getNodalConnectivity()->getPointer();
2711 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2712 int nbOfCells=getNumberOfCells();
2713 for(int i=0;i<nbOfCells;i++)
2714 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2716 int& node=conn[iconn];
2717 if(node>=0)//avoid polyhedron separator
2719 std::map<int,int>::iterator it=m.find(node);
2728 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2730 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2731 * After the call of this method the number of cells remains the same as before.
2733 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2734 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2735 * be strictly in [0;this->getNumberOfCells()).
2737 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2738 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2739 * should be contained in[0;this->getNumberOfCells()).
2741 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2744 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2746 checkConnectivityFullyDefined();
2747 int nbCells=getNumberOfCells();
2748 const int *array=old2NewBg;
2750 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2752 const int *conn=_nodal_connec->getConstPointer();
2753 const int *connI=_nodal_connec_index->getConstPointer();
2754 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2756 const int *n2oPtr=n2o->begin();
2757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2758 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2759 newConn->copyStringInfoFrom(*_nodal_connec);
2760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2761 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2762 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2764 int *newC=newConn->getPointer();
2765 int *newCI=newConnI->getPointer();
2768 for(int i=0;i<nbCells;i++)
2771 int nbOfElts=connI[pos+1]-connI[pos];
2772 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2777 setConnectivity(newConn,newConnI);
2779 free(const_cast<int *>(array));
2783 * Finds cells whose bounding boxes intersect a given bounding box.
2784 * \param [in] bbox - an array defining the bounding box via coordinates of its
2785 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2787 * \param [in] eps - a factor used to increase size of the bounding box of cell
2788 * before comparing it with \a bbox. This factor is multiplied by the maximal
2789 * extent of the bounding box of cell to produce an addition to this bounding box.
2790 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2791 * cells. The caller is to delete this array using decrRef() as it is no more
2793 * \throw If the coordinates array is not set.
2794 * \throw If the nodal connectivity of cells is not defined.
2796 * \if ENABLE_EXAMPLES
2797 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2798 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2801 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2804 if(getMeshDimension()==-1)
2806 elems->pushBackSilent(0);
2807 return elems.retn();
2809 int dim=getSpaceDimension();
2810 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2811 const int* conn = getNodalConnectivity()->getConstPointer();
2812 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2813 const double* coords = getCoords()->getConstPointer();
2814 int nbOfCells=getNumberOfCells();
2815 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2817 for (int i=0; i<dim; i++)
2819 elem_bb[i*2]=std::numeric_limits<double>::max();
2820 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2823 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2825 int node= conn[inode];
2826 if(node>=0)//avoid polyhedron separator
2828 for (int idim=0; idim<dim; idim++)
2830 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2832 elem_bb[idim*2] = coords[node*dim+idim] ;
2834 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2836 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2841 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2842 elems->pushBackSilent(ielem);
2844 return elems.retn();
2848 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2849 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2850 * added in 'elems' parameter.
2852 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2854 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2855 if(getMeshDimension()==-1)
2857 elems->pushBackSilent(0);
2858 return elems.retn();
2860 int dim=getSpaceDimension();
2861 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2862 const int* conn = getNodalConnectivity()->getConstPointer();
2863 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2864 const double* coords = getCoords()->getConstPointer();
2865 int nbOfCells=getNumberOfCells();
2866 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2868 for (int i=0; i<dim; i++)
2870 elem_bb[i*2]=std::numeric_limits<double>::max();
2871 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2874 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2876 int node= conn[inode];
2877 if(node>=0)//avoid polyhedron separator
2879 for (int idim=0; idim<dim; idim++)
2881 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2883 elem_bb[idim*2] = coords[node*dim+idim] ;
2885 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2887 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2892 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2893 elems->pushBackSilent(ielem);
2895 return elems.retn();
2899 * Returns a type of a cell by its id.
2900 * \param [in] cellId - the id of the cell of interest.
2901 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2902 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2904 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2906 const int *ptI=_nodal_connec_index->getConstPointer();
2907 const int *pt=_nodal_connec->getConstPointer();
2908 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2909 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2912 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2913 throw INTERP_KERNEL::Exception(oss.str().c_str());
2918 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2919 * This method does not throw exception if geometric type \a type is not in \a this.
2920 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2921 * The coordinates array is not considered here.
2923 * \param [in] type the geometric type
2924 * \return cell ids in this having geometric type \a type.
2926 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2931 checkConnectivityFullyDefined();
2932 int nbCells=getNumberOfCells();
2933 int mdim=getMeshDimension();
2934 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2935 if(mdim!=(int)cm.getDimension())
2936 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2937 const int *ptI=_nodal_connec_index->getConstPointer();
2938 const int *pt=_nodal_connec->getConstPointer();
2939 for(int i=0;i<nbCells;i++)
2941 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2942 ret->pushBackSilent(i);
2948 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2950 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2952 const int *ptI=_nodal_connec_index->getConstPointer();
2953 const int *pt=_nodal_connec->getConstPointer();
2954 int nbOfCells=getNumberOfCells();
2956 for(int i=0;i<nbOfCells;i++)
2957 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2963 * Returns the nodal connectivity of a given cell.
2964 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2965 * all returned node ids can be used in getCoordinatesOfNode().
2966 * \param [in] cellId - an id of the cell of interest.
2967 * \param [in,out] conn - a vector where the node ids are appended. It is not
2968 * cleared before the appending.
2969 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2971 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2973 const int *ptI=_nodal_connec_index->getConstPointer();
2974 const int *pt=_nodal_connec->getConstPointer();
2975 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2980 std::string MEDCouplingUMesh::simpleRepr() const
2982 static const char msg0[]="No coordinates specified !";
2983 std::ostringstream ret;
2984 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2985 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2987 double tt=getTime(tmpp1,tmpp2);
2988 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2989 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2991 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2993 { ret << " Mesh dimension has not been set or is invalid !"; }
2996 const int spaceDim=getSpaceDimension();
2997 ret << spaceDim << "\nInfo attached on space dimension : ";
2998 for(int i=0;i<spaceDim;i++)
2999 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3003 ret << msg0 << "\n";
3004 ret << "Number of nodes : ";
3006 ret << getNumberOfNodes() << "\n";
3008 ret << msg0 << "\n";
3009 ret << "Number of cells : ";
3010 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3011 ret << getNumberOfCells() << "\n";
3013 ret << "No connectivity specified !" << "\n";
3014 ret << "Cell types present : ";
3015 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3017 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3018 ret << cm.getRepr() << " ";
3024 std::string MEDCouplingUMesh::advancedRepr() const
3026 std::ostringstream ret;
3027 ret << simpleRepr();
3028 ret << "\nCoordinates array : \n___________________\n\n";
3030 _coords->reprWithoutNameStream(ret);
3032 ret << "No array set !\n";
3033 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3034 reprConnectivityOfThisLL(ret);
3039 * This method returns a C++ code that is a dump of \a this.
3040 * This method will throw if this is not fully defined.
3042 std::string MEDCouplingUMesh::cppRepr() const
3044 static const char coordsName[]="coords";
3045 static const char connName[]="conn";
3046 static const char connIName[]="connI";
3047 checkFullyDefined();
3048 std::ostringstream ret; ret << "// coordinates" << std::endl;
3049 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3050 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3051 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3052 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3053 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3054 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3055 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3059 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3061 std::ostringstream ret;
3062 reprConnectivityOfThisLL(ret);
3067 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3068 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3069 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3072 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3073 * 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
3074 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3076 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3078 int mdim=getMeshDimension();
3080 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3081 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3082 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3083 bool needToCpyCT=true;
3086 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3094 if(!_nodal_connec_index)
3096 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3101 tmp2=_nodal_connec_index;
3104 ret->setConnectivity(tmp1,tmp2,false);
3109 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3110 ret->setCoords(coords);
3113 ret->setCoords(_coords);
3117 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3119 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3121 int nbOfCells=getNumberOfCells();
3122 const int *c=_nodal_connec->getConstPointer();
3123 const int *ci=_nodal_connec_index->getConstPointer();
3124 for(int i=0;i<nbOfCells;i++)
3126 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3127 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3128 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3133 stream << "Connectivity not defined !\n";
3136 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3138 const int *ptI=_nodal_connec_index->getConstPointer();
3139 const int *pt=_nodal_connec->getConstPointer();
3140 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3141 return ptI[cellId+1]-ptI[cellId]-1;
3143 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3147 * Returns types of cells of the specified part of \a this mesh.
3148 * This method avoids computing sub-mesh explicitely to get its types.
3149 * \param [in] begin - an array of cell ids of interest.
3150 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3151 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3152 * describing the cell types.
3153 * \throw If the coordinates array is not set.
3154 * \throw If the nodal connectivity of cells is not defined.
3155 * \sa getAllGeoTypes()
3157 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3159 checkFullyDefined();
3160 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3161 const int *conn=_nodal_connec->getConstPointer();
3162 const int *connIndex=_nodal_connec_index->getConstPointer();
3163 for(const int *w=begin;w!=end;w++)
3164 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3169 * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3170 * Optionally updates
3171 * a set of types of cells constituting \a this mesh.
3172 * This method is for advanced users having prepared their connectivity before. For
3173 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3174 * \param [in] conn - the nodal connectivity array.
3175 * \param [in] connIndex - the nodal connectivity index array.
3176 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3179 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3181 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3182 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3183 if(isComputingTypes)
3189 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3190 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3192 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3193 _nodal_connec(0),_nodal_connec_index(0),
3194 _types(other._types)
3196 if(other._nodal_connec)
3197 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3198 if(other._nodal_connec_index)
3199 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3202 MEDCouplingUMesh::~MEDCouplingUMesh()
3205 _nodal_connec->decrRef();
3206 if(_nodal_connec_index)
3207 _nodal_connec_index->decrRef();
3211 * Recomputes a set of cell types of \a this mesh. For more info see
3212 * \ref MEDCouplingUMeshNodalConnectivity.
3214 void MEDCouplingUMesh::computeTypes()
3216 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3220 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3222 void MEDCouplingUMesh::checkFullyDefined() const
3224 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3225 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3229 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3231 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3233 if(!_nodal_connec_index || !_nodal_connec)
3234 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3238 * Returns a number of cells constituting \a this mesh.
3239 * \return int - the number of cells in \a this mesh.
3240 * \throw If the nodal connectivity of cells is not defined.
3242 int MEDCouplingUMesh::getNumberOfCells() const
3244 if(_nodal_connec_index)
3245 return _nodal_connec_index->getNumberOfTuples()-1;
3250 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3254 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3255 * mesh. For more info see \ref meshes.
3256 * \return int - the dimension of \a this mesh.
3257 * \throw If the mesh dimension is not defined using setMeshDimension().
3259 int MEDCouplingUMesh::getMeshDimension() const
3262 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3267 * Returns a length of the nodal connectivity array.
3268 * This method is for test reason. Normally the integer returned is not useable by
3269 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3270 * \return int - the length of the nodal connectivity array.
3272 int MEDCouplingUMesh::getMeshLength() const
3274 return _nodal_connec->getNbOfElems();
3278 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3280 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3282 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3283 tinyInfo.push_back(getMeshDimension());
3284 tinyInfo.push_back(getNumberOfCells());
3286 tinyInfo.push_back(getMeshLength());
3288 tinyInfo.push_back(-1);
3292 * First step of unserialization process.
3294 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3296 return tinyInfo[6]<=0;
3300 * Second step of serialization process.
3301 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3304 * \param littleStrings
3306 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3308 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3310 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3314 * Third and final step of serialization process.
3316 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3318 MEDCouplingPointSet::serialize(a1,a2);
3319 if(getMeshDimension()>-1)
3321 a1=DataArrayInt::New();
3322 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3323 int *ptA1=a1->getPointer();
3324 const int *conn=getNodalConnectivity()->getConstPointer();
3325 const int *index=getNodalConnectivityIndex()->getConstPointer();
3326 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3327 std::copy(conn,conn+getMeshLength(),ptA1);
3334 * Second and final unserialization process.
3335 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3337 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3339 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3340 setMeshDimension(tinyInfo[5]);
3344 const int *recvBuffer=a1->getConstPointer();
3345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3346 myConnecIndex->alloc(tinyInfo[6]+1,1);
3347 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3349 myConnec->alloc(tinyInfo[7],1);
3350 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3351 setConnectivity(myConnec, myConnecIndex);
3356 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3357 * CellIds are given using range specified by a start an end and step.
3359 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3361 checkFullyDefined();
3362 int ncell=getNumberOfCells();
3363 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3364 ret->_mesh_dim=_mesh_dim;
3365 ret->setCoords(_coords);
3366 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3368 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3370 const int *conn=_nodal_connec->getConstPointer();
3371 const int *connIndex=_nodal_connec_index->getConstPointer();
3372 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3374 if(work>=0 && work<ncell)
3376 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3380 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3381 throw INTERP_KERNEL::Exception(oss.str().c_str());
3384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3385 int *newConnPtr=newConn->getPointer();
3386 std::set<INTERP_KERNEL::NormalizedCellType> types;
3388 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3390 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3391 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3393 ret->setConnectivity(newConn,newConnI,false);
3395 ret->copyTinyInfoFrom(this);
3400 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3401 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3402 * The return newly allocated mesh will share the same coordinates as \a this.
3404 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3406 checkConnectivityFullyDefined();
3407 int ncell=getNumberOfCells();
3408 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3409 ret->_mesh_dim=_mesh_dim;
3410 ret->setCoords(_coords);
3411 std::size_t nbOfElemsRet=std::distance(begin,end);
3412 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3414 const int *conn=_nodal_connec->getConstPointer();
3415 const int *connIndex=_nodal_connec_index->getConstPointer();
3417 for(const int *work=begin;work!=end;work++,newNbring++)
3419 if(*work>=0 && *work<ncell)
3420 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3424 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3425 throw INTERP_KERNEL::Exception(oss.str().c_str());
3428 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3429 int *connRetWork=connRet;
3430 std::set<INTERP_KERNEL::NormalizedCellType> types;
3431 for(const int *work=begin;work!=end;work++)
3433 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3434 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3436 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3437 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3438 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3439 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3440 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3442 ret->copyTinyInfoFrom(this);
3447 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3449 * For 1D cells, the returned field contains lengths.<br>
3450 * For 2D cells, the returned field contains areas.<br>
3451 * For 3D cells, the returned field contains volumes.
3452 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3453 * orientation, i.e. the volume is always positive.
3454 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3455 * and one time . The caller is to delete this field using decrRef() as it is no
3458 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3460 std::string name="MeasureOfMesh_";
3462 int nbelem=getNumberOfCells();
3463 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3464 field->setName(name);
3465 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3466 array->alloc(nbelem,1);
3467 double *area_vol=array->getPointer();
3468 field->setArray(array) ; array=0;
3469 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3470 field->synchronizeTimeWithMesh();
3471 if(getMeshDimension()!=-1)
3474 INTERP_KERNEL::NormalizedCellType type;
3475 int dim_space=getSpaceDimension();
3476 const double *coords=getCoords()->getConstPointer();
3477 const int *connec=getNodalConnectivity()->getConstPointer();
3478 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3479 for(int iel=0;iel<nbelem;iel++)
3481 ipt=connec_index[iel];
3482 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3483 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);
3486 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3490 area_vol[0]=std::numeric_limits<double>::max();
3492 return field.retn();
3496 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3498 * For 1D cells, the returned array contains lengths.<br>
3499 * For 2D cells, the returned array contains areas.<br>
3500 * For 3D cells, the returned array contains volumes.
3501 * This method avoids building explicitly a part of \a this mesh to perform the work.
3502 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3503 * orientation, i.e. the volume is always positive.
3504 * \param [in] begin - an array of cell ids of interest.
3505 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3506 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3507 * delete this array using decrRef() as it is no more needed.
3509 * \if ENABLE_EXAMPLES
3510 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3511 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3513 * \sa getMeasureField()
3515 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3517 std::string name="PartMeasureOfMesh_";
3519 int nbelem=(int)std::distance(begin,end);
3520 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3521 array->setName(name);
3522 array->alloc(nbelem,1);
3523 double *area_vol=array->getPointer();
3524 if(getMeshDimension()!=-1)
3527 INTERP_KERNEL::NormalizedCellType type;
3528 int dim_space=getSpaceDimension();
3529 const double *coords=getCoords()->getConstPointer();
3530 const int *connec=getNodalConnectivity()->getConstPointer();
3531 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3532 for(const int *iel=begin;iel!=end;iel++)
3534 ipt=connec_index[*iel];
3535 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3536 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3539 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3543 area_vol[0]=std::numeric_limits<double>::max();
3545 return array.retn();
3549 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3550 * \a this one. The returned field contains the dual cell volume for each corresponding
3551 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3552 * the dual mesh in P1 sens of \a this.<br>
3553 * For 1D cells, the returned field contains lengths.<br>
3554 * For 2D cells, the returned field contains areas.<br>
3555 * For 3D cells, the returned field contains volumes.
3556 * This method is useful to check "P1*" conservative interpolators.
3557 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3558 * orientation, i.e. the volume is always positive.
3559 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3560 * nodes and one time. The caller is to delete this array using decrRef() as
3561 * it is no more needed.
3563 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3565 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3566 std::string name="MeasureOnNodeOfMesh_";
3568 int nbNodes=getNumberOfNodes();
3569 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3570 double cst=1./((double)getMeshDimension()+1.);
3571 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3572 array->alloc(nbNodes,1);
3573 double *valsToFill=array->getPointer();
3574 std::fill(valsToFill,valsToFill+nbNodes,0.);
3575 const double *values=tmp->getArray()->getConstPointer();
3576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3577 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3578 getReverseNodalConnectivity(da,daInd);
3579 const int *daPtr=da->getConstPointer();
3580 const int *daIPtr=daInd->getConstPointer();
3581 for(int i=0;i<nbNodes;i++)
3582 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3583 valsToFill[i]+=cst*values[*cell];
3585 ret->setArray(array);
3590 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3591 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3592 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3593 * and are normalized.
3594 * <br> \a this can be either
3595 * - a 2D mesh in 2D or 3D space or
3596 * - an 1D mesh in 2D space.
3598 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3599 * cells and one time. The caller is to delete this field using decrRef() as
3600 * it is no more needed.
3601 * \throw If the nodal connectivity of cells is not defined.
3602 * \throw If the coordinates array is not set.
3603 * \throw If the mesh dimension is not set.
3604 * \throw If the mesh and space dimension is not as specified above.
3606 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3608 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3609 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3610 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3611 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3612 int nbOfCells=getNumberOfCells();
3613 int nbComp=getMeshDimension()+1;
3614 array->alloc(nbOfCells,nbComp);
3615 double *vals=array->getPointer();
3616 const int *connI=_nodal_connec_index->getConstPointer();
3617 const int *conn=_nodal_connec->getConstPointer();
3618 const double *coords=_coords->getConstPointer();
3619 if(getMeshDimension()==2)
3621 if(getSpaceDimension()==3)
3623 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3624 const double *locPtr=loc->getConstPointer();
3625 for(int i=0;i<nbOfCells;i++,vals+=3)
3627 int offset=connI[i];
3628 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3629 double n=INTERP_KERNEL::norm<3>(vals);
3630 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3635 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3636 const double *isAbsPtr=isAbs->getArray()->begin();
3637 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3638 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3641 else//meshdimension==1
3644 for(int i=0;i<nbOfCells;i++)
3646 int offset=connI[i];
3647 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3648 double n=INTERP_KERNEL::norm<2>(tmp);
3649 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3654 ret->setArray(array);
3656 ret->synchronizeTimeWithSupport();
3661 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3662 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3663 * and are normalized.
3664 * <br> \a this can be either
3665 * - a 2D mesh in 2D or 3D space or
3666 * - an 1D mesh in 2D space.
3668 * This method avoids building explicitly a part of \a this mesh to perform the work.
3669 * \param [in] begin - an array of cell ids of interest.
3670 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3671 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3672 * cells and one time. The caller is to delete this field using decrRef() as
3673 * it is no more needed.
3674 * \throw If the nodal connectivity of cells is not defined.
3675 * \throw If the coordinates array is not set.
3676 * \throw If the mesh dimension is not set.
3677 * \throw If the mesh and space dimension is not as specified above.
3678 * \sa buildOrthogonalField()
3680 * \if ENABLE_EXAMPLES
3681 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3682 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3685 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3687 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3688 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3689 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3690 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3691 std::size_t nbelems=std::distance(begin,end);
3692 int nbComp=getMeshDimension()+1;
3693 array->alloc((int)nbelems,nbComp);
3694 double *vals=array->getPointer();
3695 const int *connI=_nodal_connec_index->getConstPointer();
3696 const int *conn=_nodal_connec->getConstPointer();
3697 const double *coords=_coords->getConstPointer();
3698 if(getMeshDimension()==2)
3700 if(getSpaceDimension()==3)
3702 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3703 const double *locPtr=loc->getConstPointer();
3704 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3706 int offset=connI[*i];
3707 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3708 double n=INTERP_KERNEL::norm<3>(vals);
3709 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3714 for(std::size_t i=0;i<nbelems;i++)
3715 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3718 else//meshdimension==1
3721 for(const int *i=begin;i!=end;i++)
3723 int offset=connI[*i];
3724 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3725 double n=INTERP_KERNEL::norm<2>(tmp);
3726 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3731 ret->setArray(array);
3733 ret->synchronizeTimeWithSupport();
3738 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3739 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3740 * and are \b not normalized.
3741 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3742 * cells and one time. The caller is to delete this field using decrRef() as
3743 * it is no more needed.
3744 * \throw If the nodal connectivity of cells is not defined.
3745 * \throw If the coordinates array is not set.
3746 * \throw If \a this->getMeshDimension() != 1.
3747 * \throw If \a this mesh includes cells of type other than SEG2.
3749 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3751 if(getMeshDimension()!=1)
3752 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3753 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3754 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3755 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3756 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3757 int nbOfCells=getNumberOfCells();
3758 int spaceDim=getSpaceDimension();
3759 array->alloc(nbOfCells,spaceDim);
3760 double *pt=array->getPointer();
3761 const double *coo=getCoords()->getConstPointer();
3762 std::vector<int> conn;
3764 for(int i=0;i<nbOfCells;i++)
3767 getNodeIdsOfCell(i,conn);
3768 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3770 ret->setArray(array);
3772 ret->synchronizeTimeWithSupport();
3777 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3778 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3779 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3780 * from. If a result face is shared by two 3D cells, then the face in included twice in
3782 * \param [in] origin - 3 components of a point defining location of the plane.
3783 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3784 * must be greater than 1e-6.
3785 * \param [in] eps - half-thickness of the plane.
3786 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3787 * producing correspondent 2D cells. The caller is to delete this array
3788 * using decrRef() as it is no more needed.
3789 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3790 * not share the node coordinates array with \a this mesh. The caller is to
3791 * delete this mesh using decrRef() as it is no more needed.
3792 * \throw If the coordinates array is not set.
3793 * \throw If the nodal connectivity of cells is not defined.
3794 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3795 * \throw If magnitude of \a vec is less than 1e-6.
3796 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3797 * \throw If \a this includes quadratic cells.
3799 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3801 checkFullyDefined();
3802 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3803 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3804 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3805 if(candidates->empty())
3806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3807 std::vector<int> nodes;
3808 DataArrayInt *cellIds1D=0;
3809 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3810 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3815 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3816 revDesc2=0; revDescIndx2=0;
3817 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3818 revDesc1=0; revDescIndx1=0;
3819 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3822 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3823 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3825 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3826 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3827 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3828 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3829 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3831 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3832 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3833 if(cellIds2->empty())
3834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3835 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3836 ret->setCoords(mDesc1->getCoords());
3837 ret->setConnectivity(conn,connI,true);
3838 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3843 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3844 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
3845 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3847 * \param [in] origin - 3 components of a point defining location of the plane.
3848 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3849 * must be greater than 1e-6.
3850 * \param [in] eps - half-thickness of the plane.
3851 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3852 * producing correspondent segments. The caller is to delete this array
3853 * using decrRef() as it is no more needed.
3854 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3855 * mesh in 3D space. This mesh does not share the node coordinates array with
3856 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3858 * \throw If the coordinates array is not set.
3859 * \throw If the nodal connectivity of cells is not defined.
3860 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3861 * \throw If magnitude of \a vec is less than 1e-6.
3862 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3863 * \throw If \a this includes quadratic cells.
3865 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3867 checkFullyDefined();
3868 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3869 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3871 if(candidates->empty())
3872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3873 std::vector<int> nodes;
3874 DataArrayInt *cellIds1D=0;
3875 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3876 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3881 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3882 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3885 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3886 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3888 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3889 int ncellsSub=subMesh->getNumberOfCells();
3890 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3891 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3892 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3893 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3896 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3897 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3898 for(int i=0;i<ncellsSub;i++)
3900 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3902 if(cut3DSurf[i].first!=-2)
3904 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3905 connI->pushBackSilent(conn->getNumberOfTuples());
3906 cellIds2->pushBackSilent(i);
3910 int cellId3DSurf=cut3DSurf[i].second;
3911 int offset=nodalI[cellId3DSurf]+1;
3912 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3913 for(int j=0;j<nbOfEdges;j++)
3915 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3916 connI->pushBackSilent(conn->getNumberOfTuples());
3917 cellIds2->pushBackSilent(cellId3DSurf);
3922 if(cellIds2->empty())
3923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3924 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3925 ret->setCoords(mDesc1->getCoords());
3926 ret->setConnectivity(conn,connI,true);
3927 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3932 * Finds cells whose bounding boxes intersect a given plane.
3933 * \param [in] origin - 3 components of a point defining location of the plane.
3934 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3935 * must be greater than 1e-6.
3936 * \param [in] eps - half-thickness of the plane.
3937 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3938 * cells. The caller is to delete this array using decrRef() as it is no more
3940 * \throw If the coordinates array is not set.
3941 * \throw If the nodal connectivity of cells is not defined.
3942 * \throw If \a this->getSpaceDimension() != 3.
3943 * \throw If magnitude of \a vec is less than 1e-6.
3944 * \sa buildSlice3D()
3946 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3948 checkFullyDefined();
3949 if(getSpaceDimension()!=3)
3950 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3951 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3953 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3955 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3956 double angle=acos(vec[2]/normm);
3957 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3961 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3962 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3963 if(normm2/normm>1e-6)
3964 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3965 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3967 mw->getBoundingBox(bbox);
3968 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3969 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3973 getBoundingBox(bbox);
3974 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3975 cellIds=getCellsInBoundingBox(bbox,eps);
3977 return cellIds.retn();
3981 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3982 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3983 * No consideration of coordinate is done by this method.
3984 * 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)
3985 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3987 bool MEDCouplingUMesh::isContiguous1D() const
3989 if(getMeshDimension()!=1)
3990 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3991 int nbCells=getNumberOfCells();
3993 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3994 const int *connI=_nodal_connec_index->getConstPointer();
3995 const int *conn=_nodal_connec->getConstPointer();
3996 int ref=conn[connI[0]+2];
3997 for(int i=1;i<nbCells;i++)
3999 if(conn[connI[i]+1]!=ref)
4001 ref=conn[connI[i]+2];
4007 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4008 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4009 * \param pt reference point of the line
4010 * \param v normalized director vector of the line
4011 * \param eps max precision before throwing an exception
4012 * \param res output of size this->getNumberOfCells
4014 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4016 if(getMeshDimension()!=1)
4017 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4018 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4019 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4020 if(getSpaceDimension()!=3)
4021 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4022 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4023 const double *fPtr=f->getArray()->getConstPointer();
4025 for(int i=0;i<getNumberOfCells();i++)
4027 const double *tmp1=fPtr+3*i;
4028 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4029 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4030 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4031 double n1=INTERP_KERNEL::norm<3>(tmp);
4032 n1/=INTERP_KERNEL::norm<3>(tmp1);
4034 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4036 const double *coo=getCoords()->getConstPointer();
4037 for(int i=0;i<getNumberOfNodes();i++)
4039 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4040 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4041 res[i]=std::accumulate(tmp,tmp+3,0.);
4046 * 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.
4047 * \a this is expected to be a mesh so that its space dimension is equal to its
4048 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4049 * 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).
4051 * 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
4052 * 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).
4053 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4055 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4056 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4058 * \param [in] ptBg the start pointer (included) of the coordinates of the point
4059 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4060 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4061 * \return the positive value of the distance.
4062 * \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
4064 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4066 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4068 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4069 if(meshDim!=spaceDim-1)
4070 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4071 if(meshDim!=2 && meshDim!=1)
4072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4073 checkFullyDefined();
4074 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4075 { 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()); }
4076 DataArrayInt *ret1=0;
4077 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4078 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4080 cellId=*ret1Safe->begin();
4081 return *ret0->begin();
4085 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4086 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4087 * 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
4088 * 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).
4089 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4091 * \a this is expected to be a mesh so that its space dimension is equal to its
4092 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4093 * 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).
4095 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4096 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4098 * \param [in] pts the list of points in which each tuple represents a point
4099 * \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.
4100 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4101 * \throw if number of components of \a pts is not equal to the space dimension.
4102 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4103 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4105 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4108 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4109 pts->checkAllocated();
4110 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4111 if(meshDim!=spaceDim-1)
4112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4113 if(meshDim!=2 && meshDim!=1)
4114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4115 if(pts->getNumberOfComponents()!=spaceDim)
4117 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4118 throw INTERP_KERNEL::Exception(oss.str().c_str());
4120 checkFullyDefined();
4121 int nbCells=getNumberOfCells();
4123 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4124 int nbOfPts=pts->getNumberOfTuples();
4125 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4127 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4128 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4129 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4130 const double *bbox(bboxArr->begin());
4135 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4136 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4138 double x=std::numeric_limits<double>::max();
4139 std::vector<int> elems;
4140 myTree.getMinDistanceOfMax(ptsPtr,x);
4141 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4142 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4148 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4149 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4151 double x=std::numeric_limits<double>::max();
4152 std::vector<int> elems;
4153 myTree.getMinDistanceOfMax(ptsPtr,x);
4154 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4155 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4160 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4162 cellIds=ret1.retn();
4169 * \param [in] pt the start pointer (included) of the coordinates of the point
4170 * \param [in] cellIdsBg the start pointer (included) of cellIds
4171 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4172 * \param [in] nc nodal connectivity
4173 * \param [in] ncI nodal connectivity index
4174 * \param [in,out] ret0 the min distance between \a this and the external input point
4175 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4176 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4178 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)
4181 ret0=std::numeric_limits<double>::max();
4182 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4184 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4186 case INTERP_KERNEL::NORM_TRI3:
4188 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4190 { ret0=tmp; cellId=*zeCell; }
4193 case INTERP_KERNEL::NORM_QUAD4:
4194 case INTERP_KERNEL::NORM_POLYGON:
4196 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4198 { ret0=tmp; cellId=*zeCell; }
4202 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4208 * \param [in] pt the start pointer (included) of the coordinates of the point
4209 * \param [in] cellIdsBg the start pointer (included) of cellIds
4210 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4211 * \param [in] nc nodal connectivity
4212 * \param [in] ncI nodal connectivity index
4213 * \param [in,out] ret0 the min distance between \a this and the external input point
4214 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4215 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4217 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)
4220 ret0=std::numeric_limits<double>::max();
4221 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4223 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4225 case INTERP_KERNEL::NORM_SEG2:
4227 std::size_t uselessEntry=0;
4228 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4231 { ret0=tmp; cellId=*zeCell; }
4235 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4242 * Finds cells in contact with a ball (i.e. a point with precision).
4243 * 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.
4244 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4246 * \warning This method is suitable if the caller intends to evaluate only one
4247 * point, for more points getCellsContainingPoints() is recommended as it is
4249 * \param [in] pos - array of coordinates of the ball central point.
4250 * \param [in] eps - ball radius.
4251 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4252 * if there are no such cells.
4253 * \throw If the coordinates array is not set.
4254 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4256 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4258 std::vector<int> elts;
4259 getCellsContainingPoint(pos,eps,elts);
4262 return elts.front();
4266 * Finds cells in contact with a ball (i.e. a point with precision).
4267 * 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.
4268 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4269 * \warning This method is suitable if the caller intends to evaluate only one
4270 * point, for more points getCellsContainingPoints() is recommended as it is
4272 * \param [in] pos - array of coordinates of the ball central point.
4273 * \param [in] eps - ball radius.
4274 * \param [out] elts - vector returning ids of the found cells. It is cleared
4275 * before inserting ids.
4276 * \throw If the coordinates array is not set.
4277 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4279 * \if ENABLE_EXAMPLES
4280 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4281 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4284 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4287 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4288 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4293 namespace ParaMEDMEM
4295 template<const int SPACEDIMM>
4299 static const int MY_SPACEDIM=SPACEDIMM;
4300 static const int MY_MESHDIM=8;
4301 typedef int MyConnType;
4302 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4304 // useless, but for windows compilation ...
4305 const double* getCoordinatesPtr() const { return 0; }
4306 const int* getConnectivityPtr() const { return 0; }
4307 const int* getConnectivityIndexPtr() const { return 0; }
4308 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4312 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4314 INTERP_KERNEL::Edge *ret(0);
4315 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]));
4316 m[n0]=bg[0]; m[n1]=bg[1];
4319 case INTERP_KERNEL::NORM_SEG2:
4321 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4324 case INTERP_KERNEL::NORM_SEG3:
4326 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4327 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4328 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4329 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4330 bool colinearity(inters.areColinears());
4331 delete e1; delete e2;
4333 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4335 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4339 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4344 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4346 INTERP_KERNEL::Edge *ret=0;
4349 case INTERP_KERNEL::NORM_SEG2:
4351 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4354 case INTERP_KERNEL::NORM_SEG3:
4356 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4357 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4358 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4359 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4360 bool colinearity=inters.areColinears();
4361 delete e1; delete e2;
4363 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4365 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4366 mapp2[bg[2]].second=false;
4370 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4376 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4377 * the global mesh 'mDesc'.
4378 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4379 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4381 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4382 std::map<INTERP_KERNEL::Node *,int>& mapp)
4385 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.
4386 const double *coo=mDesc->getCoords()->getConstPointer();
4387 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4388 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4390 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4391 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4392 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4394 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4395 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4397 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4398 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4400 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4401 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4403 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4405 if((*it2).second.second)
4406 mapp[(*it2).second.first]=(*it2).first;
4407 ((*it2).second.first)->decrRef();
4412 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4416 int locId=nodeId-offset2;
4417 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4421 int locId=nodeId-offset1;
4422 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4424 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4428 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4430 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4431 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4432 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4434 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4436 int eltId1=abs(*desc1)-1;
4437 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4439 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4440 if(it==mappRev.end())
4442 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4453 template<int SPACEDIM>
4454 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4455 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4457 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4458 int *eltsIndexPtr(eltsIndex->getPointer());
4459 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4460 const double *bbox(bboxArr->begin());
4461 int nbOfCells=getNumberOfCells();
4462 const int *conn=_nodal_connec->getConstPointer();
4463 const int *connI=_nodal_connec_index->getConstPointer();
4464 double bb[2*SPACEDIM];
4465 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4466 for(int i=0;i<nbOfPoints;i++)
4468 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4469 for(int j=0;j<SPACEDIM;j++)
4471 bb[2*j]=pos[SPACEDIM*i+j];
4472 bb[2*j+1]=pos[SPACEDIM*i+j];
4474 std::vector<int> candidates;
4475 myTree.getIntersectingElems(bb,candidates);
4476 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4478 int sz(connI[(*iter)+1]-connI[*iter]-1);
4479 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4481 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4482 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4486 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4487 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4488 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4489 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4490 INTERP_KERNEL::QuadraticPolygon *pol(0);
4491 for(int j=0;j<sz;j++)
4493 int nodeId(conn[connI[*iter]+1+j]);
4494 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4496 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4497 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4499 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4500 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4501 double a(0.),b(0.),c(0.);
4502 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4503 status=pol->isInOrOut2(n);
4504 delete pol; n->decrRef();
4508 eltsIndexPtr[i+1]++;
4509 elts->pushBackSilent(*iter);
4515 * Finds cells in contact with several balls (i.e. points with precision).
4516 * This method is an extension of getCellContainingPoint() and
4517 * getCellsContainingPoint() for the case of multiple points.
4518 * 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.
4519 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4520 * \param [in] pos - an array of coordinates of points in full interlace mode :
4521 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4522 * this->getSpaceDimension() * \a nbOfPoints
4523 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4524 * \param [in] eps - radius of balls (i.e. the precision).
4525 * \param [out] elts - vector returning ids of found cells.
4526 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4527 * dividing cell ids in \a elts into groups each referring to one
4528 * point. Its every element (except the last one) is an index pointing to the
4529 * first id of a group of cells. For example cells in contact with the *i*-th
4530 * point are described by following range of indices:
4531 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4532 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4533 * Number of cells in contact with the *i*-th point is
4534 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4535 * \throw If the coordinates array is not set.
4536 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4538 * \if ENABLE_EXAMPLES
4539 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4540 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4543 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4546 int spaceDim=getSpaceDimension();
4547 int mDim=getMeshDimension();
4552 const double *coords=_coords->getConstPointer();
4553 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4560 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4562 else if(spaceDim==2)
4566 const double *coords=_coords->getConstPointer();
4567 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4570 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4572 else if(spaceDim==1)
4576 const double *coords=_coords->getConstPointer();
4577 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4580 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4587 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4588 * least two its edges intersect each other anywhere except their extremities. An
4589 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4590 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4591 * cleared before filling in.
4592 * \param [in] eps - precision.
4593 * \throw If \a this->getMeshDimension() != 2.
4594 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4596 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4598 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4599 if(getMeshDimension()!=2)
4600 throw INTERP_KERNEL::Exception(msg);
4601 int spaceDim=getSpaceDimension();
4602 if(spaceDim!=2 && spaceDim!=3)
4603 throw INTERP_KERNEL::Exception(msg);
4604 const int *conn=_nodal_connec->getConstPointer();
4605 const int *connI=_nodal_connec_index->getConstPointer();
4606 int nbOfCells=getNumberOfCells();
4607 std::vector<double> cell2DinS2;
4608 for(int i=0;i<nbOfCells;i++)
4610 int offset=connI[i];
4611 int nbOfNodesForCell=connI[i+1]-offset-1;
4612 if(nbOfNodesForCell<=3)
4614 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4615 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4616 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4623 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4625 * 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.
4626 * 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.
4628 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4629 * This convex envelop is computed using Jarvis march algorithm.
4630 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4631 * 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)
4632 * 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.
4634 * \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.
4635 * \sa MEDCouplingUMesh::colinearize2D
4637 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4639 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4640 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4641 checkFullyDefined();
4642 const double *coords=getCoords()->getConstPointer();
4643 int nbOfCells=getNumberOfCells();
4644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4645 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4647 int *workIndexOut=nodalConnecIndexOut->getPointer();
4649 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4650 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4651 std::set<INTERP_KERNEL::NormalizedCellType> types;
4652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4653 isChanged->alloc(0,1);
4654 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4656 int pos=nodalConnecOut->getNumberOfTuples();
4657 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4658 isChanged->pushBackSilent(i);
4659 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4660 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4662 if(isChanged->empty())
4664 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4666 return isChanged.retn();
4670 * This method is \b NOT const because it can modify \a this.
4671 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4672 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4673 * \param policy specifies the type of extrusion chosen:
4674 * - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4675 * will be repeated to build each level
4676 * - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4677 * the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4678 * along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4680 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4682 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4684 checkFullyDefined();
4685 mesh1D->checkFullyDefined();
4686 if(!mesh1D->isContiguous1D())
4687 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4688 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4689 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4690 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4691 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4692 if(mesh1D->getMeshDimension()!=1)
4693 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4695 if(isPresenceOfQuadratic())
4697 if(mesh1D->isFullyQuadratic())
4700 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4702 int oldNbOfNodes(getNumberOfNodes());
4703 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4708 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4713 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4717 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4719 setCoords(newCoords);
4720 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4726 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4727 * If it is not the case an exception will be thrown.
4728 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4729 * intersection of plane defined by ('origin','vec').
4730 * This method has one in/out parameter : 'cut3DCurve'.
4731 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4732 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4733 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4734 * This method will throw an exception if \a this contains a non linear segment.
4736 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4738 checkFullyDefined();
4739 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4740 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4741 int ncells=getNumberOfCells();
4742 int nnodes=getNumberOfNodes();
4743 double vec2[3],vec3[3],vec4[3];
4744 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4746 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4747 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4748 const int *conn=_nodal_connec->getConstPointer();
4749 const int *connI=_nodal_connec_index->getConstPointer();
4750 const double *coo=_coords->getConstPointer();
4751 std::vector<double> addCoo;
4752 for(int i=0;i<ncells;i++)
4754 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4756 if(cut3DCurve[i]==-2)
4758 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4759 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];
4760 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4761 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4762 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4764 const double *st2=coo+3*st;
4765 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4766 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]));
4767 if(pos>eps && pos<1-eps)
4769 int nNode=((int)addCoo.size())/3;
4770 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4771 addCoo.insert(addCoo.end(),vec4,vec4+3);
4772 cut3DCurve[i]=nnodes+nNode;
4778 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4782 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4783 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4784 coo2->alloc(newNbOfNodes,3);
4785 double *tmp=coo2->getPointer();
4786 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4787 std::copy(addCoo.begin(),addCoo.end(),tmp);
4788 DataArrayDouble::SetArrayIn(coo2,_coords);
4793 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4794 * \param mesh1D is the input 1D mesh used for translation computation.
4795 * \return newCoords new coords filled by this method.
4797 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4799 int oldNbOfNodes=getNumberOfNodes();
4800 int nbOf1DCells=mesh1D->getNumberOfCells();
4801 int spaceDim=getSpaceDimension();
4802 DataArrayDouble *ret=DataArrayDouble::New();
4803 std::vector<bool> isQuads;
4804 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4805 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4806 double *retPtr=ret->getPointer();
4807 const double *coords=getCoords()->getConstPointer();
4808 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4810 std::vector<double> c;
4814 for(int i=0;i<nbOf1DCells;i++)
4817 mesh1D->getNodeIdsOfCell(i,v);
4819 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4820 mesh1D->getCoordinatesOfNode(v[0],c);
4821 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4822 for(int j=0;j<oldNbOfNodes;j++)
4823 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4827 mesh1D->getCoordinatesOfNode(v[1],c);
4828 mesh1D->getCoordinatesOfNode(v[0],c);
4829 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4830 for(int j=0;j<oldNbOfNodes;j++)
4831 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4834 ret->copyStringInfoFrom(*getCoords());
4839 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4840 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4841 * \return newCoords new coords filled by this method.
4843 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4845 if(mesh1D->getSpaceDimension()==2)
4846 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4847 if(mesh1D->getSpaceDimension()==3)
4848 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4849 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4853 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4854 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4855 * \return newCoords new coords filled by this method.
4857 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4861 int oldNbOfNodes=getNumberOfNodes();
4862 int nbOf1DCells=mesh1D->getNumberOfCells();
4864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4865 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4866 int nbOfLevsInVec=nbOf1DCells+1;
4867 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4868 double *retPtr=ret->getPointer();
4869 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4870 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4871 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4872 tmp->setCoords(tmp2);
4873 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4874 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4875 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4876 for(int i=1;i<nbOfLevsInVec;i++)
4878 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4879 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4880 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4881 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4882 tmp->translate(vec);
4883 double tmp3[2],radius,alpha,alpha0;
4884 const double *p0=i+1<nbOfLevsInVec?begin:third;
4885 const double *p1=i+1<nbOfLevsInVec?end:begin;
4886 const double *p2=i+1<nbOfLevsInVec?third:end;
4887 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4888 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]);
4889 double angle=acos(cosangle/(radius*radius));
4890 tmp->rotate(end,0,angle);
4891 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4897 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4898 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4899 * \return newCoords new coords filled by this method.
4901 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4904 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4905 int oldNbOfNodes=getNumberOfNodes();
4906 int nbOf1DCells=mesh1D->getNumberOfCells();
4908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4909 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4910 int nbOfLevsInVec=nbOf1DCells+1;
4911 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4912 double *retPtr=ret->getPointer();
4913 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4914 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4915 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4916 tmp->setCoords(tmp2);
4917 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4918 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4919 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4920 for(int i=1;i<nbOfLevsInVec;i++)
4922 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4923 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4924 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4925 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4926 tmp->translate(vec);
4927 double tmp3[2],radius,alpha,alpha0;
4928 const double *p0=i+1<nbOfLevsInVec?begin:third;
4929 const double *p1=i+1<nbOfLevsInVec?end:begin;
4930 const double *p2=i+1<nbOfLevsInVec?third:end;
4931 double vecPlane[3]={
4932 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4933 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4934 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4936 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4939 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4940 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4941 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4943 double c2=cos(asin(s2));
4945 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4946 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4947 {-vec2[1]*s2, vec2[0]*s2, c2}
4949 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]};
4950 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]};
4951 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]};
4952 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4953 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]);
4954 double angle=acos(cosangle/(radius*radius));
4955 tmp->rotate(end,vecPlane,angle);
4957 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4963 * This method is private because not easy to use for end user. This method is const contrary to
4964 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4965 * the coords sorted slice by slice.
4966 * \param isQuad specifies presence of quadratic cells.
4968 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4970 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4971 int nbOf2DCells(getNumberOfCells());
4972 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4973 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4974 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4976 newConnI->alloc(nbOf3DCells+1,1);
4977 int *newConnIPtr(newConnI->getPointer());
4979 std::vector<int> newc;
4980 for(int j=0;j<nbOf2DCells;j++)
4982 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4983 *newConnIPtr++=(int)newc.size();
4985 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4986 int *newConnPtr(newConn->getPointer());
4987 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4988 newConnIPtr=newConnI->getPointer();
4989 for(int iz=0;iz<nbOf1DCells;iz++)
4992 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4993 const int *posOfTypeOfCell(newConnIPtr);
4994 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4996 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4997 if(icell!=*posOfTypeOfCell)
5000 *newConnPtr=(*iter)+iz*deltaPerLev;
5011 ret->setConnectivity(newConn,newConnI,true);
5012 ret->setCoords(getCoords());
5017 * Checks if \a this mesh is constituted by only quadratic cells.
5018 * \return bool - \c true if there are only quadratic cells in \a this mesh.
5019 * \throw If the coordinates array is not set.
5020 * \throw If the nodal connectivity of cells is not defined.
5022 bool MEDCouplingUMesh::isFullyQuadratic() const
5024 checkFullyDefined();
5026 int nbOfCells=getNumberOfCells();
5027 for(int i=0;i<nbOfCells && ret;i++)
5029 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5030 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5031 ret=cm.isQuadratic();
5037 * Checks if \a this mesh includes any quadratic cell.
5038 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5039 * \throw If the coordinates array is not set.
5040 * \throw If the nodal connectivity of cells is not defined.
5042 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5044 checkFullyDefined();
5046 int nbOfCells=getNumberOfCells();
5047 for(int i=0;i<nbOfCells && !ret;i++)
5049 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5050 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5051 ret=cm.isQuadratic();
5057 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5058 * this mesh, it remains unchanged.
5059 * \throw If the coordinates array is not set.
5060 * \throw If the nodal connectivity of cells is not defined.
5062 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5064 checkFullyDefined();
5065 int nbOfCells=getNumberOfCells();
5067 const int *iciptr=_nodal_connec_index->getConstPointer();
5068 for(int i=0;i<nbOfCells;i++)
5070 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5071 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5072 if(cm.isQuadratic())
5074 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5075 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5076 if(!cml.isDynamic())
5077 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5079 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5084 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5086 const int *icptr=_nodal_connec->getConstPointer();
5087 newConn->alloc(getMeshLength()-delta,1);
5088 newConnI->alloc(nbOfCells+1,1);
5089 int *ocptr=newConn->getPointer();
5090 int *ociptr=newConnI->getPointer();
5093 for(int i=0;i<nbOfCells;i++,ociptr++)
5095 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5096 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5097 if(!cm.isQuadratic())
5099 _types.insert(type);
5100 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5101 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5105 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5106 _types.insert(typel);
5107 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5108 int newNbOfNodes=cml.getNumberOfNodes();
5110 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5111 *ocptr++=(int)typel;
5112 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5113 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5116 setConnectivity(newConn,newConnI,false);
5120 * This method converts all linear cell in \a this to quadratic one.
5121 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5122 * 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)
5123 * 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.
5124 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5125 * end of the existing coordinates.
5127 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5128 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5129 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5131 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5133 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5135 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5137 DataArrayInt *conn=0,*connI=0;
5138 DataArrayDouble *coords=0;
5139 std::set<INTERP_KERNEL::NormalizedCellType> types;
5140 checkFullyDefined();
5141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5142 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5143 int meshDim=getMeshDimension();
5144 switch(conversionType)
5150 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5151 connSafe=conn; connISafe=connI; coordsSafe=coords;
5154 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5155 connSafe=conn; connISafe=connI; coordsSafe=coords;
5158 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5159 connSafe=conn; connISafe=connI; coordsSafe=coords;
5162 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5170 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5171 connSafe=conn; connISafe=connI; coordsSafe=coords;
5174 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5175 connSafe=conn; connISafe=connI; coordsSafe=coords;
5178 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5179 connSafe=conn; connISafe=connI; coordsSafe=coords;
5182 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5187 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5189 setConnectivity(connSafe,connISafe,false);
5191 setCoords(coordsSafe);
5196 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5197 * so that the number of cells remains the same. Quadratic faces are converted to
5198 * polygons. This method works only for 2D meshes in
5199 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5200 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5201 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5202 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5203 * a polylinized edge constituting the input polygon.
5204 * \throw If the coordinates array is not set.
5205 * \throw If the nodal connectivity of cells is not defined.
5206 * \throw If \a this->getMeshDimension() != 2.
5207 * \throw If \a this->getSpaceDimension() != 2.
5209 void MEDCouplingUMesh::tessellate2D(double eps)
5211 int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5213 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5217 return tessellate2DCurveInternal(eps);
5219 return tessellate2DInternal(eps);
5221 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5225 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5226 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5227 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5228 * a sub-divided edge.
5229 * \throw If the coordinates array is not set.
5230 * \throw If the nodal connectivity of cells is not defined.
5231 * \throw If \a this->getMeshDimension() != 1.
5232 * \throw If \a this->getSpaceDimension() != 2.
5237 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5238 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5239 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5240 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5241 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5242 * This method can be seen as the opposite method of colinearize2D.
5243 * 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
5244 * to avoid to modify the numbering of existing nodes.
5246 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5247 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5248 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5249 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5250 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5251 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5252 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5254 * \sa buildDescendingConnectivity2
5256 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5257 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5259 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5260 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5261 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5262 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5263 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5264 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5265 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5266 //DataArrayInt *out0(0),*outi0(0);
5267 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5268 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5269 //out0s=out0s->buildUnique(); out0s->sort(true);
5274 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5275 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5276 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5278 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5284 int nbOfCells=getNumberOfCells();
5285 int nbOfNodes=getNumberOfNodes();
5286 const int *cPtr=_nodal_connec->getConstPointer();
5287 const int *icPtr=_nodal_connec_index->getConstPointer();
5288 int lastVal=0,offset=nbOfNodes;
5289 for(int i=0;i<nbOfCells;i++,icPtr++)
5291 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5292 if(type==INTERP_KERNEL::NORM_SEG2)
5294 types.insert(INTERP_KERNEL::NORM_SEG3);
5295 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5296 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5297 newConn->pushBackSilent(offset++);
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(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5315 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
5317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5321 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5322 DataArrayInt *conn1D=0,*conn1DI=0;
5323 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5324 DataArrayDouble *coordsTmp=0;
5325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5326 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5328 const int *c1DPtr=conn1D->begin();
5329 const int *c1DIPtr=conn1DI->begin();
5330 int nbOfCells=getNumberOfCells();
5331 const int *cPtr=_nodal_connec->getConstPointer();
5332 const int *icPtr=_nodal_connec_index->getConstPointer();
5334 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5336 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5337 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5338 if(!cm.isQuadratic())
5340 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5341 types.insert(typ2); newConn->pushBackSilent(typ2);
5342 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5343 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5344 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5345 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5346 newConnI->pushBackSilent(lastVal);
5347 ret->pushBackSilent(i);
5352 lastVal+=(icPtr[1]-icPtr[0]);
5353 newConnI->pushBackSilent(lastVal);
5354 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5357 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5362 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5363 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5364 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5366 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5369 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5370 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5373 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5376 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5382 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5383 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5384 DataArrayInt *conn1D=0,*conn1DI=0;
5385 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5386 DataArrayDouble *coordsTmp=0;
5387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5388 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5390 const int *c1DPtr=conn1D->begin();
5391 const int *c1DIPtr=conn1DI->begin();
5392 int nbOfCells=getNumberOfCells();
5393 const int *cPtr=_nodal_connec->getConstPointer();
5394 const int *icPtr=_nodal_connec_index->getConstPointer();
5395 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5396 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5398 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5399 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5400 if(!cm.isQuadratic())
5402 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5403 types.insert(typ2); newConn->pushBackSilent(typ2);
5404 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5405 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5406 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5407 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5408 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5409 newConnI->pushBackSilent(lastVal);
5410 ret->pushBackSilent(i);
5415 lastVal+=(icPtr[1]-icPtr[0]);
5416 newConnI->pushBackSilent(lastVal);
5417 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5420 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5421 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5426 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5427 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5428 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5430 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5434 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5437 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5440 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5442 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5448 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5449 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5450 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5451 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5452 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5455 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5457 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5459 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5460 int nbOfCells=getNumberOfCells();
5461 const int *cPtr=_nodal_connec->getConstPointer();
5462 const int *icPtr=_nodal_connec_index->getConstPointer();
5463 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5464 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5466 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5467 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5468 if(!cm.isQuadratic())
5470 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5471 if(typ2==INTERP_KERNEL::NORM_ERROR)
5473 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5474 throw INTERP_KERNEL::Exception(oss.str().c_str());
5476 types.insert(typ2); newConn->pushBackSilent(typ2);
5477 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5478 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5479 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5480 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5482 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5483 int tmpPos=newConn->getNumberOfTuples();
5484 newConn->pushBackSilent(nodeId2);
5485 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5487 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5488 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5489 newConnI->pushBackSilent(lastVal);
5490 ret->pushBackSilent(i);
5495 lastVal+=(icPtr[1]-icPtr[0]);
5496 newConnI->pushBackSilent(lastVal);
5497 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5500 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5501 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5502 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5503 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5504 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5505 int *c=newConn->getPointer();
5506 const int *cI(newConnI->begin());
5507 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5508 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5509 offset=coordsTmp2Safe->getNumberOfTuples();
5510 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5511 c[cI[(*elt)+1]-1]+=offset;
5512 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5517 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5518 * In addition, returns an array mapping new cells to old ones. <br>
5519 * This method typically increases the number of cells in \a this mesh
5520 * but the number of nodes remains \b unchanged.
5521 * That's why the 3D splitting policies
5522 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5523 * \param [in] policy - specifies a pattern used for splitting.
5524 * The semantic of \a policy is:
5525 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5526 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5527 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5528 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5531 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5532 * an id of old cell producing it. The caller is to delete this array using
5533 * decrRef() as it is no more needed.
5535 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5536 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5537 * and \a this->getMeshDimension() != 3.
5538 * \throw If \a policy is not one of the four discussed above.
5539 * \throw If the nodal connectivity of cells is not defined.
5540 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5542 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5547 return simplexizePol0();
5549 return simplexizePol1();
5550 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5551 return simplexizePlanarFace5();
5552 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5553 return simplexizePlanarFace6();
5555 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)");
5560 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5561 * - 1D: INTERP_KERNEL::NORM_SEG2
5562 * - 2D: INTERP_KERNEL::NORM_TRI3
5563 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5565 * This method is useful for users that need to use P1 field services as
5566 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5567 * All these methods need mesh support containing only simplex cells.
5568 * \return bool - \c true if there are only simplex cells in \a this mesh.
5569 * \throw If the coordinates array is not set.
5570 * \throw If the nodal connectivity of cells is not defined.
5571 * \throw If \a this->getMeshDimension() < 1.
5573 bool MEDCouplingUMesh::areOnlySimplexCells() const
5575 checkFullyDefined();
5576 int mdim=getMeshDimension();
5577 if(mdim<1 || mdim>3)
5578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5579 int nbCells=getNumberOfCells();
5580 const int *conn=_nodal_connec->getConstPointer();
5581 const int *connI=_nodal_connec_index->getConstPointer();
5582 for(int i=0;i<nbCells;i++)
5584 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5592 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5594 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5596 checkConnectivityFullyDefined();
5597 if(getMeshDimension()!=2)
5598 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5599 int nbOfCells=getNumberOfCells();
5600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5601 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5602 ret->alloc(nbOfCells+nbOfCutCells,1);
5603 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5604 int *retPt=ret->getPointer();
5605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5606 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5607 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5608 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5609 int *pt=newConn->getPointer();
5610 int *ptI=newConnI->getPointer();
5612 const int *oldc=_nodal_connec->getConstPointer();
5613 const int *ci=_nodal_connec_index->getConstPointer();
5614 for(int i=0;i<nbOfCells;i++,ci++)
5616 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5618 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5619 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5620 pt=std::copy(tmp,tmp+8,pt);
5629 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5630 ptI[1]=ptI[0]+ci[1]-ci[0];
5635 _nodal_connec->decrRef();
5636 _nodal_connec=newConn.retn();
5637 _nodal_connec_index->decrRef();
5638 _nodal_connec_index=newConnI.retn();
5645 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5647 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5649 checkConnectivityFullyDefined();
5650 if(getMeshDimension()!=2)
5651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5652 int nbOfCells=getNumberOfCells();
5653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5654 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5655 ret->alloc(nbOfCells+nbOfCutCells,1);
5656 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5657 int *retPt=ret->getPointer();
5658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5660 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5661 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5662 int *pt=newConn->getPointer();
5663 int *ptI=newConnI->getPointer();
5665 const int *oldc=_nodal_connec->getConstPointer();
5666 const int *ci=_nodal_connec_index->getConstPointer();
5667 for(int i=0;i<nbOfCells;i++,ci++)
5669 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5671 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5672 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5673 pt=std::copy(tmp,tmp+8,pt);
5682 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5683 ptI[1]=ptI[0]+ci[1]-ci[0];
5688 _nodal_connec->decrRef();
5689 _nodal_connec=newConn.retn();
5690 _nodal_connec_index->decrRef();
5691 _nodal_connec_index=newConnI.retn();
5698 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5700 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5702 checkConnectivityFullyDefined();
5703 if(getMeshDimension()!=3)
5704 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5705 int nbOfCells=getNumberOfCells();
5706 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5707 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5708 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5709 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5710 int *retPt=ret->getPointer();
5711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5713 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5714 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5715 int *pt=newConn->getPointer();
5716 int *ptI=newConnI->getPointer();
5718 const int *oldc=_nodal_connec->getConstPointer();
5719 const int *ci=_nodal_connec_index->getConstPointer();
5720 for(int i=0;i<nbOfCells;i++,ci++)
5722 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5724 for(int j=0;j<5;j++,pt+=5,ptI++)
5726 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5727 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];
5734 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5735 ptI[1]=ptI[0]+ci[1]-ci[0];
5740 _nodal_connec->decrRef();
5741 _nodal_connec=newConn.retn();
5742 _nodal_connec_index->decrRef();
5743 _nodal_connec_index=newConnI.retn();
5750 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5752 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5754 checkConnectivityFullyDefined();
5755 if(getMeshDimension()!=3)
5756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5757 int nbOfCells=getNumberOfCells();
5758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5759 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5760 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5761 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5762 int *retPt=ret->getPointer();
5763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5764 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5765 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5766 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5767 int *pt=newConn->getPointer();
5768 int *ptI=newConnI->getPointer();
5770 const int *oldc=_nodal_connec->getConstPointer();
5771 const int *ci=_nodal_connec_index->getConstPointer();
5772 for(int i=0;i<nbOfCells;i++,ci++)
5774 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5776 for(int j=0;j<6;j++,pt+=5,ptI++)
5778 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5779 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];
5786 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5787 ptI[1]=ptI[0]+ci[1]-ci[0];
5792 _nodal_connec->decrRef();
5793 _nodal_connec=newConn.retn();
5794 _nodal_connec_index->decrRef();
5795 _nodal_connec_index=newConnI.retn();
5802 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5803 * so that the number of cells remains the same. Quadratic faces are converted to
5804 * polygons. This method works only for 2D meshes in
5805 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5806 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5807 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5808 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5809 * a polylinized edge constituting the input polygon.
5810 * \throw If the coordinates array is not set.
5811 * \throw If the nodal connectivity of cells is not defined.
5812 * \throw If \a this->getMeshDimension() != 2.
5813 * \throw If \a this->getSpaceDimension() != 2.
5815 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5817 checkFullyDefined();
5818 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5819 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5820 double epsa=fabs(eps);
5821 if(epsa<std::numeric_limits<double>::min())
5822 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5824 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5825 revDesc1=0; revDescIndx1=0;
5826 mDesc->tessellate2D(eps);
5827 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5828 setCoords(mDesc->getCoords());
5832 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5833 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5834 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5835 * a sub-divided edge.
5836 * \throw If the coordinates array is not set.
5837 * \throw If the nodal connectivity of cells is not defined.
5838 * \throw If \a this->getMeshDimension() != 1.
5839 * \throw If \a this->getSpaceDimension() != 2.
5841 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5843 checkFullyDefined();
5844 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5845 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5846 double epsa=fabs(eps);
5847 if(epsa<std::numeric_limits<double>::min())
5848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5849 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5850 int nbCells=getNumberOfCells();
5851 int nbNodes=getNumberOfNodes();
5852 const int *conn=_nodal_connec->getConstPointer();
5853 const int *connI=_nodal_connec_index->getConstPointer();
5854 const double *coords=_coords->getConstPointer();
5855 std::vector<double> addCoo;
5856 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5858 newConnI->alloc(nbCells+1,1);
5859 int *newConnIPtr=newConnI->getPointer();
5862 INTERP_KERNEL::Node *tmp2[3];
5863 std::set<INTERP_KERNEL::NormalizedCellType> types;
5864 for(int i=0;i<nbCells;i++,newConnIPtr++)
5866 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5867 if(cm.isQuadratic())
5868 {//assert(connI[i+1]-connI[i]-1==3)
5869 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5870 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5871 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5872 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5873 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5876 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5877 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5879 newConnIPtr[1]=(int)newConn.size();
5883 types.insert(INTERP_KERNEL::NORM_SEG2);
5884 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5885 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5886 newConnIPtr[1]=newConnIPtr[0]+3;
5891 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5892 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5893 newConnIPtr[1]=newConnIPtr[0]+3;
5896 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5899 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5900 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5901 newConnArr->alloc((int)newConn.size(),1);
5902 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5903 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5904 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5905 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5906 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5907 std::copy(addCoo.begin(),addCoo.end(),work);
5908 DataArrayDouble::SetArrayIn(newCoords,_coords);
5913 * 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.
5914 * This method completly ignore coordinates.
5915 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5916 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5917 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5918 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5920 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5922 checkFullyDefined();
5923 if(getMeshDimension()!=2)
5924 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5925 int nbOfCells=getNumberOfCells();
5926 int *connI=_nodal_connec_index->getPointer();
5928 for(int i=0;i<nbOfCells;i++,connI++)
5930 int offset=descIndex[i];
5931 int nbOfEdges=descIndex[i+1]-offset;
5933 bool ddirect=desc[offset+nbOfEdges-1]>0;
5934 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5935 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5936 for(int j=0;j<nbOfEdges;j++)
5938 bool direct=desc[offset+j]>0;
5939 int edgeId=std::abs(desc[offset+j])-1;
5940 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5942 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5943 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5944 int ref2=direct?id1:id2;
5947 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5948 newConnLgth+=nbOfSubNodes-1;
5953 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5954 throw INTERP_KERNEL::Exception(oss.str().c_str());
5959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5962 newConnLgth++;//+1 is for cell type
5963 connI[1]=newConnLgth;
5966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5967 newConn->alloc(newConnLgth,1);
5968 int *work=newConn->getPointer();
5969 for(int i=0;i<nbOfCells;i++)
5971 *work++=INTERP_KERNEL::NORM_POLYGON;
5972 int offset=descIndex[i];
5973 int nbOfEdges=descIndex[i+1]-offset;
5974 for(int j=0;j<nbOfEdges;j++)
5976 bool direct=desc[offset+j]>0;
5977 int edgeId=std::abs(desc[offset+j])-1;
5979 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5982 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5983 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5984 work=std::copy(it,it+nbOfSubNodes-1,work);
5988 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5991 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5995 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5996 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5997 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5998 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5999 * so it can be useful to call mergeNodes() before calling this method.
6000 * \throw If \a this->getMeshDimension() <= 1.
6001 * \throw If the coordinates array is not set.
6002 * \throw If the nodal connectivity of cells is not defined.
6004 void MEDCouplingUMesh::convertDegeneratedCells()
6006 checkFullyDefined();
6007 if(getMeshDimension()<=1)
6008 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
6009 int nbOfCells=getNumberOfCells();
6012 int initMeshLgth=getMeshLength();
6013 int *conn=_nodal_connec->getPointer();
6014 int *index=_nodal_connec_index->getPointer();
6018 for(int i=0;i<nbOfCells;i++)
6020 lgthOfCurCell=index[i+1]-posOfCurCell;
6021 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6023 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6024 conn+newPos+1,newLgth);
6025 conn[newPos]=newType;
6027 posOfCurCell=index[i+1];
6030 if(newPos!=initMeshLgth)
6031 _nodal_connec->reAlloc(newPos);
6036 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6037 * A cell is considered to be oriented correctly if an angle between its
6038 * normal vector and a given vector is less than \c PI / \c 2.
6039 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6041 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
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() != 2.
6046 * \throw If \a this->getSpaceDimension() != 3.
6048 * \if ENABLE_EXAMPLES
6049 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6050 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6053 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6055 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6056 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6057 int nbOfCells=getNumberOfCells();
6058 const int *conn=_nodal_connec->getConstPointer();
6059 const int *connI=_nodal_connec_index->getConstPointer();
6060 const double *coordsPtr=_coords->getConstPointer();
6061 for(int i=0;i<nbOfCells;i++)
6063 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6064 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6066 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6067 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6074 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6075 * considered to be oriented correctly if an angle between its normal vector and a
6076 * given vector is less than \c PI / \c 2.
6077 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6079 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6081 * \throw If \a this->getMeshDimension() != 2.
6082 * \throw If \a this->getSpaceDimension() != 3.
6084 * \if ENABLE_EXAMPLES
6085 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6086 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6089 * \sa changeOrientationOfCells
6091 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6093 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6094 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6095 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6096 const int *connI(_nodal_connec_index->getConstPointer());
6097 const double *coordsPtr(_coords->getConstPointer());
6098 bool isModified(false);
6099 for(int i=0;i<nbOfCells;i++)
6101 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6102 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6104 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6105 bool isQuadratic(cm.isQuadratic());
6106 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6109 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6114 _nodal_connec->declareAsNew();
6119 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6121 * \sa orientCorrectly2DCells
6123 void MEDCouplingUMesh::changeOrientationOfCells()
6125 int mdim(getMeshDimension());
6126 if(mdim!=2 && mdim!=1)
6127 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6128 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6129 const int *connI(_nodal_connec_index->getConstPointer());
6132 for(int i=0;i<nbOfCells;i++)
6134 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6135 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6136 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6141 for(int i=0;i<nbOfCells;i++)
6143 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6144 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6145 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6151 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6152 * oriented facets. The normal vector of the facet should point out of the cell.
6153 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6154 * is not cleared before filling in.
6155 * \throw If \a this->getMeshDimension() != 3.
6156 * \throw If \a this->getSpaceDimension() != 3.
6157 * \throw If the coordinates array is not set.
6158 * \throw If the nodal connectivity of cells is not defined.
6160 * \if ENABLE_EXAMPLES
6161 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6162 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6165 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6167 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6168 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6169 int nbOfCells=getNumberOfCells();
6170 const int *conn=_nodal_connec->getConstPointer();
6171 const int *connI=_nodal_connec_index->getConstPointer();
6172 const double *coordsPtr=_coords->getConstPointer();
6173 for(int i=0;i<nbOfCells;i++)
6175 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6176 if(type==INTERP_KERNEL::NORM_POLYHED)
6178 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6185 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6187 * \throw If \a this->getMeshDimension() != 3.
6188 * \throw If \a this->getSpaceDimension() != 3.
6189 * \throw If the coordinates array is not set.
6190 * \throw If the nodal connectivity of cells is not defined.
6191 * \throw If the reparation fails.
6193 * \if ENABLE_EXAMPLES
6194 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6195 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6197 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6199 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6201 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6202 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6203 int nbOfCells=getNumberOfCells();
6204 int *conn=_nodal_connec->getPointer();
6205 const int *connI=_nodal_connec_index->getConstPointer();
6206 const double *coordsPtr=_coords->getConstPointer();
6207 for(int i=0;i<nbOfCells;i++)
6209 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6210 if(type==INTERP_KERNEL::NORM_POLYHED)
6214 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6215 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6217 catch(INTERP_KERNEL::Exception& e)
6219 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6220 throw INTERP_KERNEL::Exception(oss.str().c_str());
6228 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6229 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6230 * according to which the first facet of the cell should be oriented to have the normal vector
6231 * pointing out of cell.
6232 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6233 * cells. The caller is to delete this array using decrRef() as it is no more
6235 * \throw If \a this->getMeshDimension() != 3.
6236 * \throw If \a this->getSpaceDimension() != 3.
6237 * \throw If the coordinates array is not set.
6238 * \throw If the nodal connectivity of cells is not defined.
6240 * \if ENABLE_EXAMPLES
6241 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6242 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6244 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6246 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6248 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6249 if(getMeshDimension()!=3)
6250 throw INTERP_KERNEL::Exception(msg);
6251 int spaceDim=getSpaceDimension();
6253 throw INTERP_KERNEL::Exception(msg);
6255 int nbOfCells=getNumberOfCells();
6256 int *conn=_nodal_connec->getPointer();
6257 const int *connI=_nodal_connec_index->getConstPointer();
6258 const double *coo=getCoords()->getConstPointer();
6259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6260 for(int i=0;i<nbOfCells;i++)
6262 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6263 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6265 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6267 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6268 cells->pushBackSilent(i);
6272 return cells.retn();
6276 * This method is a faster method to correct orientation of all 3D cells in \a this.
6277 * 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.
6278 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6280 * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6281 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6283 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6285 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6286 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6287 int nbOfCells=getNumberOfCells();
6288 int *conn=_nodal_connec->getPointer();
6289 const int *connI=_nodal_connec_index->getConstPointer();
6290 const double *coordsPtr=_coords->getConstPointer();
6291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6292 for(int i=0;i<nbOfCells;i++)
6294 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6297 case INTERP_KERNEL::NORM_TETRA4:
6299 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6301 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6302 ret->pushBackSilent(i);
6306 case INTERP_KERNEL::NORM_PYRA5:
6308 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6310 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6311 ret->pushBackSilent(i);
6315 case INTERP_KERNEL::NORM_PENTA6:
6316 case INTERP_KERNEL::NORM_HEXA8:
6317 case INTERP_KERNEL::NORM_HEXGP12:
6319 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6321 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6322 ret->pushBackSilent(i);
6326 case INTERP_KERNEL::NORM_POLYHED:
6328 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6330 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6331 ret->pushBackSilent(i);
6336 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 !");
6344 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6345 * If it is not the case an exception will be thrown.
6346 * This method is fast because the first cell of \a this is used to compute the plane.
6347 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6348 * \param pos output of size at least 3 used to store a point owned of searched plane.
6350 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6352 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6353 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6354 const int *conn=_nodal_connec->getConstPointer();
6355 const int *connI=_nodal_connec_index->getConstPointer();
6356 const double *coordsPtr=_coords->getConstPointer();
6357 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6358 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6362 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6363 * cells. Currently cells of the following types are treated:
6364 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6365 * For a cell of other type an exception is thrown.
6366 * Space dimension of a 2D mesh can be either 2 or 3.
6367 * The Edge Ratio of a cell \f$t\f$ is:
6368 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6369 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6370 * the smallest edge lengths of \f$t\f$.
6371 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6372 * cells and one time, lying on \a this mesh. The caller is to delete this
6373 * field using decrRef() as it is no more needed.
6374 * \throw If the coordinates array is not set.
6375 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6376 * \throw If the connectivity data array has more than one component.
6377 * \throw If the connectivity data array has a named component.
6378 * \throw If the connectivity index data array has more than one component.
6379 * \throw If the connectivity index data array has a named component.
6380 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6381 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6382 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6384 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6387 int spaceDim=getSpaceDimension();
6388 int meshDim=getMeshDimension();
6389 if(spaceDim!=2 && spaceDim!=3)
6390 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6391 if(meshDim!=2 && meshDim!=3)
6392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6393 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6395 int nbOfCells=getNumberOfCells();
6396 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6397 arr->alloc(nbOfCells,1);
6398 double *pt=arr->getPointer();
6399 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6400 const int *conn=_nodal_connec->getConstPointer();
6401 const int *connI=_nodal_connec_index->getConstPointer();
6402 const double *coo=_coords->getConstPointer();
6404 for(int i=0;i<nbOfCells;i++,pt++)
6406 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6409 case INTERP_KERNEL::NORM_TRI3:
6411 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6412 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6415 case INTERP_KERNEL::NORM_QUAD4:
6417 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6418 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6421 case INTERP_KERNEL::NORM_TETRA4:
6423 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6424 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6430 conn+=connI[i+1]-connI[i];
6432 ret->setName("EdgeRatio");
6433 ret->synchronizeTimeWithSupport();
6438 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6439 * cells. Currently cells of the following types are treated:
6440 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6441 * For a cell of other type an exception is thrown.
6442 * Space dimension of a 2D mesh can be either 2 or 3.
6443 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6444 * cells and one time, lying on \a this mesh. The caller is to delete this
6445 * field using decrRef() as it is no more needed.
6446 * \throw If the coordinates array is not set.
6447 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6448 * \throw If the connectivity data array has more than one component.
6449 * \throw If the connectivity data array has a named component.
6450 * \throw If the connectivity index data array has more than one component.
6451 * \throw If the connectivity index data array has a named component.
6452 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6453 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6454 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6456 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6459 int spaceDim=getSpaceDimension();
6460 int meshDim=getMeshDimension();
6461 if(spaceDim!=2 && spaceDim!=3)
6462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6463 if(meshDim!=2 && meshDim!=3)
6464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6465 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6467 int nbOfCells=getNumberOfCells();
6468 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6469 arr->alloc(nbOfCells,1);
6470 double *pt=arr->getPointer();
6471 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6472 const int *conn=_nodal_connec->getConstPointer();
6473 const int *connI=_nodal_connec_index->getConstPointer();
6474 const double *coo=_coords->getConstPointer();
6476 for(int i=0;i<nbOfCells;i++,pt++)
6478 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6481 case INTERP_KERNEL::NORM_TRI3:
6483 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6484 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6487 case INTERP_KERNEL::NORM_QUAD4:
6489 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6490 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6493 case INTERP_KERNEL::NORM_TETRA4:
6495 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6496 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6500 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6502 conn+=connI[i+1]-connI[i];
6504 ret->setName("AspectRatio");
6505 ret->synchronizeTimeWithSupport();
6510 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6511 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6512 * treated: INTERP_KERNEL::NORM_QUAD4.
6513 * For a cell of other type an exception is thrown.
6514 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6515 * cells and one time, lying on \a this mesh. The caller is to delete this
6516 * field using decrRef() as it is no more needed.
6517 * \throw If the coordinates array is not set.
6518 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6519 * \throw If the connectivity data array has more than one component.
6520 * \throw If the connectivity data array has a named component.
6521 * \throw If the connectivity index data array has more than one component.
6522 * \throw If the connectivity index data array has a named component.
6523 * \throw If \a this->getMeshDimension() != 2.
6524 * \throw If \a this->getSpaceDimension() != 3.
6525 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6527 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6530 int spaceDim=getSpaceDimension();
6531 int meshDim=getMeshDimension();
6533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6535 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6536 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6538 int nbOfCells=getNumberOfCells();
6539 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6540 arr->alloc(nbOfCells,1);
6541 double *pt=arr->getPointer();
6542 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6543 const int *conn=_nodal_connec->getConstPointer();
6544 const int *connI=_nodal_connec_index->getConstPointer();
6545 const double *coo=_coords->getConstPointer();
6547 for(int i=0;i<nbOfCells;i++,pt++)
6549 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6552 case INTERP_KERNEL::NORM_QUAD4:
6554 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6555 *pt=INTERP_KERNEL::quadWarp(tmp);
6559 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6561 conn+=connI[i+1]-connI[i];
6563 ret->setName("Warp");
6564 ret->synchronizeTimeWithSupport();
6570 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6571 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6572 * treated: INTERP_KERNEL::NORM_QUAD4.
6573 * For a cell of other type an exception is thrown.
6574 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6575 * cells and one time, lying on \a this mesh. The caller is to delete this
6576 * field using decrRef() as it is no more needed.
6577 * \throw If the coordinates array is not set.
6578 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6579 * \throw If the connectivity data array has more than one component.
6580 * \throw If the connectivity data array has a named component.
6581 * \throw If the connectivity index data array has more than one component.
6582 * \throw If the connectivity index data array has a named component.
6583 * \throw If \a this->getMeshDimension() != 2.
6584 * \throw If \a this->getSpaceDimension() != 3.
6585 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6587 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6590 int spaceDim=getSpaceDimension();
6591 int meshDim=getMeshDimension();
6593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6596 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6598 int nbOfCells=getNumberOfCells();
6599 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6600 arr->alloc(nbOfCells,1);
6601 double *pt=arr->getPointer();
6602 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6603 const int *conn=_nodal_connec->getConstPointer();
6604 const int *connI=_nodal_connec_index->getConstPointer();
6605 const double *coo=_coords->getConstPointer();
6607 for(int i=0;i<nbOfCells;i++,pt++)
6609 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6612 case INTERP_KERNEL::NORM_QUAD4:
6614 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6615 *pt=INTERP_KERNEL::quadSkew(tmp);
6619 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6621 conn+=connI[i+1]-connI[i];
6623 ret->setName("Skew");
6624 ret->synchronizeTimeWithSupport();
6629 * 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.
6631 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6633 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6635 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6638 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6640 std::set<INTERP_KERNEL::NormalizedCellType> types;
6641 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6642 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6643 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6644 arr->alloc(nbCells,1);
6645 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6647 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6648 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6649 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6652 ret->setName("Diameter");
6657 * This method aggregate the bbox of each cell and put it into bbox parameter.
6659 * \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)
6660 * For all other cases this input parameter is ignored.
6661 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6663 * \throw If \a this is not fully set (coordinates and connectivity).
6664 * \throw If a cell in \a this has no valid nodeId.
6665 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6667 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6669 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6670 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.
6671 return getBoundingBoxForBBTreeFast();
6672 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6674 bool presenceOfQuadratic(false);
6675 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6677 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6678 if(cm.isQuadratic())
6679 presenceOfQuadratic=true;
6681 if(!presenceOfQuadratic)
6682 return getBoundingBoxForBBTreeFast();
6683 if(mDim==2 && sDim==2)
6684 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6686 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6688 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) !");
6692 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6693 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6695 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6697 * \throw If \a this is not fully set (coordinates and connectivity).
6698 * \throw If a cell in \a this has no valid nodeId.
6700 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6702 checkFullyDefined();
6703 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6704 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6705 double *bbox(ret->getPointer());
6706 for(int i=0;i<nbOfCells*spaceDim;i++)
6708 bbox[2*i]=std::numeric_limits<double>::max();
6709 bbox[2*i+1]=-std::numeric_limits<double>::max();
6711 const double *coordsPtr(_coords->getConstPointer());
6712 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6713 for(int i=0;i<nbOfCells;i++)
6715 int offset=connI[i]+1;
6716 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6717 for(int j=0;j<nbOfNodesForCell;j++)
6719 int nodeId=conn[offset+j];
6720 if(nodeId>=0 && nodeId<nbOfNodes)
6722 for(int k=0;k<spaceDim;k++)
6724 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6725 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6732 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6733 throw INTERP_KERNEL::Exception(oss.str().c_str());
6740 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6741 * useful for 2D meshes having quadratic cells
6742 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6743 * the two extremities of the arc of circle).
6745 * \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)
6746 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6747 * \throw If \a this is not fully defined.
6748 * \throw If \a this is not a mesh with meshDimension equal to 2.
6749 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6750 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6752 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6754 checkFullyDefined();
6755 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6756 if(spaceDim!=2 || mDim!=2)
6757 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!");
6758 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6759 double *bbox(ret->getPointer());
6760 const double *coords(_coords->getConstPointer());
6761 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6762 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6764 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6765 int sz(connI[1]-connI[0]-1);
6766 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6767 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6768 INTERP_KERNEL::QuadraticPolygon *pol(0);
6769 for(int j=0;j<sz;j++)
6771 int nodeId(conn[*connI+1+j]);
6772 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6774 if(!cm.isQuadratic())
6775 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6777 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6778 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6779 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6785 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6786 * useful for 2D meshes having quadratic cells
6787 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6788 * the two extremities of the arc of circle).
6790 * \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)
6791 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6792 * \throw If \a this is not fully defined.
6793 * \throw If \a this is not a mesh with meshDimension equal to 1.
6794 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6795 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6797 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6799 checkFullyDefined();
6800 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6801 if(spaceDim!=2 || mDim!=1)
6802 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!");
6803 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6804 double *bbox(ret->getPointer());
6805 const double *coords(_coords->getConstPointer());
6806 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6807 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6809 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6810 int sz(connI[1]-connI[0]-1);
6811 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6812 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6813 INTERP_KERNEL::Edge *edge(0);
6814 for(int j=0;j<sz;j++)
6816 int nodeId(conn[*connI+1+j]);
6817 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6819 if(!cm.isQuadratic())
6820 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6822 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6823 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6824 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6831 namespace ParaMEDMEMImpl
6836 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6837 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6846 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6847 bool operator() (const int& pos) { return _conn[pos]==_val; }
6857 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6858 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6859 * \a this is composed in cell types.
6860 * The returned array is of size 3*n where n is the number of different types present in \a this.
6861 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6862 * This parameter is kept only for compatibility with other methode listed above.
6864 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6866 checkConnectivityFullyDefined();
6867 const int *conn=_nodal_connec->getConstPointer();
6868 const int *connI=_nodal_connec_index->getConstPointer();
6869 const int *work=connI;
6870 int nbOfCells=getNumberOfCells();
6871 std::size_t n=getAllGeoTypes().size();
6872 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6873 std::set<INTERP_KERNEL::NormalizedCellType> types;
6874 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6876 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6877 if(types.find(typ)!=types.end())
6879 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6880 oss << " is not contiguous !";
6881 throw INTERP_KERNEL::Exception(oss.str().c_str());
6885 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6886 ret[3*i+1]=(int)std::distance(work,work2);
6893 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6894 * only for types cell, type node is not managed.
6895 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6896 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6897 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6898 * If 2 or more same geometric type is in \a code and exception is thrown too.
6900 * This method firstly checks
6901 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6902 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6903 * an exception is thrown too.
6905 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6906 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6907 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6909 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6913 std::size_t sz=code.size();
6916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6917 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6919 bool isNoPflUsed=true;
6920 for(std::size_t i=0;i<n;i++)
6921 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6923 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6925 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6926 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6927 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6930 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6933 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6935 if(types.size()==_types.size())
6938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6940 int *retPtr=ret->getPointer();
6941 const int *connI=_nodal_connec_index->getConstPointer();
6942 const int *conn=_nodal_connec->getConstPointer();
6943 int nbOfCells=getNumberOfCells();
6946 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6948 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6949 int offset=(int)std::distance(connI,i);
6950 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6951 int nbOfCellsOfCurType=(int)std::distance(i,j);
6952 if(code[3*kk+2]==-1)
6953 for(int k=0;k<nbOfCellsOfCurType;k++)
6957 int idInIdsPerType=code[3*kk+2];
6958 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6960 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6963 zePfl->checkAllocated();
6964 if(zePfl->getNumberOfComponents()==1)
6966 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6968 if(*k>=0 && *k<nbOfCellsOfCurType)
6969 *retPtr=(*k)+offset;
6972 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6973 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6974 throw INTERP_KERNEL::Exception(oss.str().c_str());
6979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6982 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6986 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6987 oss << " should be in [0," << idsPerType.size() << ") !";
6988 throw INTERP_KERNEL::Exception(oss.str().c_str());
6997 * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6998 * 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.
6999 * 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.
7000 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
7002 * \param [in] profile
7003 * \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.
7004 * \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,
7005 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7006 * \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.
7007 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7008 * \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
7010 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7013 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7014 if(profile->getNumberOfComponents()!=1)
7015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7016 checkConnectivityFullyDefined();
7017 const int *conn=_nodal_connec->getConstPointer();
7018 const int *connI=_nodal_connec_index->getConstPointer();
7019 int nbOfCells=getNumberOfCells();
7020 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7021 std::vector<int> typeRangeVals(1);
7022 for(const int *i=connI;i!=connI+nbOfCells;)
7024 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7025 if(std::find(types.begin(),types.end(),curType)!=types.end())
7027 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7029 types.push_back(curType);
7030 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7031 typeRangeVals.push_back((int)std::distance(connI,i));
7034 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7035 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
7037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
7038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
7040 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7041 code.resize(3*nbOfCastsFinal);
7042 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7043 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7044 for(int i=0;i<nbOfCastsFinal;i++)
7046 int castId=castsPresent->getIJ(i,0);
7047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7048 idsInPflPerType2.push_back(tmp3);
7049 code[3*i]=(int)types[castId];
7050 code[3*i+1]=tmp3->getNumberOfTuples();
7051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7052 if(!tmp4->isIdentity2(typeRangeVals[castId+1]-typeRangeVals[castId]))
7054 tmp4->copyStringInfoFrom(*profile);
7055 idsPerType2.push_back(tmp4);
7056 code[3*i+2]=(int)idsPerType2.size()-1;
7063 std::size_t sz2=idsInPflPerType2.size();
7064 idsInPflPerType.resize(sz2);
7065 for(std::size_t i=0;i<sz2;i++)
7067 DataArrayInt *locDa=idsInPflPerType2[i];
7069 idsInPflPerType[i]=locDa;
7071 std::size_t sz=idsPerType2.size();
7072 idsPerType.resize(sz);
7073 for(std::size_t i=0;i<sz;i++)
7075 DataArrayInt *locDa=idsPerType2[i];
7077 idsPerType[i]=locDa;
7082 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7083 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7084 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7085 * 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.
7087 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7089 checkFullyDefined();
7090 nM1LevMesh->checkFullyDefined();
7091 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7093 if(_coords!=nM1LevMesh->getCoords())
7094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7097 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7099 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7100 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7101 tmp->setConnectivity(tmp0,tmp1);
7102 tmp->renumberCells(ret0->getConstPointer(),false);
7103 revDesc=tmp->getNodalConnectivity();
7104 revDescIndx=tmp->getNodalConnectivityIndex();
7105 DataArrayInt *ret=0;
7106 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7109 ret->getMaxValue(tmp2);
7111 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7112 throw INTERP_KERNEL::Exception(oss.str().c_str());
7117 revDescIndx->incrRef();
7120 meshnM1Old2New=ret0;
7125 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7126 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7127 * in "Old to New" mode.
7128 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7129 * this array using decrRef() as it is no more needed.
7130 * \throw If the nodal connectivity of cells is not defined.
7132 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7134 checkConnectivityFullyDefined();
7135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7136 renumberCells(ret->getConstPointer(),false);
7141 * This methods checks that cells are sorted by their types.
7142 * This method makes asumption (no check) that connectivity is correctly set before calling.
7144 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7146 checkFullyDefined();
7147 const int *conn=_nodal_connec->getConstPointer();
7148 const int *connI=_nodal_connec_index->getConstPointer();
7149 int nbOfCells=getNumberOfCells();
7150 std::set<INTERP_KERNEL::NormalizedCellType> types;
7151 for(const int *i=connI;i!=connI+nbOfCells;)
7153 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7154 if(types.find(curType)!=types.end())
7156 types.insert(curType);
7157 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7163 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7164 * The geometric type order is specified by MED file.
7166 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7168 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7170 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7174 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7175 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7176 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7177 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7179 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7181 checkFullyDefined();
7182 const int *conn=_nodal_connec->getConstPointer();
7183 const int *connI=_nodal_connec_index->getConstPointer();
7184 int nbOfCells=getNumberOfCells();
7188 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7189 for(const int *i=connI;i!=connI+nbOfCells;)
7191 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7192 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7193 if(isTypeExists!=orderEnd)
7195 int pos=(int)std::distance(orderBg,isTypeExists);
7199 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7203 if(sg.find(curType)==sg.end())
7205 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7216 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7217 * 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
7218 * 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'.
7220 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7222 checkConnectivityFullyDefined();
7223 int nbOfCells=getNumberOfCells();
7224 const int *conn=_nodal_connec->getConstPointer();
7225 const int *connI=_nodal_connec_index->getConstPointer();
7226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7228 tmpa->alloc(nbOfCells,1);
7229 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7230 tmpb->fillWithZero();
7231 int *tmp=tmpa->getPointer();
7232 int *tmp2=tmpb->getPointer();
7233 for(const int *i=connI;i!=connI+nbOfCells;i++)
7235 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7238 int pos=(int)std::distance(orderBg,where);
7240 tmp[std::distance(connI,i)]=pos;
7244 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7245 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7246 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7247 throw INTERP_KERNEL::Exception(oss.str().c_str());
7250 nbPerType=tmpb.retn();
7255 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7257 * \return a new object containing the old to new correspondance.
7259 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7261 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7263 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7267 * 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.
7268 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7269 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7270 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7272 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7274 DataArrayInt *nbPerType=0;
7275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7276 nbPerType->decrRef();
7277 return tmpa->buildPermArrPerLevel();
7281 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7282 * The number of cells remains unchanged after the call of this method.
7283 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7284 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7286 * \return the array giving the correspondance old to new.
7288 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7290 checkFullyDefined();
7292 const int *conn=_nodal_connec->getConstPointer();
7293 const int *connI=_nodal_connec_index->getConstPointer();
7294 int nbOfCells=getNumberOfCells();
7295 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7296 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7297 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7299 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7300 types.push_back(curType);
7301 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7303 DataArrayInt *ret=DataArrayInt::New();
7304 ret->alloc(nbOfCells,1);
7305 int *retPtr=ret->getPointer();
7306 std::fill(retPtr,retPtr+nbOfCells,-1);
7308 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7310 for(const int *i=connI;i!=connI+nbOfCells;i++)
7311 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7312 retPtr[std::distance(connI,i)]=newCellId++;
7314 renumberCells(retPtr,false);
7319 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7320 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7321 * This method makes asumption that connectivity is correctly set before calling.
7323 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7325 checkConnectivityFullyDefined();
7326 const int *conn=_nodal_connec->getConstPointer();
7327 const int *connI=_nodal_connec_index->getConstPointer();
7328 int nbOfCells=getNumberOfCells();
7329 std::vector<MEDCouplingUMesh *> ret;
7330 for(const int *i=connI;i!=connI+nbOfCells;)
7332 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7333 int beginCellId=(int)std::distance(connI,i);
7334 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7335 int endCellId=(int)std::distance(connI,i);
7336 int sz=endCellId-beginCellId;
7337 int *cells=new int[sz];
7338 for(int j=0;j<sz;j++)
7339 cells[j]=beginCellId+j;
7340 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7348 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7349 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7350 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7352 * \return a newly allocated instance, that the caller must manage.
7353 * \throw If \a this contains more than one geometric type.
7354 * \throw If the nodal connectivity of \a this is not fully defined.
7355 * \throw If the internal data is not coherent.
7357 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7359 checkConnectivityFullyDefined();
7360 if(_types.size()!=1)
7361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7362 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7363 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7364 ret->setCoords(getCoords());
7365 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7369 retC->setNodalConnectivity(c);
7373 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7375 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7376 DataArrayInt *c=0,*ci=0;
7377 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7379 retD->setNodalConnectivity(cs,cis);
7384 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7386 checkConnectivityFullyDefined();
7387 if(_types.size()!=1)
7388 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7389 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7390 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7393 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7394 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7395 throw INTERP_KERNEL::Exception(oss.str().c_str());
7397 int nbCells=getNumberOfCells();
7399 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7401 int *outPtr=connOut->getPointer();
7402 const int *conn=_nodal_connec->begin();
7403 const int *connI=_nodal_connec_index->begin();
7405 for(int i=0;i<nbCells;i++,connI++)
7407 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7408 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7411 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 << ") !";
7412 throw INTERP_KERNEL::Exception(oss.str().c_str());
7415 return connOut.retn();
7419 * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7420 * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7424 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7426 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7427 checkConnectivityFullyDefined();
7428 if(_types.size()!=1)
7429 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7430 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7432 throw INTERP_KERNEL::Exception(msg0);
7433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7434 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7435 int *cp(c->getPointer()),*cip(ci->getPointer());
7436 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7438 for(int i=0;i<nbCells;i++,cip++,incip++)
7440 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7441 int delta(stop-strt);
7444 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7445 cp=std::copy(incp+strt,incp+stop,cp);
7447 throw INTERP_KERNEL::Exception(msg0);
7450 throw INTERP_KERNEL::Exception(msg0);
7451 cip[1]=cip[0]+delta;
7453 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7457 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7458 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7459 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7460 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7461 * are not used here to avoid the build of big permutation array.
7463 * \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
7464 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7465 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7466 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7467 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7468 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7469 * \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
7470 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7472 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7473 DataArrayInt *&szOfCellGrpOfSameType,
7474 DataArrayInt *&idInMsOfCellGrpOfSameType)
7476 std::vector<const MEDCouplingUMesh *> ms2;
7477 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7480 (*it)->checkConnectivityFullyDefined();
7484 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7485 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7486 int meshDim=ms2[0]->getMeshDimension();
7487 std::vector<const MEDCouplingUMesh *> m1ssm;
7488 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7490 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7491 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7493 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7494 ret1->alloc(0,1); ret2->alloc(0,1);
7495 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7497 if(meshDim!=(*it)->getMeshDimension())
7498 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7499 if(refCoo!=(*it)->getCoords())
7500 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7501 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7502 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7503 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7504 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7506 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7507 m1ssmSingleAuto.push_back(singleCell);
7508 m1ssmSingle.push_back(singleCell);
7509 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7512 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7514 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7515 for(std::size_t i=0;i<m1ssm.size();i++)
7516 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7517 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7518 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7519 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7524 * This method returns a newly created DataArrayInt instance.
7525 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7527 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7529 checkFullyDefined();
7530 const int *conn=_nodal_connec->getConstPointer();
7531 const int *connIndex=_nodal_connec_index->getConstPointer();
7532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7533 for(const int *w=begin;w!=end;w++)
7534 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7535 ret->pushBackSilent(*w);
7540 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7541 * are in [0:getNumberOfCells())
7543 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7545 checkFullyDefined();
7546 const int *conn=_nodal_connec->getConstPointer();
7547 const int *connI=_nodal_connec_index->getConstPointer();
7548 int nbOfCells=getNumberOfCells();
7549 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7550 int *tmp=new int[nbOfCells];
7551 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7554 for(const int *i=connI;i!=connI+nbOfCells;i++)
7555 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7556 tmp[std::distance(connI,i)]=j++;
7558 DataArrayInt *ret=DataArrayInt::New();
7559 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7560 ret->copyStringInfoFrom(*da);
7561 int *retPtr=ret->getPointer();
7562 const int *daPtr=da->getConstPointer();
7563 int nbOfElems=da->getNbOfElems();
7564 for(int k=0;k<nbOfElems;k++)
7565 retPtr[k]=tmp[daPtr[k]];
7571 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7572 * This method \b works \b for mesh sorted by type.
7573 * cells whose ids is in 'idsPerGeoType' array.
7574 * This method conserves coords and name of mesh.
7576 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7578 std::vector<int> code=getDistributionOfTypes();
7579 std::size_t nOfTypesInThis=code.size()/3;
7580 int sz=0,szOfType=0;
7581 for(std::size_t i=0;i<nOfTypesInThis;i++)
7586 szOfType=code[3*i+1];
7588 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7589 if(*work<0 || *work>=szOfType)
7591 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7592 oss << ". It should be in [0," << szOfType << ") !";
7593 throw INTERP_KERNEL::Exception(oss.str().c_str());
7595 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7596 int *idsPtr=idsTokeep->getPointer();
7598 for(std::size_t i=0;i<nOfTypesInThis;i++)
7601 for(int j=0;j<code[3*i+1];j++)
7604 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7605 offset+=code[3*i+1];
7607 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7608 ret->copyTinyInfoFrom(this);
7613 * This method returns a vector of size 'this->getNumberOfCells()'.
7614 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7616 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7618 int ncell=getNumberOfCells();
7619 std::vector<bool> ret(ncell);
7620 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7621 const int *c=getNodalConnectivity()->getConstPointer();
7622 for(int i=0;i<ncell;i++)
7624 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7625 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7626 ret[i]=cm.isQuadratic();
7632 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7634 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7636 if(other->getType()!=UNSTRUCTURED)
7637 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7638 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7639 return MergeUMeshes(this,otherC);
7643 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7644 * computed by averaging coordinates of cell nodes, so this method is not a right
7645 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7646 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7647 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7648 * components. The caller is to delete this array using decrRef() as it is
7650 * \throw If the coordinates array is not set.
7651 * \throw If the nodal connectivity of cells is not defined.
7652 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7654 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7657 int spaceDim=getSpaceDimension();
7658 int nbOfCells=getNumberOfCells();
7659 ret->alloc(nbOfCells,spaceDim);
7660 ret->copyStringInfoFrom(*getCoords());
7661 double *ptToFill=ret->getPointer();
7662 const int *nodal=_nodal_connec->getConstPointer();
7663 const int *nodalI=_nodal_connec_index->getConstPointer();
7664 const double *coor=_coords->getConstPointer();
7665 for(int i=0;i<nbOfCells;i++)
7667 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7668 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7675 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7676 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7678 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7679 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7681 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7682 * \throw If \a this is not fully defined (coordinates and connectivity)
7683 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7685 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7687 checkFullyDefined();
7688 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7689 int spaceDim=getSpaceDimension();
7690 int nbOfCells=getNumberOfCells();
7691 int nbOfNodes=getNumberOfNodes();
7692 ret->alloc(nbOfCells,spaceDim);
7693 double *ptToFill=ret->getPointer();
7694 const int *nodal=_nodal_connec->getConstPointer();
7695 const int *nodalI=_nodal_connec_index->getConstPointer();
7696 const double *coor=_coords->getConstPointer();
7697 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7699 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7700 std::fill(ptToFill,ptToFill+spaceDim,0.);
7701 if(type!=INTERP_KERNEL::NORM_POLYHED)
7703 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7705 if(*conn>=0 && *conn<nbOfNodes)
7706 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7709 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7710 throw INTERP_KERNEL::Exception(oss.str().c_str());
7713 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7714 if(nbOfNodesInCell>0)
7715 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7718 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7719 throw INTERP_KERNEL::Exception(oss.str().c_str());
7724 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7726 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7728 if(*it>=0 && *it<nbOfNodes)
7729 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7732 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7733 throw INTERP_KERNEL::Exception(oss.str().c_str());
7737 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7740 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7741 throw INTERP_KERNEL::Exception(oss.str().c_str());
7749 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7750 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7751 * are specified via an array of cell ids.
7752 * \warning Validity of the specified cell ids is not checked!
7753 * Valid range is [ 0, \a this->getNumberOfCells() ).
7754 * \param [in] begin - an array of cell ids of interest.
7755 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7756 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7757 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7758 * caller is to delete this array using decrRef() as it is no more needed.
7759 * \throw If the coordinates array is not set.
7760 * \throw If the nodal connectivity of cells is not defined.
7762 * \if ENABLE_EXAMPLES
7763 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7764 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7767 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7769 DataArrayDouble *ret=DataArrayDouble::New();
7770 int spaceDim=getSpaceDimension();
7771 int nbOfTuple=(int)std::distance(begin,end);
7772 ret->alloc(nbOfTuple,spaceDim);
7773 double *ptToFill=ret->getPointer();
7774 double *tmp=new double[spaceDim];
7775 const int *nodal=_nodal_connec->getConstPointer();
7776 const int *nodalI=_nodal_connec_index->getConstPointer();
7777 const double *coor=_coords->getConstPointer();
7778 for(const int *w=begin;w!=end;w++)
7780 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7781 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7789 * 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".
7790 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7791 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7792 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7793 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7795 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7796 * \throw If spaceDim!=3 or meshDim!=2.
7797 * \throw If connectivity of \a this is invalid.
7798 * \throw If connectivity of a cell in \a this points to an invalid node.
7800 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7802 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7803 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7804 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7805 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7806 ret->alloc(nbOfCells,4);
7807 double *retPtr(ret->getPointer());
7808 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7809 const double *coor(_coords->begin());
7810 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7812 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7813 if(nodalI[1]-nodalI[0]>=3)
7815 for(int j=0;j<3;j++)
7817 int nodeId(nodal[nodalI[0]+1+j]);
7818 if(nodeId>=0 && nodeId<nbOfNodes)
7819 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7822 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7823 throw INTERP_KERNEL::Exception(oss.str().c_str());
7829 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7830 throw INTERP_KERNEL::Exception(oss.str().c_str());
7832 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7833 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7839 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7842 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7845 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7846 da->checkAllocated();
7847 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7849 int nbOfTuples=da->getNumberOfTuples();
7850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7851 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7852 c->alloc(2*nbOfTuples,1);
7853 cI->alloc(nbOfTuples+1,1);
7854 int *cp=c->getPointer();
7855 int *cip=cI->getPointer();
7857 for(int i=0;i<nbOfTuples;i++)
7859 *cp++=INTERP_KERNEL::NORM_POINT1;
7863 ret->setConnectivity(c,cI,true);
7867 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7868 * Cells and nodes of
7869 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7870 * \param [in] mesh1 - the first mesh.
7871 * \param [in] mesh2 - the second mesh.
7872 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7873 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7874 * is no more needed.
7875 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7876 * \throw If the coordinates array is not set in none of the meshes.
7877 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7878 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7880 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7882 std::vector<const MEDCouplingUMesh *> tmp(2);
7883 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7884 return MergeUMeshes(tmp);
7888 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7889 * Cells and nodes of
7890 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7891 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7892 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7893 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7894 * is no more needed.
7895 * \throw If \a a.size() == 0.
7896 * \throw If \a a[ *i* ] == NULL.
7897 * \throw If the coordinates array is not set in none of the meshes.
7898 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7899 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7901 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7903 std::size_t sz=a.size();
7905 return MergeUMeshesLL(a);
7906 for(std::size_t ii=0;ii<sz;ii++)
7909 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7910 throw INTERP_KERNEL::Exception(oss.str().c_str());
7912 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7913 std::vector< const MEDCouplingUMesh * > aa(sz);
7915 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7917 const MEDCouplingUMesh *cur=a[i];
7918 const DataArrayDouble *coo=cur->getCoords();
7920 spaceDim=coo->getNumberOfComponents();
7923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7924 for(std::size_t i=0;i<sz;i++)
7926 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7929 return MergeUMeshesLL(aa);
7934 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7938 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7939 int meshDim=(*it)->getMeshDimension();
7940 int nbOfCells=(*it)->getNumberOfCells();
7941 int meshLgth=(*it++)->getMeshLength();
7942 for(;it!=a.end();it++)
7944 if(meshDim!=(*it)->getMeshDimension())
7945 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7946 nbOfCells+=(*it)->getNumberOfCells();
7947 meshLgth+=(*it)->getMeshLength();
7949 std::vector<const MEDCouplingPointSet *> aps(a.size());
7950 std::copy(a.begin(),a.end(),aps.begin());
7951 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7952 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7953 ret->setCoords(pts);
7954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7955 c->alloc(meshLgth,1);
7956 int *cPtr=c->getPointer();
7957 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7958 cI->alloc(nbOfCells+1,1);
7959 int *cIPtr=cI->getPointer();
7963 for(it=a.begin();it!=a.end();it++)
7965 int curNbOfCell=(*it)->getNumberOfCells();
7966 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7967 const int *curC=(*it)->_nodal_connec->getConstPointer();
7968 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7969 for(int j=0;j<curNbOfCell;j++)
7971 const int *src=curC+curCI[j];
7973 for(;src!=curC+curCI[j+1];src++,cPtr++)
7981 offset+=curCI[curNbOfCell];
7982 offset2+=(*it)->getNumberOfNodes();
7985 ret->setConnectivity(c,cI,true);
7992 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7993 * dimension and sharing the node coordinates array.
7994 * All cells of the first mesh precede all cells of the second mesh
7995 * within the result mesh.
7996 * \param [in] mesh1 - the first mesh.
7997 * \param [in] mesh2 - the second mesh.
7998 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7999 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8000 * is no more needed.
8001 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8002 * \throw If the meshes do not share the node coordinates array.
8003 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8004 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8006 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8008 std::vector<const MEDCouplingUMesh *> tmp(2);
8009 tmp[0]=mesh1; tmp[1]=mesh2;
8010 return MergeUMeshesOnSameCoords(tmp);
8014 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8015 * dimension and sharing the node coordinates array.
8016 * All cells of the *i*-th mesh precede all cells of the
8017 * (*i*+1)-th mesh within the result mesh.
8018 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8019 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8020 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8021 * is no more needed.
8022 * \throw If \a a.size() == 0.
8023 * \throw If \a a[ *i* ] == NULL.
8024 * \throw If the meshes do not share the node coordinates array.
8025 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
8026 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8028 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8031 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8032 for(std::size_t ii=0;ii<meshes.size();ii++)
8035 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8036 throw INTERP_KERNEL::Exception(oss.str().c_str());
8038 const DataArrayDouble *coords=meshes.front()->getCoords();
8039 int meshDim=meshes.front()->getMeshDimension();
8040 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8042 int meshIndexLgth=0;
8043 for(;iter!=meshes.end();iter++)
8045 if(coords!=(*iter)->getCoords())
8046 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8047 if(meshDim!=(*iter)->getMeshDimension())
8048 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8049 meshLgth+=(*iter)->getMeshLength();
8050 meshIndexLgth+=(*iter)->getNumberOfCells();
8052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8053 nodal->alloc(meshLgth,1);
8054 int *nodalPtr=nodal->getPointer();
8055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8056 nodalIndex->alloc(meshIndexLgth+1,1);
8057 int *nodalIndexPtr=nodalIndex->getPointer();
8059 for(iter=meshes.begin();iter!=meshes.end();iter++)
8061 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8062 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8063 int nbOfCells=(*iter)->getNumberOfCells();
8064 int meshLgth2=(*iter)->getMeshLength();
8065 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8066 if(iter!=meshes.begin())
8067 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8069 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8072 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8073 ret->setName("merge");
8074 ret->setMeshDimension(meshDim);
8075 ret->setConnectivity(nodal,nodalIndex,true);
8076 ret->setCoords(coords);
8081 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8082 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8083 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8084 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8085 * New" mode are returned for each input mesh.
8086 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8087 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8088 * valid values [0,1,2], see zipConnectivityTraducer().
8089 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8090 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8091 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8093 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8094 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8095 * is no more needed.
8096 * \throw If \a meshes.size() == 0.
8097 * \throw If \a meshes[ *i* ] == NULL.
8098 * \throw If the meshes do not share the node coordinates array.
8099 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8100 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8101 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8102 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8104 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8106 //All checks are delegated to MergeUMeshesOnSameCoords
8107 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8109 corr.resize(meshes.size());
8110 std::size_t nbOfMeshes=meshes.size();
8112 const int *o2nPtr=o2n->getConstPointer();
8113 for(std::size_t i=0;i<nbOfMeshes;i++)
8115 DataArrayInt *tmp=DataArrayInt::New();
8116 int curNbOfCells=meshes[i]->getNumberOfCells();
8117 tmp->alloc(curNbOfCells,1);
8118 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8119 offset+=curNbOfCells;
8120 tmp->setName(meshes[i]->getName());
8127 * Makes all given meshes share the nodal connectivity array. The common connectivity
8128 * array is created by concatenating the connectivity arrays of all given meshes. All
8129 * the given meshes must be of the same space dimension but dimension of cells **can
8130 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8131 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8132 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8133 * \param [in,out] meshes - a vector of meshes to update.
8134 * \throw If any of \a meshes is NULL.
8135 * \throw If the coordinates array is not set in any of \a meshes.
8136 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8137 * \throw If \a meshes are of different space dimension.
8139 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8141 std::size_t sz=meshes.size();
8144 std::vector< const DataArrayDouble * > coords(meshes.size());
8145 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8146 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8150 (*it)->checkConnectivityFullyDefined();
8151 const DataArrayDouble *coo=(*it)->getCoords();
8156 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8157 oss << " has no coordinate array defined !";
8158 throw INTERP_KERNEL::Exception(oss.str().c_str());
8163 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8164 oss << " is null !";
8165 throw INTERP_KERNEL::Exception(oss.str().c_str());
8168 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8169 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8170 int offset=(*it)->getNumberOfNodes();
8171 (*it++)->setCoords(res);
8172 for(;it!=meshes.end();it++)
8174 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8175 (*it)->setCoords(res);
8176 (*it)->shiftNodeNumbersInConn(offset);
8177 offset+=oldNumberOfNodes;
8182 * Merges nodes coincident with a given precision within all given meshes that share
8183 * the nodal connectivity array. The given meshes **can be of different** mesh
8184 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8185 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8186 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8187 * \param [in,out] meshes - a vector of meshes to update.
8188 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8189 * \throw If any of \a meshes is NULL.
8190 * \throw If the \a meshes do not share the same node coordinates array.
8191 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8193 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8197 std::set<const DataArrayDouble *> s;
8198 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8201 s.insert((*it)->getCoords());
8204 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 !";
8205 throw INTERP_KERNEL::Exception(oss.str().c_str());
8210 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 !";
8211 throw INTERP_KERNEL::Exception(oss.str().c_str());
8213 const DataArrayDouble *coo=*(s.begin());
8217 DataArrayInt *comm,*commI;
8218 coo->findCommonTuples(eps,-1,comm,commI);
8219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8220 int oldNbOfNodes=coo->getNumberOfTuples();
8222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8223 if(oldNbOfNodes==newNbOfNodes)
8225 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8226 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8228 (*it)->renumberNodesInConn(o2n->getConstPointer());
8229 (*it)->setCoords(newCoords);
8234 * 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.
8235 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8236 * \param isQuad specifies the policy of connectivity.
8237 * @ret in/out parameter in which the result will be append
8239 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8241 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8242 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8243 ret.push_back(cm.getExtrudedType());
8244 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8247 case INTERP_KERNEL::NORM_POINT1:
8249 ret.push_back(connBg[1]);
8250 ret.push_back(connBg[1]+nbOfNodesPerLev);
8253 case INTERP_KERNEL::NORM_SEG2:
8255 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8256 ret.insert(ret.end(),conn,conn+4);
8259 case INTERP_KERNEL::NORM_SEG3:
8261 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8262 ret.insert(ret.end(),conn,conn+8);
8265 case INTERP_KERNEL::NORM_QUAD4:
8267 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8268 ret.insert(ret.end(),conn,conn+8);
8271 case INTERP_KERNEL::NORM_TRI3:
8273 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8274 ret.insert(ret.end(),conn,conn+6);
8277 case INTERP_KERNEL::NORM_TRI6:
8279 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,
8280 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8281 ret.insert(ret.end(),conn,conn+15);
8284 case INTERP_KERNEL::NORM_QUAD8:
8287 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8288 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8289 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8291 ret.insert(ret.end(),conn,conn+20);
8294 case INTERP_KERNEL::NORM_POLYGON:
8296 std::back_insert_iterator< std::vector<int> > ii(ret);
8297 std::copy(connBg+1,connEnd,ii);
8299 std::reverse_iterator<const int *> rConnBg(connEnd);
8300 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8301 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8302 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8303 for(std::size_t i=0;i<nbOfRadFaces;i++)
8306 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8307 std::copy(conn,conn+4,ii);
8312 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8317 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8319 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8322 double v[3]={0.,0.,0.};
8323 std::size_t sz=std::distance(begin,end);
8328 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];
8329 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8330 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8332 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8334 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8335 // SEG3 forming a circle):
8336 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8338 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8339 for(std::size_t j=0;j<sz;j++)
8341 if (j%2) // current point i is quadratic, next point i+1 is standard
8344 ip1 = (j+1)%sz; // ip1 = "i+1"
8346 else // current point i is standard, next point i+1 is quadratic
8351 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8352 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8353 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8355 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8361 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8363 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8365 std::vector<std::pair<int,int> > edges;
8366 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8367 const int *bgFace=begin;
8368 for(std::size_t i=0;i<nbOfFaces;i++)
8370 const int *endFace=std::find(bgFace+1,end,-1);
8371 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8372 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8374 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8375 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8377 edges.push_back(p1);
8381 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8385 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8387 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8389 double vec0[3],vec1[3];
8390 std::size_t sz=std::distance(begin,end);
8392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8393 int nbOfNodes=(int)sz/2;
8394 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8395 const double *pt0=coords+3*begin[0];
8396 const double *pt1=coords+3*begin[nbOfNodes];
8397 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8398 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8401 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8403 std::size_t sz=std::distance(begin,end);
8404 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8405 std::size_t nbOfNodes(sz/2);
8406 std::copy(begin,end,(int *)tmp);
8407 for(std::size_t j=1;j<nbOfNodes;j++)
8409 begin[j]=tmp[nbOfNodes-j];
8410 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8414 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8416 std::size_t sz=std::distance(begin,end);
8418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8419 double vec0[3],vec1[3];
8420 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8421 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];
8422 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;
8425 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8427 std::size_t sz=std::distance(begin,end);
8429 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8431 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8432 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8433 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8437 * 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 )
8438 * 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
8441 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8442 * \param [in] coords the coordinates with nb of components exactly equal to 3
8443 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8444 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8445 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8447 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8449 int nbFaces=std::count(begin+1,end,-1)+1;
8450 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8451 double *vPtr=v->getPointer();
8452 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8453 double *pPtr=p->getPointer();
8454 const int *stFaceConn=begin+1;
8455 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8457 const int *endFaceConn=std::find(stFaceConn,end,-1);
8458 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8459 stFaceConn=endFaceConn+1;
8461 pPtr=p->getPointer(); vPtr=v->getPointer();
8462 DataArrayInt *comm1=0,*commI1=0;
8463 v->findCommonTuples(eps,-1,comm1,commI1);
8464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8465 const int *comm1Ptr=comm1->getConstPointer();
8466 const int *commI1Ptr=commI1->getConstPointer();
8467 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8468 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8470 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8471 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8472 mm->finishInsertingCells();
8474 for(int i=0;i<nbOfGrps1;i++)
8476 int vecId=comm1Ptr[commI1Ptr[i]];
8477 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8478 DataArrayInt *comm2=0,*commI2=0;
8479 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8481 const int *comm2Ptr=comm2->getConstPointer();
8482 const int *commI2Ptr=commI2->getConstPointer();
8483 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8484 for(int j=0;j<nbOfGrps2;j++)
8486 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8488 res->insertAtTheEnd(begin,end);
8489 res->pushBackSilent(-1);
8493 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8495 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8496 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8497 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8498 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8499 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8500 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8501 const int *idsNodePtr=idsNode->getConstPointer();
8502 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];
8503 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8504 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8505 if(std::abs(norm)>eps)
8507 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8508 mm3->rotate(center,vec,angle);
8510 mm3->changeSpaceDimension(2);
8511 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8512 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8513 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8514 int nbOfCells=mm4->getNumberOfCells();
8515 for(int k=0;k<nbOfCells;k++)
8518 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8519 res->pushBackSilent(idsNodePtr[*work]);
8520 res->pushBackSilent(-1);
8525 res->popBackSilent();
8529 * 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
8530 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8532 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8533 * \param [in] coords coordinates expected to have 3 components.
8534 * \param [in] begin start of the nodal connectivity of the face.
8535 * \param [in] end end of the nodal connectivity (excluded) of the face.
8536 * \param [out] v the normalized vector of size 3
8537 * \param [out] p the pos of plane
8539 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8541 std::size_t nbPoints=std::distance(begin,end);
8543 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8544 double vec[3]={0.,0.,0.};
8546 bool refFound=false;
8547 for(;j<nbPoints-1 && !refFound;j++)
8549 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8550 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8551 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8552 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8556 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8559 for(std::size_t i=j;i<nbPoints-1;i++)
8562 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8563 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8564 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8565 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8568 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8569 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];
8570 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8573 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8574 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8578 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8582 * This method tries to obtain a well oriented polyhedron.
8583 * If the algorithm fails, an exception will be thrown.
8585 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8587 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8588 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8589 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8591 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8592 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8593 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8595 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8598 std::size_t smthChanged=0;
8599 for(std::size_t i=0;i<nbOfFaces;i++)
8601 endFace=std::find(bgFace+1,end,-1);
8602 nbOfEdgesInFace=std::distance(bgFace,endFace);
8606 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8608 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8609 std::pair<int,int> p2(p1.second,p1.first);
8610 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8611 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8612 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8617 std::reverse(bgFace+1,endFace);
8618 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8620 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8621 std::pair<int,int> p2(p1.second,p1.first);
8622 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8623 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8624 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8625 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8626 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8627 if(it!=edgesOK.end())
8630 edgesFinished.push_back(p1);
8633 edgesOK.push_back(p1);
8640 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8642 if(!edgesOK.empty())
8643 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8644 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8645 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8647 for(std::size_t i=0;i<nbOfFaces;i++)
8649 endFace=std::find(bgFace+1,end,-1);
8650 std::reverse(bgFace+1,endFace);
8656 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8658 int nbOfNodesExpected(skin->getNumberOfNodes());
8659 const int *n2oPtr(n2o->getConstPointer());
8660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8661 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8662 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8663 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8664 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8666 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8667 if(nbOfNodesExpected<1)
8669 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8670 *work++=n2oPtr[prevNode];
8671 for(int i=1;i<nbOfNodesExpected;i++)
8673 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8675 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8676 conn.erase(prevNode);
8679 int curNode(*(conn.begin()));
8680 *work++=n2oPtr[curNode];
8681 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8682 shar.erase(prevCell);
8685 prevCell=*(shar.begin());
8689 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8692 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8695 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8700 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8702 int nbOfNodesExpected(skin->getNumberOfNodes());
8703 int nbOfTurn(nbOfNodesExpected/2);
8704 const int *n2oPtr(n2o->getConstPointer());
8705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8706 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8707 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8708 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8709 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8711 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8712 if(nbOfNodesExpected<1)
8714 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8715 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8716 for(int i=1;i<nbOfTurn;i++)
8718 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8720 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8721 conn.erase(prevNode);
8724 int curNode(*(conn.begin()));
8725 *work=n2oPtr[curNode];
8726 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8727 shar.erase(prevCell);
8730 int curCell(*(shar.begin()));
8731 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8737 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8740 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8743 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8749 * This method makes the assumption spacedimension == meshdimension == 2.
8750 * This method works only for linear cells.
8752 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8754 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8756 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8758 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8759 int oldNbOfNodes(skin->getNumberOfNodes());
8760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8761 int nbOfNodesExpected(skin->getNumberOfNodes());
8762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8763 int nbCells(skin->getNumberOfCells());
8764 if(nbCells==nbOfNodesExpected)
8765 return buildUnionOf2DMeshLinear(skin,n2o);
8766 else if(2*nbCells==nbOfNodesExpected)
8767 return buildUnionOf2DMeshQuadratic(skin,n2o);
8769 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8773 * This method makes the assumption spacedimension == meshdimension == 3.
8774 * This method works only for linear cells.
8776 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8778 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8780 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8782 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8783 const int *conn=m->getNodalConnectivity()->getConstPointer();
8784 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8785 int nbOfCells=m->getNumberOfCells();
8786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8787 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8790 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8791 for(int i=1;i<nbOfCells;i++)
8794 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8800 * \brief Creates a graph of cell neighbors
8801 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8802 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8804 * - index: 0 3 5 6 6
8805 * - value: 1 2 3 2 3 3
8806 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8807 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8809 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8811 checkConnectivityFullyDefined();
8813 int meshDim = this->getMeshDimension();
8814 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8815 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8816 this->getReverseNodalConnectivity(revConn,indexr);
8817 const int* indexr_ptr=indexr->getConstPointer();
8818 const int* revConn_ptr=revConn->getConstPointer();
8820 const ParaMEDMEM::DataArrayInt* index;
8821 const ParaMEDMEM::DataArrayInt* conn;
8822 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8823 index=this->getNodalConnectivityIndex();
8824 int nbCells=this->getNumberOfCells();
8825 const int* index_ptr=index->getConstPointer();
8826 const int* conn_ptr=conn->getConstPointer();
8828 //creating graph arcs (cell to cell relations)
8829 //arcs are stored in terms of (index,value) notation
8832 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8833 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8835 //warning here one node have less than or equal effective number of cell with it
8836 //but cell could have more than effective nodes
8837 //because other equals nodes in other domain (with other global inode)
8838 std::vector <int> cell2cell_index(nbCells+1,0);
8839 std::vector <int> cell2cell;
8840 cell2cell.reserve(3*nbCells);
8842 for (int icell=0; icell<nbCells;icell++)
8844 std::map<int,int > counter;
8845 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8847 int inode=conn_ptr[iconn];
8848 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8850 int icell2=revConn_ptr[iconnr];
8851 std::map<int,int>::iterator iter=counter.find(icell2);
8852 if (iter!=counter.end()) (iter->second)++;
8853 else counter.insert(std::make_pair(icell2,1));
8856 for (std::map<int,int>::const_iterator iter=counter.begin();
8857 iter!=counter.end(); iter++)
8858 if (iter->second >= meshDim)
8860 cell2cell_index[icell+1]++;
8861 cell2cell.push_back(iter->first);
8866 cell2cell_index[0]=0;
8867 for (int icell=0; icell<nbCells;icell++)
8868 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8870 //filling up index and value to create skylinearray structure
8871 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8876 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8877 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8879 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8883 for(int i=0;i<nbOfNodesInCell;i++)
8884 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8885 else if(spaceDim==2)
8887 for(int i=0;i<nbOfNodesInCell;i++)
8889 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8894 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8897 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8899 int nbOfCells=getNumberOfCells();
8901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8902 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};
8903 ofs << " <" << getVTKDataSetType() << ">\n";
8904 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8905 ofs << " <PointData>\n" << pointData << std::endl;
8906 ofs << " </PointData>\n";
8907 ofs << " <CellData>\n" << cellData << std::endl;
8908 ofs << " </CellData>\n";
8909 ofs << " <Points>\n";
8910 if(getSpaceDimension()==3)
8911 _coords->writeVTK(ofs,8,"Points",byteData);
8914 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8915 coo->writeVTK(ofs,8,"Points",byteData);
8917 ofs << " </Points>\n";
8918 ofs << " <Cells>\n";
8919 const int *cPtr=_nodal_connec->getConstPointer();
8920 const int *cIPtr=_nodal_connec_index->getConstPointer();
8921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8923 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8925 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8926 int szFaceOffsets=0,szConn=0;
8927 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8930 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8933 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8934 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8938 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8939 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8940 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8941 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8942 w4=std::copy(c.begin(),c.end(),w4);
8945 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8946 types->writeVTK(ofs,8,"UInt8","types",byteData);
8947 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8948 if(szFaceOffsets!=0)
8949 {//presence of Polyhedra
8950 connectivity->reAlloc(szConn);
8951 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8953 w1=faces->getPointer();
8954 for(int i=0;i<nbOfCells;i++)
8955 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8957 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8959 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8960 for(int j=0;j<nbFaces;j++)
8962 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8963 *w1++=(int)std::distance(w6,w5);
8964 w1=std::copy(w6,w5,w1);
8968 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8970 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8971 ofs << " </Cells>\n";
8972 ofs << " </Piece>\n";
8973 ofs << " </" << getVTKDataSetType() << ">\n";
8976 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8978 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8980 { stream << " Not set !"; return ; }
8981 stream << " Mesh dimension : " << _mesh_dim << ".";
8985 { stream << " No coordinates set !"; return ; }
8986 if(!_coords->isAllocated())
8987 { stream << " Coordinates set but not allocated !"; return ; }
8988 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8989 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8990 if(!_nodal_connec_index)
8991 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8992 if(!_nodal_connec_index->isAllocated())
8993 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8994 int lgth=_nodal_connec_index->getNumberOfTuples();
8995 int cpt=_nodal_connec_index->getNumberOfComponents();
8996 if(cpt!=1 || lgth<1)
8998 stream << std::endl << "Number of cells : " << lgth-1 << ".";
9001 std::string MEDCouplingUMesh::getVTKDataSetType() const
9003 return std::string("UnstructuredGrid");
9006 std::string MEDCouplingUMesh::getVTKFileExtension() const
9008 return std::string("vtu");
9012 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9013 * returns a result mesh constituted by polygons.
9014 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9015 * all nodes from m2.
9016 * The meshes should be in 2D space. In
9017 * addition, returns two arrays mapping cells of the result mesh to cells of the input
9019 * \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
9020 * 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)
9021 * \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
9022 * 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)
9023 * \param [in] eps - precision used to detect coincident mesh entities.
9024 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9025 * cell an id of the cell of \a m1 it comes from. The caller is to delete
9026 * this array using decrRef() as it is no more needed.
9027 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9028 * cell an id of the cell of \a m2 it comes from. -1 value means that a
9029 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9030 * any cell of \a m2. The caller is to delete this array using decrRef() as
9031 * it is no more needed.
9032 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9033 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9034 * is no more needed.
9035 * \throw If the coordinates array is not set in any of the meshes.
9036 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
9037 * \throw If any of the meshes is not a 2D mesh in 2D space.
9039 * \sa conformize2D, mergeNodes
9041 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9042 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9045 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9046 m1->checkFullyDefined();
9047 m2->checkFullyDefined();
9048 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
9051 // Step 1: compute all edge intersections (new nodes)
9052 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9053 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9054 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9055 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9056 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9057 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9058 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9059 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9061 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9063 // Step 2: re-order newly created nodes according to the ordering found in m2
9064 std::vector< std::vector<int> > intersectEdge2;
9065 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9066 subDiv2.clear(); dd5=0; dd6=0;
9069 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9070 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9071 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9072 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9074 // Step 4: Prepare final result:
9075 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9076 addCooDa->alloc((int)(addCoo.size())/2,2);
9077 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9078 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9079 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9080 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9081 std::vector<const DataArrayDouble *> coordss(4);
9082 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9083 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9084 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9086 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9089 ret->setConnectivity(conn,connI,true);
9090 ret->setCoords(coo);
9091 cellNb1=c1.retn(); cellNb2=c2.retn();
9097 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9099 if(candidates.empty())
9101 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9103 const std::vector<int>& pool(intersectEdge1[*it]);
9104 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9105 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9110 tmp[0]=stop; tmp[1]=start;
9111 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9120 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,
9121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9123 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9124 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9125 int nCells(mesh1D->getNumberOfCells());
9126 if(nCells!=(int)intersectEdge2.size())
9127 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9128 const DataArrayDouble *coo2(mesh1D->getCoords());
9129 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9130 const double *coo2Ptr(coo2->begin());
9131 int offset1(coords1->getNumberOfTuples());
9132 int offset2(offset1+coo2->getNumberOfTuples());
9133 int offset3(offset2+addCoo.size()/2);
9134 std::vector<double> addCooQuad;
9135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9136 int tmp[4],cicnt(0),kk(0);
9137 for(int i=0;i<nCells;i++)
9139 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9140 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9141 const std::vector<int>& subEdges(intersectEdge2[i]);
9142 int nbSubEdge(subEdges.size()/2);
9143 for(int j=0;j<nbSubEdge;j++,kk++)
9145 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));
9146 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9147 INTERP_KERNEL::Edge *e2Ptr(e2);
9148 std::map<int,int>::const_iterator itm;
9149 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9151 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9152 itm=mergedNodes.find(subEdges[2*j]);
9153 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9154 itm=mergedNodes.find(subEdges[2*j+1]);
9155 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9156 tmp[3]=offset3+(int)addCooQuad.size()/2;
9158 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9160 cOut->insertAtTheEnd(tmp,tmp+4);
9161 ciOut->pushBackSilent(cicnt);
9165 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9166 itm=mergedNodes.find(subEdges[2*j]);
9167 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9168 itm=mergedNodes.find(subEdges[2*j+1]);
9169 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9171 cOut->insertAtTheEnd(tmp,tmp+3);
9172 ciOut->pushBackSilent(cicnt);
9175 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9177 idsInRetColinear->pushBackSilent(kk);
9178 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9183 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9184 ret->setConnectivity(cOut,ciOut,true);
9185 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9186 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9187 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9188 std::vector<const DataArrayDouble *> coordss(4);
9189 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9190 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9191 ret->setCoords(arr);
9195 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9197 std::vector<int> allEdges;
9198 for(const int *it2(descBg);it2!=descEnd;it2++)
9200 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9202 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9204 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9206 std::size_t nb(allEdges.size());
9208 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9209 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9210 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9211 ret->setCoords(coords);
9212 ret->allocateCells(1);
9213 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9214 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9215 connOut[kk]=allEdges[2*kk];
9216 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9220 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9222 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9223 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9225 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9226 if(sz!=std::distance(descBg,descEnd))
9227 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9228 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9229 std::vector<int> allEdges,centers;
9230 const double *coordsPtr(coords->begin());
9231 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9232 int offset(coords->getNumberOfTuples());
9233 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9235 INTERP_KERNEL::NormalizedCellType typeOfSon;
9236 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9237 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9239 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9241 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9243 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9245 {//the current edge has been subsplit -> create corresponding centers.
9246 std::size_t nbOfCentersToAppend(edge1.size()/2);
9247 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9248 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9249 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9250 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9253 const double *aa(coordsPtr+2*(*it3++));
9254 const double *bb(coordsPtr+2*(*it3++));
9255 ee->getMiddleOfPoints(aa,bb,tmpp);
9256 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9257 centers.push_back(offset+k);
9261 std::size_t nb(allEdges.size());
9263 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9264 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9265 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9267 ret->setCoords(coords);
9270 addCoo->rearrange(2);
9271 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9272 ret->setCoords(addCoo);
9274 ret->allocateCells(1);
9275 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9276 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9277 connOut[kk]=allEdges[2*kk];
9278 connOut.insert(connOut.end(),centers.begin(),centers.end());
9279 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9284 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9287 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9289 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9291 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9292 if(!cm.isQuadratic())
9293 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9295 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9298 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9301 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9303 const INTERP_KERNEL::Edge *ee(*it);
9304 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9308 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9311 const double *coo(mesh2D->getCoords()->begin());
9312 std::size_t sz(conn.size());
9313 std::vector<double> addCoo;
9314 std::vector<int> conn2(conn);
9315 int offset(mesh2D->getNumberOfNodes());
9316 for(std::size_t i=0;i<sz;i++)
9319 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9320 addCoo.insert(addCoo.end(),tmp,tmp+2);
9321 conn2.push_back(offset+(int)i);
9323 mesh2D->getCoords()->rearrange(1);
9324 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9325 mesh2D->getCoords()->rearrange(2);
9326 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9331 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9333 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9334 * a set of edges defined in \a splitMesh1D.
9336 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9337 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9339 std::size_t nb(edge1Bis.size()/2);
9340 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9341 int iEnd(splitMesh1D->getNumberOfCells());
9343 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9345 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9346 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9347 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9350 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9351 out0.resize(1); out1.resize(1);
9352 std::vector<int>& connOut(out0[0]);
9353 connOut.resize(nbOfEdgesOf2DCellSplit);
9354 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9355 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9356 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9358 connOut[kk]=edge1Bis[2*kk];
9359 edgesPtr[kk]=edge1BisPtr[2*kk];
9364 // [i,iEnd[ contains the
9365 out0.resize(2); out1.resize(2);
9366 std::vector<int>& connOutLeft(out0[0]);
9367 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9368 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9369 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9370 for(std::size_t k=ii;k<jj+1;k++)
9371 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9372 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9373 for(int ik=0;ik<iEnd;ik++)
9375 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9376 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9379 for(int ik=iEnd-1;ik>=0;ik--)
9380 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9381 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9382 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9383 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9384 for(int ik=0;ik<iEnd;ik++)
9385 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9386 eright.insert(eright.end(),ees.begin(),ees.end());
9398 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9400 std::vector<int> _edges;
9401 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9404 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9406 std::size_t nbe(edges.size());
9407 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9408 for(std::size_t i=0;i<nbe;i++)
9410 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9411 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9413 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9414 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9415 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9421 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9422 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9423 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9424 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9425 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9429 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9430 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9435 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9437 const MEDCouplingUMesh *mesh(_mesh);
9443 { _left++; _right++; return ; }
9446 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9447 if((isLeft && isRight) || (!isLeft && !isRight))
9448 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9459 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9460 if((isLeft && isRight) || (!isLeft && !isRight))
9461 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9476 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9478 const MEDCouplingUMesh *mesh(_mesh);
9481 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9484 {// not fully splitting cell case
9485 if(mesh2D->getNumberOfCells()==1)
9486 {//little optimization. 1 cell no need to find in which cell mesh is !
9487 neighbors[0]=offset; neighbors[1]=offset;
9492 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9493 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9495 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9496 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9501 class VectorOfCellInfo
9504 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9505 std::size_t size() const { return _pool.size(); }
9506 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9507 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);
9508 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9509 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9510 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9511 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9513 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9514 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9515 const CellInfo& get(int pos) const;
9516 CellInfo& get(int pos);
9518 std::vector<CellInfo> _pool;
9519 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9520 std::vector<EdgeInfo> _edge_info;
9523 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9525 _pool[0]._edges=edges;
9526 _pool[0]._edges_ptr=edgesPtr;
9529 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9532 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9535 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9537 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9538 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9539 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9542 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)
9544 get(pos);//to check pos
9545 bool isFast(pos==0 && _pool.size()==1);
9546 std::size_t sz(edges.size());
9547 // dealing with edges
9549 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9551 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9553 std::vector<CellInfo> pool(_pool.size()-1+sz);
9554 for(int i=0;i<pos;i++)
9556 for(std::size_t j=0;j<sz;j++)
9557 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9558 for(int i=pos+1;i<(int)_pool.size();i++)
9559 pool[i+sz-1]=_pool[i];
9563 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9571 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9574 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9578 if(pos<_ze_mesh->getNumberOfCells()-1)
9580 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9583 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9584 for(std::size_t j=0;j<ms2.size();j++)
9586 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9589 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9591 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9594 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9597 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9599 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9601 if((*it).isInMyRange(pos))
9604 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9607 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9609 get(pos);//to check;
9610 if(_edge_info.empty())
9612 std::size_t sz(_edge_info.size()-1);
9613 for(std::size_t i=0;i<sz;i++)
9614 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9617 const CellInfo& VectorOfCellInfo::get(int pos) const
9619 if(pos<0 || pos>=(int)_pool.size())
9620 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9624 CellInfo& VectorOfCellInfo::get(int pos)
9626 if(pos<0 || pos>=(int)_pool.size())
9627 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9633 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9634 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9636 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9638 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9640 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9642 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9645 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9646 if(nbCellsInSplitMesh1D==0)
9647 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9648 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9649 std::size_t nb(allEdges.size()),jj;
9651 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9652 std::vector<int> edge1Bis(nb*2);
9653 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9654 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9655 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9656 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9657 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9659 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9660 int *idsLeftRightPtr(idsLeftRight->getPointer());
9661 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9662 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9663 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9665 for(;iEnd<nbCellsInSplitMesh1D;)
9667 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9673 if(iEnd<nbCellsInSplitMesh1D)
9676 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9677 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9679 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9680 retTmp->setCoords(splitMesh1D->getCoords());
9681 retTmp->allocateCells();
9683 std::vector< std::vector<int> > out0;
9684 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9686 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9687 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9688 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9689 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9693 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9694 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9695 return pool.getZeMesh().retn();
9698 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9699 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9702 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9704 std::vector<int> allEdges;
9705 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9706 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9708 int edgeId(std::abs(*it)-1);
9709 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9710 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9711 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9713 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9715 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9716 std::size_t sz(edge1.size());
9717 for(std::size_t cnt=0;cnt<sz;cnt++)
9718 allEdgesPtr.push_back(ee);
9721 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9724 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9726 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9727 {//easy case comparison not
9728 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9730 else if(typ1.isQuadratic() && typ2.isQuadratic())
9732 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9735 if(conn1[2]==conn2[2])
9737 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9738 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9742 {//only one is quadratic
9743 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9746 const double *a(0),*bb(0),*be(0);
9747 if(typ1.isQuadratic())
9749 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9753 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9755 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9756 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9762 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9763 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9765 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9767 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9769 if(candidatesIn2DEnd==candidatesIn2DBg)
9770 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9771 const double *coo(mesh2DSplit->getCoords()->begin());
9772 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9773 return *candidatesIn2DBg;
9774 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9775 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9776 if(cellIdInMesh1DSplitRelative<0)
9777 cur1D->changeOrientationOfCells();
9778 const int *c1D(cur1D->getNodalConnectivity()->begin());
9779 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9780 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9782 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9783 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9784 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9785 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9786 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9787 for(unsigned it2=0;it2<sz;it2++)
9789 INTERP_KERNEL::NormalizedCellType typeOfSon;
9790 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9791 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9792 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9796 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9802 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9803 * 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
9804 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9805 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9807 * \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
9808 * 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)
9809 * \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
9810 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9811 * \param [in] eps - precision used to perform intersections and localization operations.
9812 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9813 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9814 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9815 * 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.
9816 * \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
9817 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9818 * 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.
9820 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9822 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9824 if(!mesh2D || !mesh1D)
9825 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9826 mesh2D->checkFullyDefined();
9827 mesh1D->checkFullyDefined();
9828 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9829 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9831 // Step 1: compute all edge intersections (new nodes)
9832 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9833 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9834 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9835 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9837 // Build desc connectivity
9838 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9839 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9840 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9841 std::map<int,int> mergedNodes;
9842 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9843 // use mergeNodes to fix intersectEdge1
9844 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9846 std::size_t n((*it0).size()/2);
9847 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9848 std::map<int,int>::const_iterator it1;
9849 it1=mergedNodes.find(eltStart);
9850 if(it1!=mergedNodes.end())
9851 (*it0)[0]=(*it1).second;
9852 it1=mergedNodes.find(eltEnd);
9853 if(it1!=mergedNodes.end())
9854 (*it0)[2*n-1]=(*it1).second;
9857 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9858 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9859 // Step 2: re-order newly created nodes according to the ordering found in m2
9860 std::vector< std::vector<int> > intersectEdge2;
9861 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9863 // Step 3: compute splitMesh1D
9864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9866 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9867 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9869 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9870 // deal with cells in mesh2D that are not cut but only some of their edges are
9871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9872 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9873 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9874 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
9875 if(!idsInDesc2DToBeRefined->empty())
9877 DataArrayInt *out0(0),*outi0(0);
9878 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9881 out0s=out0s->buildUnique();
9885 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9886 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9888 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9890 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9891 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9892 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9894 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9895 if((DataArrayInt *)out0s)
9896 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9897 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9898 // OK all is ready to insert in ret2 mesh
9899 if(!untouchedCells->empty())
9900 {// the most easy part, cells in mesh2D not impacted at all
9901 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9902 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9903 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9905 if((DataArrayInt *)out0s)
9906 {// here dealing with cells in out0s but not in cellsToBeModified
9907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9908 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9909 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9911 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9912 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9914 int offset(ret2->getNumberOfTuples());
9915 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9917 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9918 int kk(0),*ret3ptr(partOfRet3->getPointer());
9919 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9921 int faceId(std::abs(*it)-1);
9922 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9924 int tmp(fewModifiedCells->locateValue(*it2));
9927 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9928 ret3ptr[2*kk]=tmp+offset;
9929 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9930 ret3ptr[2*kk+1]=tmp+offset;
9933 {//the current edge is shared by a 2D cell that will be split just after
9934 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9935 ret3ptr[2*kk]=-(*it2+1);
9936 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9937 ret3ptr[2*kk+1]=-(*it2+1);
9941 m1Desc->setCoords(ret1->getCoords());
9942 ret1NonCol->setCoords(ret1->getCoords());
9943 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9944 if(!outMesh2DSplit.empty())
9946 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9947 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9948 (*itt)->setCoords(da);
9951 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9952 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9955 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9957 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9958 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9959 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));
9960 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9961 outMesh2DSplit.push_back(splitOfOneCell);
9962 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9963 ret2->pushBackSilent(*it);
9966 std::size_t nbOfMeshes(outMesh2DSplit.size());
9967 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9968 for(std::size_t i=0;i<nbOfMeshes;i++)
9969 tmp[i]=outMesh2DSplit[i];
9971 ret1->getCoords()->setInfoOnComponents(compNames);
9972 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9973 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9976 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9978 int old2DCellId(-ret3->getIJ(*it,0)-1);
9979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9980 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
9982 ret3->changeValue(std::numeric_limits<int>::max(),-1);
9985 splitMesh1D=ret1.retn();
9986 splitMesh2D=ret2D.retn();
9987 cellIdInMesh2D=ret2.retn();
9988 cellIdInMesh1D=ret3.retn();
9992 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9993 * (newly created) nodes corresponding to the edge intersections.
9995 * @param[out] cr, crI connectivity of the resulting mesh
9996 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9997 * TODO: describe input parameters
9999 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
10000 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
10001 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
10002 const std::vector<double>& addCoords,
10003 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10005 static const int SPACEDIM=2;
10006 const double *coo1(m1->getCoords()->getConstPointer());
10007 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
10008 int offset1(m1->getNumberOfNodes());
10009 const double *coo2(m2->getCoords()->getConstPointer());
10010 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
10011 int offset2(offset1+m2->getNumberOfNodes());
10012 int offset3(offset2+((int)addCoords.size())/2);
10013 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10014 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10015 // Here a BBTree on 2D-cells, not on segments:
10016 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10017 int ncell1(m1->getNumberOfCells());
10019 for(int i=0;i<ncell1;i++)
10021 std::vector<int> candidates2;
10022 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10023 std::map<INTERP_KERNEL::Node *,int> mapp;
10024 std::map<int,INTERP_KERNEL::Node *> mappRev;
10025 INTERP_KERNEL::QuadraticPolygon pol1;
10026 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10028 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10029 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10030 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10031 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10032 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10034 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
10035 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10036 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10037 for(it1.first();!it1.finished();it1.next())
10038 edges1.insert(it1.current()->getPtr());
10040 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10041 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10043 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10045 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10046 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10047 // Complete mapping with elements coming from the current cell it2 in mesh2:
10048 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10049 // pol2 is the new QP in the final merged result.
10050 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10051 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10054 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10056 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10057 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10058 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10059 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10061 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10062 // by m2 but that we still want to keep in the final result.
10063 if(!edges1.empty())
10067 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10069 catch(INTERP_KERNEL::Exception& e)
10071 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();
10072 throw INTERP_KERNEL::Exception(oss.str().c_str());
10075 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10076 (*it).second->decrRef();
10081 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10082 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10083 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10084 * The caller is to deal with the resulting DataArrayInt.
10085 * \throw If the coordinate array is not set.
10086 * \throw If the nodal connectivity of the cells is not defined.
10087 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10088 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10090 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10092 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10094 checkFullyDefined();
10095 if(getMeshDimension()!=1)
10096 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10098 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10101 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10102 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10103 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10105 const int * dsi(_dsi->getConstPointer());
10106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10108 if (dsii->getNumberOfTuples())
10109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10111 int nc(getNumberOfCells());
10112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10113 result->alloc(nc,1);
10115 // set of edges not used so far
10116 std::set<int> edgeSet;
10117 for (int i=0; i<nc; edgeSet.insert(i), i++);
10121 // while we have points with only one neighbor segments
10124 std::list<int> linePiece;
10125 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10126 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10128 // Fill the list forward (resp. backward) from the start segment:
10129 int activeSeg = startSeg;
10130 int prevPointId = -20;
10132 while (!edgeSet.empty())
10134 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10137 linePiece.push_back(activeSeg);
10139 linePiece.push_front(activeSeg);
10140 edgeSet.erase(activeSeg);
10143 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10144 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10145 if (dsi[ptId] == 1) // hitting the end of the line
10147 prevPointId = ptId;
10148 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10149 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10152 // Done, save final piece into DA:
10153 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10154 newIdx += linePiece.size();
10156 // identify next valid start segment (one which is not consumed)
10157 if(!edgeSet.empty())
10158 startSeg = *(edgeSet.begin());
10160 while (!edgeSet.empty());
10161 return result.retn();
10166 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10168 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10169 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10171 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10172 int v((*it).second);
10173 if(v==forbVal0 || v==forbVal1)
10175 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10176 isect.push_back(v);
10179 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10184 bool presenceOfOn(false);
10185 for(int i=0;i<sz;i++)
10187 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10188 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10190 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10191 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10193 return presenceOfOn;
10199 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10200 * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10201 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10202 * a minimal creation of new nodes is wanted.
10203 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10204 * nodes if a SEG3 is split without information of middle.
10205 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10206 * avoid to have a non conform mesh.
10208 * \return int - the number of new nodes created (in most of cases 0).
10210 * \throw If \a this is not coherent.
10211 * \throw If \a this has not spaceDim equal to 2.
10212 * \throw If \a this has not meshDim equal to 2.
10213 * \throw If some subcells needed to be split are orphan.
10214 * \sa MEDCouplingUMesh::conformize2D
10216 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10218 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10219 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10220 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10221 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10222 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10223 if(midOpt==0 && midOptI==0)
10225 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10228 else if(midOpt!=0 && midOptI!=0)
10229 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10235 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10236 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10237 * 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
10238 * 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).
10239 * 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.
10241 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10242 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10244 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10245 * This method expects that all nodes in \a this are not closer than \a eps.
10246 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10248 * \param [in] eps the relative error to detect merged edges.
10249 * \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
10250 * that the user is expected to deal with.
10252 * \throw If \a this is not coherent.
10253 * \throw If \a this has not spaceDim equal to 2.
10254 * \throw If \a this has not meshDim equal to 2.
10255 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10257 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10259 static const int SPACEDIM=2;
10261 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10262 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10264 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10265 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10266 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10267 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10268 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10269 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10270 std::vector<double> addCoo;
10271 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10272 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10273 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10274 for(int i=0;i<nDescCell;i++)
10276 std::vector<int> candidates;
10277 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10278 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10281 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10282 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10283 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10284 INTERP_KERNEL::MergePoints merge;
10285 INTERP_KERNEL::QuadraticPolygon c1,c2;
10286 e1->intersectWith(e2,merge,c1,c2);
10287 e1->decrRef(); e2->decrRef();
10288 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10289 overlapEdge[i].push_back(*it);
10290 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10291 overlapEdge[*it].push_back(i);
10294 // splitting done. sort intersect point in intersectEdge.
10295 std::vector< std::vector<int> > middle(nDescCell);
10296 int nbOf2DCellsToBeSplit(0);
10297 bool middleNeedsToBeUsed(false);
10298 std::vector<bool> cells2DToTreat(nDescCell,false);
10299 for(int i=0;i<nDescCell;i++)
10301 std::vector<int>& isect(intersectEdge[i]);
10302 int sz((int)isect.size());
10305 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10306 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10307 e->sortSubNodesAbs(coords,isect);
10312 int idx0(rdi[i]),idx1(rdi[i+1]);
10314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10315 if(!cells2DToTreat[rd[idx0]])
10317 cells2DToTreat[rd[idx0]]=true;
10318 nbOf2DCellsToBeSplit++;
10320 // try to reuse at most eventual 'middle' of SEG3
10321 std::vector<int>& mid(middle[i]);
10322 mid.resize(sz+1,-1);
10323 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10325 middleNeedsToBeUsed=true;
10326 const std::vector<int>& candidates(overlapEdge[i]);
10327 std::vector<int> trueCandidates;
10328 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10329 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10330 trueCandidates.push_back(*itc);
10331 int stNode(c[ci[i]+1]),endNode(isect[0]);
10332 for(int j=0;j<sz+1;j++)
10334 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10336 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10337 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10338 { mid[j]=*itc; break; }
10341 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10347 if(nbOf2DCellsToBeSplit==0)
10350 int *retPtr(ret->getPointer());
10351 for(int i=0;i<nCell;i++)
10352 if(cells2DToTreat[i])
10355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10356 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10357 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10358 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10359 if(middleNeedsToBeUsed)
10360 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10361 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10362 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10363 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.
10364 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10366 bool areNodesMerged; int newNbOfNodes;
10367 if(nbOfNodesCreated!=0)
10368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10374 * 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.
10375 * 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).
10376 * 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
10377 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10378 * 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
10379 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10381 * 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
10382 * using new instance, idem for coordinates.
10384 * 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.
10386 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10388 * \throw If \a this is not coherent.
10389 * \throw If \a this has not spaceDim equal to 2.
10390 * \throw If \a this has not meshDim equal to 2.
10392 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10394 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10398 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10399 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10400 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10401 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10402 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10403 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10405 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10406 const double *coords(_coords->begin());
10407 int *newciptr(newci->getPointer());
10408 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10410 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10411 ret->pushBackSilent(i);
10412 newciptr[1]=newc->getNumberOfTuples();
10417 if(!appendedCoords->empty())
10419 appendedCoords->rearrange(2);
10420 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10422 setCoords(newCoords);
10425 setConnectivity(newc,newci,true);
10430 * \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.
10431 * 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.
10432 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10433 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10434 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10435 * \param [out] addCoo - nodes to be append at the end
10436 * \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.
10438 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10439 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)
10441 static const int SPACEDIM=2;
10442 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10443 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10444 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10445 // Build BB tree of all edges in the tool mesh (second mesh)
10446 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10447 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10448 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10449 intersectEdge1.resize(nDescCell1);
10450 colinear2.resize(nDescCell2);
10451 subDiv2.resize(nDescCell2);
10452 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10454 std::vector<int> candidates1(1);
10455 int offset1(m1Desc->getNumberOfNodes());
10456 int offset2(offset1+m2Desc->getNumberOfNodes());
10457 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10459 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10460 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10461 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10463 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10464 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10465 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10467 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10468 // 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
10469 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10470 std::set<INTERP_KERNEL::Node *> nodes;
10471 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10472 std::size_t szz(nodes.size());
10473 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10474 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10475 for(std::size_t iii=0;iii<szz;iii++,itt++)
10476 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10477 // end of protection
10478 // Performs egde cutting:
10479 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10484 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10485 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10490 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10491 * It builds the descending connectivity of the two meshes, and then using a binary tree
10492 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10493 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10495 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10496 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10497 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10498 std::vector<double>& addCoo,
10499 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10501 // Build desc connectivity
10502 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10503 desc2=DataArrayInt::New();
10504 descIndx2=DataArrayInt::New();
10505 revDesc2=DataArrayInt::New();
10506 revDescIndx2=DataArrayInt::New();
10507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10509 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10510 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10511 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10512 std::map<int,int> notUsedMap;
10513 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10514 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10515 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10519 * This method performs the 2nd step of Partition of 2D mesh.
10520 * This method has 4 inputs :
10521 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10522 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10523 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10524 * 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'
10525 * Nodes end up lying consecutively on a cutted edge.
10526 * \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.
10527 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10528 * \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.
10529 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10530 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10532 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10533 const std::vector<double>& addCoo,
10534 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10536 int offset1=m1->getNumberOfNodes();
10537 int ncell=m2->getNumberOfCells();
10538 const int *c=m2->getNodalConnectivity()->getConstPointer();
10539 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10540 const double *coo=m2->getCoords()->getConstPointer();
10541 const double *cooBis=m1->getCoords()->getConstPointer();
10542 int offset2=offset1+m2->getNumberOfNodes();
10543 intersectEdge.resize(ncell);
10544 for(int i=0;i<ncell;i++,cI++)
10546 const std::vector<int>& divs=subDiv[i];
10547 int nnode=cI[1]-cI[0]-1;
10548 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10549 std::map<INTERP_KERNEL::Node *, int> mapp22;
10550 for(int j=0;j<nnode;j++)
10552 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10553 int nnid=c[(*cI)+j+1];
10554 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10555 mapp22[nn]=nnid+offset1;
10557 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10558 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10559 ((*it).second.first)->decrRef();
10560 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10561 std::map<INTERP_KERNEL::Node *,int> mapp3;
10562 for(std::size_t j=0;j<divs.size();j++)
10565 INTERP_KERNEL::Node *tmp=0;
10567 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10568 else if(id<offset2)
10569 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10571 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10575 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10576 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10583 * 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).
10584 * 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
10585 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10586 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10587 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10588 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10589 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10590 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10591 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10592 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10593 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10594 * \param [out] cut3DSuf input/output param.
10596 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10597 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10598 const int *desc, const int *descIndx,
10599 std::vector< std::pair<int,int> >& cut3DSurf)
10601 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10602 int nbOf3DSurfCell=(int)cut3DSurf.size();
10603 for(int i=0;i<nbOf3DSurfCell;i++)
10605 std::vector<int> res;
10606 int offset=descIndx[i];
10607 int nbOfSeg=descIndx[i+1]-offset;
10608 for(int j=0;j<nbOfSeg;j++)
10610 int edgeId=desc[offset+j];
10611 int status=cut3DCurve[edgeId];
10615 res.push_back(status);
10618 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10619 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10627 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10633 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10634 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10637 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10641 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10646 {// case when plane is on a multi colinear edge of a polyhedron
10647 if((int)res.size()==2*nbOfSeg)
10649 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10659 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10660 * 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).
10661 * 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
10662 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10663 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10664 * \param desc is the descending connectivity 3D->3DSurf
10665 * \param descIndx is the descending connectivity index 3D->3DSurf
10667 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10668 const int *desc, const int *descIndx,
10669 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10671 checkFullyDefined();
10672 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10673 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10674 const int *nodal3D=_nodal_connec->getConstPointer();
10675 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10676 int nbOfCells=getNumberOfCells();
10677 for(int i=0;i<nbOfCells;i++)
10679 std::map<int, std::set<int> > m;
10680 int offset=descIndx[i];
10681 int nbOfFaces=descIndx[i+1]-offset;
10684 for(int j=0;j<nbOfFaces;j++)
10686 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10687 if(p.first!=-1 && p.second!=-1)
10691 start=p.first; end=p.second;
10692 m[p.first].insert(p.second);
10693 m[p.second].insert(p.first);
10697 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10698 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10699 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10700 INTERP_KERNEL::NormalizedCellType cmsId;
10701 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10702 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10703 for(unsigned k=0;k<nbOfNodesSon;k++)
10705 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10706 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10713 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10717 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10718 const std::set<int>& s=(*it).second;
10719 std::set<int> s2; s2.insert(prev);
10721 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10724 int val=*s3.begin();
10725 conn.push_back(start);
10732 conn.push_back(end);
10735 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10736 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10737 cellIds->pushBackSilent(i);
10743 * 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
10744 * 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
10745 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10746 * 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
10747 * 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.
10749 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10751 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10753 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10756 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10757 if(cm.getDimension()==2)
10759 const int *node=nodalConnBg+1;
10760 int startNode=*node++;
10761 double refX=coords[2*startNode];
10762 for(;node!=nodalConnEnd;node++)
10764 if(coords[2*(*node)]<refX)
10767 refX=coords[2*startNode];
10770 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10774 double angle0=-M_PI/2;
10779 double angleNext=0.;
10780 while(nextNode!=startNode)
10784 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10786 if(*node!=tmpOut.back() && *node!=prevNode)
10788 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10789 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10794 res=angle0-angleM+2.*M_PI;
10803 if(nextNode!=startNode)
10805 angle0=angleNext-M_PI;
10808 prevNode=tmpOut.back();
10809 tmpOut.push_back(nextNode);
10812 std::vector<int> tmp3(2*(sz-1));
10813 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10814 std::copy(nodalConnBg+1,nodalConnEnd,it);
10815 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10817 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10820 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10822 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10827 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10828 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10836 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10840 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10841 * 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.
10843 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10844 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10845 * \param [in,out] arr array in which the remove operation will be done.
10846 * \param [in,out] arrIndx array in the remove operation will modify
10847 * \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])
10848 * \return true if \b arr and \b arrIndx have been modified, false if not.
10850 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10852 if(!arrIndx || !arr)
10853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10854 if(offsetForRemoval<0)
10855 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10856 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10857 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10858 int *arrIPtr=arrIndx->getPointer();
10860 int previousArrI=0;
10861 const int *arrPtr=arr->getConstPointer();
10862 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10863 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10865 if(*arrIPtr-previousArrI>offsetForRemoval)
10867 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10869 if(s.find(*work)==s.end())
10870 arrOut.push_back(*work);
10873 previousArrI=*arrIPtr;
10874 *arrIPtr=(int)arrOut.size();
10876 if(arr->getNumberOfTuples()==(int)arrOut.size())
10878 arr->alloc((int)arrOut.size(),1);
10879 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10884 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10885 * (\ref numbering-indirect).
10886 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10887 * The selection of extraction is done standardly in new2old format.
10888 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10890 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10891 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10892 * \param [in] arrIn arr origin array from which the extraction will be done.
10893 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10894 * \param [out] arrOut the resulting array
10895 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10896 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10898 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10899 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10901 if(!arrIn || !arrIndxIn)
10902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10903 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10904 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10905 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10906 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10907 const int *arrInPtr=arrIn->getConstPointer();
10908 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10909 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10912 int maxSizeOfArr=arrIn->getNumberOfTuples();
10913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10915 arrIo->alloc((int)(sz+1),1);
10916 const int *idsIt=idsOfSelectBg;
10917 int *work=arrIo->getPointer();
10920 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10922 if(*idsIt>=0 && *idsIt<nbOfGrps)
10923 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10926 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10927 throw INTERP_KERNEL::Exception(oss.str().c_str());
10933 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10934 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10935 throw INTERP_KERNEL::Exception(oss.str().c_str());
10938 arro->alloc(lgth,1);
10939 work=arro->getPointer();
10940 idsIt=idsOfSelectBg;
10941 for(std::size_t i=0;i<sz;i++,idsIt++)
10943 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10944 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10947 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10948 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10949 throw INTERP_KERNEL::Exception(oss.str().c_str());
10952 arrOut=arro.retn();
10953 arrIndexOut=arrIo.retn();
10957 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10958 * (\ref numbering-indirect).
10959 * 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 ).
10960 * The selection of extraction is done standardly in new2old format.
10961 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10963 * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10964 * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10965 * \param [in] idsOfSelectStep
10966 * \param [in] arrIn arr origin array from which the extraction will be done.
10967 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10968 * \param [out] arrOut the resulting array
10969 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10970 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10972 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10973 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10975 if(!arrIn || !arrIndxIn)
10976 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10977 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10978 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10980 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10981 const int *arrInPtr=arrIn->getConstPointer();
10982 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10983 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10986 int maxSizeOfArr=arrIn->getNumberOfTuples();
10987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10989 arrIo->alloc((int)(sz+1),1);
10990 int idsIt=idsOfSelectStart;
10991 int *work=arrIo->getPointer();
10994 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10996 if(idsIt>=0 && idsIt<nbOfGrps)
10997 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
11000 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11001 throw INTERP_KERNEL::Exception(oss.str().c_str());
11007 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11008 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11009 throw INTERP_KERNEL::Exception(oss.str().c_str());
11012 arro->alloc(lgth,1);
11013 work=arro->getPointer();
11014 idsIt=idsOfSelectStart;
11015 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11017 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11018 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11021 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11022 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11023 throw INTERP_KERNEL::Exception(oss.str().c_str());
11026 arrOut=arro.retn();
11027 arrIndexOut=arrIo.retn();
11031 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11032 * 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
11033 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11034 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11036 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11037 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11038 * \param [in] arrIn arr origin array from which the extraction will be done.
11039 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11040 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11041 * \param [in] srcArrIndex index array of \b srcArr
11042 * \param [out] arrOut the resulting array
11043 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11045 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11047 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11048 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11049 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11051 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11052 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11053 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11055 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11056 std::vector<bool> v(nbOfTuples,true);
11058 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11059 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11060 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11062 if(*it>=0 && *it<nbOfTuples)
11065 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11069 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11070 throw INTERP_KERNEL::Exception(oss.str().c_str());
11073 srcArrIndexPtr=srcArrIndex->getConstPointer();
11074 arrIo->alloc(nbOfTuples+1,1);
11075 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11076 const int *arrInPtr=arrIn->getConstPointer();
11077 const int *srcArrPtr=srcArr->getConstPointer();
11078 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11079 int *arroPtr=arro->getPointer();
11080 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11084 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11085 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11089 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11090 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11091 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11094 arrOut=arro.retn();
11095 arrIndexOut=arrIo.retn();
11099 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11100 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11102 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11103 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11104 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11105 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11106 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11107 * \param [in] srcArrIndex index array of \b srcArr
11109 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11111 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11112 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11114 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11116 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11117 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11118 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11119 int *arrInOutPtr=arrInOut->getPointer();
11120 const int *srcArrPtr=srcArr->getConstPointer();
11121 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11123 if(*it>=0 && *it<nbOfTuples)
11125 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11126 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11129 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] !";
11130 throw INTERP_KERNEL::Exception(oss.str().c_str());
11135 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11136 throw INTERP_KERNEL::Exception(oss.str().c_str());
11142 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11143 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11144 * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11145 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11146 * A negative value in \b arrIn means that it is ignored.
11147 * 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.
11149 * \param [in] arrIn arr origin array from which the extraction will be done.
11150 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11151 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11152 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11154 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11156 int seed=0,nbOfDepthPeelingPerformed=0;
11157 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11161 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11162 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11163 * 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]].
11164 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11165 * A negative value in \b arrIn means that it is ignored.
11166 * 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.
11167 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11168 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11169 * \param [in] arrIn arr origin array from which the extraction will be done.
11170 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11171 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11172 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11173 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11174 * \sa MEDCouplingUMesh::partitionBySpreadZone
11176 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11178 nbOfDepthPeelingPerformed=0;
11180 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11181 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11184 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11188 std::vector<bool> fetched(nbOfTuples,false);
11189 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11192 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11194 nbOfDepthPeelingPerformed=0;
11195 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11196 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11197 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11198 std::vector<bool> fetched2(nbOfTuples,false);
11200 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11202 if(*seedElt>=0 && *seedElt<nbOfTuples)
11203 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11205 { 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()); }
11207 const int *arrInPtr=arrIn->getConstPointer();
11208 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11209 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11210 std::vector<int> idsToFetch1(seedBg,seedEnd);
11211 std::vector<int> idsToFetch2;
11212 std::vector<int> *idsToFetch=&idsToFetch1;
11213 std::vector<int> *idsToFetchOther=&idsToFetch2;
11214 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11216 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11217 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11219 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11220 std::swap(idsToFetch,idsToFetchOther);
11221 idsToFetchOther->clear();
11222 nbOfDepthPeelingPerformed++;
11224 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11227 int *retPtr=ret->getPointer();
11228 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11235 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11236 * 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
11237 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11238 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11240 * \param [in] start begin of set of ids of the input extraction (included)
11241 * \param [in] end end of set of ids of the input extraction (excluded)
11242 * \param [in] step step of the set of ids in range mode.
11243 * \param [in] arrIn arr origin array from which the extraction will be done.
11244 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11245 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11246 * \param [in] srcArrIndex index array of \b srcArr
11247 * \param [out] arrOut the resulting array
11248 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11250 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11252 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11253 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11254 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11256 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11257 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11260 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11262 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11263 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11264 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11266 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11268 if(it>=0 && it<nbOfTuples)
11269 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11272 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11273 throw INTERP_KERNEL::Exception(oss.str().c_str());
11276 srcArrIndexPtr=srcArrIndex->getConstPointer();
11277 arrIo->alloc(nbOfTuples+1,1);
11278 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11279 const int *arrInPtr=arrIn->getConstPointer();
11280 const int *srcArrPtr=srcArr->getConstPointer();
11281 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11282 int *arroPtr=arro->getPointer();
11283 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11285 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11288 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11289 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11293 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11294 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11297 arrOut=arro.retn();
11298 arrIndexOut=arrIo.retn();
11302 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11303 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11305 * \param [in] start begin of set of ids of the input extraction (included)
11306 * \param [in] end end of set of ids of the input extraction (excluded)
11307 * \param [in] step step of the set of ids in range mode.
11308 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11309 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11310 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11311 * \param [in] srcArrIndex index array of \b srcArr
11313 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11315 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11316 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11318 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11319 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11320 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11321 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11322 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11323 int *arrInOutPtr=arrInOut->getPointer();
11324 const int *srcArrPtr=srcArr->getConstPointer();
11325 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11327 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11329 if(it>=0 && it<nbOfTuples)
11331 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11332 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11335 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11336 throw INTERP_KERNEL::Exception(oss.str().c_str());
11341 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11342 throw INTERP_KERNEL::Exception(oss.str().c_str());
11348 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11349 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11350 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11351 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11352 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11354 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11356 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11358 checkFullyDefined();
11359 int mdim=getMeshDimension();
11360 int spaceDim=getSpaceDimension();
11362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11363 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11364 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11365 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11366 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11367 ret->setCoords(getCoords());
11368 ret->allocateCells((int)partition.size());
11370 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11372 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11377 cell=tmp->buildUnionOf2DMesh();
11380 cell=tmp->buildUnionOf3DMesh();
11383 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11386 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11389 ret->finishInsertingCells();
11394 * This method partitions \b this into contiguous zone.
11395 * This method only needs a well defined connectivity. Coordinates are not considered here.
11396 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11398 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11400 int nbOfCellsCur=getNumberOfCells();
11401 std::vector<DataArrayInt *> ret;
11402 if(nbOfCellsCur<=0)
11404 DataArrayInt *neigh=0,*neighI=0;
11405 computeNeighborsOfCells(neigh,neighI);
11406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11407 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11408 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11410 while(seed<nbOfCellsCur)
11412 int nbOfPeelPerformed=0;
11413 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11414 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11416 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11417 ret.push_back((*it).retn());
11422 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11423 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11425 * \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.
11426 * \return a newly allocated DataArrayInt to be managed by the caller.
11427 * \throw In case of \a code has not the right format (typically of size 3*n)
11429 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11432 std::size_t nb=code.size()/3;
11433 if(code.size()%3!=0)
11434 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11435 ret->alloc((int)nb,2);
11436 int *retPtr=ret->getPointer();
11437 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11439 retPtr[0]=code[3*i+2];
11440 retPtr[1]=code[3*i+2]+code[3*i+1];
11446 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11447 * All cells in \a this are expected to be linear 3D cells.
11448 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11449 * It leads to an increase to number of cells.
11450 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11451 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11452 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11454 * \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.
11455 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11456 * \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.
11457 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11458 * an id of old cell producing it. The caller is to delete this array using
11459 * decrRef() as it is no more needed.
11460 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11462 * \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
11463 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11465 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11466 * \throw If \a this is not fully constituted with linear 3D cells.
11467 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11469 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11471 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11472 checkConnectivityFullyDefined();
11473 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11474 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11475 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11476 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11478 int *retPt(ret->getPointer());
11479 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11480 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11481 const int *oldc(_nodal_connec->begin());
11482 const int *oldci(_nodal_connec_index->begin());
11483 const double *coords(_coords->begin());
11484 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11486 std::vector<int> a; std::vector<double> b;
11487 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11488 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11489 const int *aa(&a[0]);
11492 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11494 *it=(-(*(it))-1+nbNodes);
11495 addPts->insertAtTheEnd(b.begin(),b.end());
11496 nbNodes+=(int)b.size()/3;
11498 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11499 newConn->insertAtTheEnd(aa,aa+4);
11501 if(!addPts->empty())
11503 addPts->rearrange(3);
11504 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11505 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11506 ret0->setCoords(addPts);
11510 nbOfAdditionalPoints=0;
11511 ret0->setCoords(getCoords());
11513 ret0->setNodalConnectivity(newConn);
11515 ret->computeOffsets2();
11516 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11517 return ret0.retn();
11521 * 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).
11523 * \sa MEDCouplingUMesh::split2DCells
11525 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11527 checkConnectivityFullyDefined();
11528 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11530 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11531 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11532 int prevPosOfCi(ciPtr[0]);
11533 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11535 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11536 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11537 for(int j=0;j<sz;j++)
11539 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11540 for(int k=0;k<sz2;k++)
11541 *cPtr++=subPtr[offset2+k];
11543 *cPtr++=oldConn[prevPosOfCi+j+2];
11546 prevPosOfCi=ciPtr[1];
11547 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11550 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11551 _nodal_connec->decrRef();
11552 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11555 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11561 int ret(nodesCnter++);
11563 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11564 addCoo.insertAtTheEnd(newPt,newPt+2);
11569 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11575 int ret(nodesCnter++);
11577 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11578 addCoo.insertAtTheEnd(newPt,newPt+2);
11586 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)
11589 int trueStart(start>=0?start:nbOfEdges+start);
11590 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11591 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11596 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11597 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11598 middles.push_back(tmp3+offset);
11601 middles.push_back(connBg[trueStart+nbOfEdges]);
11605 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)
11607 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11608 newConnOfCell->pushBackSilent(tmpEnd);
11613 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11614 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11615 middles.push_back(tmp3+offset);
11618 middles.push_back(connBg[start+nbOfEdges]);
11622 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)
11624 // only the quadratic point to deal with:
11629 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11630 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11631 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11632 middles.push_back(tmp3+offset);
11635 middles.push_back(connBg[start+nbOfEdges]);
11642 * 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 ) .
11643 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11645 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11647 std::size_t sz(std::distance(connBg,connEnd));
11648 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11649 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11651 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11652 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11653 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11654 unsigned nbOfHit(0); // number of fusions operated
11655 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11656 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
11657 INTERP_KERNEL::NormalizedCellType typeOfSon;
11658 std::vector<int> middles;
11660 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11662 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11663 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11664 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11665 posEndElt = posBaseElt+1;
11667 // Look backward first: are the final edges of the cells colinear with the first ones?
11668 // This initializes posBaseElt.
11671 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11673 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11674 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11675 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11676 bool isColinear=eint->areColinears();
11689 // Now move forward:
11690 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11691 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11693 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11694 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11695 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11696 bool isColinear(eint->areColinears());
11708 //push [posBaseElt,posEndElt) in newConnOfCell using e
11709 // 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!
11711 // at the begining of the connectivity (insert type)
11712 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11713 else if((nbOfHit+nbOfTurn) != (nbs-1))
11715 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11716 if ((nbOfHit+nbOfTurn) == (nbs-1))
11717 // at the end (only quad points to deal with)
11718 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11719 posBaseElt=posEndElt;
11722 if(!middles.empty())
11723 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11728 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11730 * \return int - the number of new nodes created.
11731 * \sa MEDCouplingUMesh::split2DCells
11733 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11736 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11738 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11739 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11740 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11741 const double *oldCoordsPtr(getCoords()->begin());
11742 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11743 int prevPosOfCi(ciPtr[0]);
11744 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11746 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11747 for(int j=0;j<sz;j++)
11748 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11749 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11750 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11752 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11756 cPtr[1]=oldConn[prevPosOfCi+2+j];
11757 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11760 std::vector<INTERP_KERNEL::Node *> ns(3);
11761 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11762 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11763 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11764 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11765 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11767 cPtr[1]=subPtr[offset2+k];
11768 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11770 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11772 { cPtr[1]=tmpEnd; }
11773 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11775 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11776 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11779 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11780 _nodal_connec->decrRef();
11781 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11782 addCoo->rearrange(2);
11783 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11785 return addCoo->getNumberOfTuples();
11788 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11790 if(nodalConnec && nodalConnecIndex)
11793 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11794 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11796 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11797 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11801 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11802 _own_cell(true),_cell_id(-1),_nb_cell(0)
11807 _nb_cell=mesh->getNumberOfCells();
11811 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11819 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11820 _own_cell(false),_cell_id(bg-1),
11827 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11830 if(_cell_id<_nb_cell)
11839 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11845 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11847 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11850 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11856 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11864 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11870 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11875 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11880 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11882 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11885 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11890 _nb_cell=mesh->getNumberOfCells();
11894 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11901 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11903 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11904 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11905 if(_cell_id<_nb_cell)
11907 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11908 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11909 int startId=_cell_id;
11910 _cell_id+=nbOfElems;
11911 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11917 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11921 _conn=mesh->getNodalConnectivity()->getPointer();
11922 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11926 void MEDCouplingUMeshCell::next()
11928 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11933 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11936 std::string MEDCouplingUMeshCell::repr() const
11938 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11940 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11942 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11946 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11949 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11951 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11952 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11954 return INTERP_KERNEL::NORM_ERROR;
11957 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11960 if(_conn_lgth!=NOTICABLE_FIRST_VAL)