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);
5197 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5198 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5199 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5200 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5201 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5202 * This method can be seen as the opposite method of colinearize2D.
5203 * 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
5204 * to avoid to modify the numbering of existing nodes.
5206 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5207 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5208 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5209 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5210 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5211 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5212 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5214 * \sa buildDescendingConnectivity2
5216 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5217 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5219 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5220 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5221 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5222 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5223 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5224 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5225 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5226 //DataArrayInt *out0(0),*outi0(0);
5227 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5228 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5229 //out0s=out0s->buildUnique(); out0s->sort(true);
5234 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5235 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5236 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5238 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5240 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5244 int nbOfCells=getNumberOfCells();
5245 int nbOfNodes=getNumberOfNodes();
5246 const int *cPtr=_nodal_connec->getConstPointer();
5247 const int *icPtr=_nodal_connec_index->getConstPointer();
5248 int lastVal=0,offset=nbOfNodes;
5249 for(int i=0;i<nbOfCells;i++,icPtr++)
5251 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5252 if(type==INTERP_KERNEL::NORM_SEG2)
5254 types.insert(INTERP_KERNEL::NORM_SEG3);
5255 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5256 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5257 newConn->pushBackSilent(offset++);
5259 newConnI->pushBackSilent(lastVal);
5260 ret->pushBackSilent(i);
5265 lastVal+=(icPtr[1]-icPtr[0]);
5266 newConnI->pushBackSilent(lastVal);
5267 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5271 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5275 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
5277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5281 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5282 DataArrayInt *conn1D=0,*conn1DI=0;
5283 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5284 DataArrayDouble *coordsTmp=0;
5285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5286 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5287 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5288 const int *c1DPtr=conn1D->begin();
5289 const int *c1DIPtr=conn1DI->begin();
5290 int nbOfCells=getNumberOfCells();
5291 const int *cPtr=_nodal_connec->getConstPointer();
5292 const int *icPtr=_nodal_connec_index->getConstPointer();
5294 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5296 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5297 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5298 if(!cm.isQuadratic())
5300 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5301 types.insert(typ2); newConn->pushBackSilent(typ2);
5302 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5303 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5304 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5305 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5306 newConnI->pushBackSilent(lastVal);
5307 ret->pushBackSilent(i);
5312 lastVal+=(icPtr[1]-icPtr[0]);
5313 newConnI->pushBackSilent(lastVal);
5314 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5317 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5322 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5323 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5324 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5326 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5330 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5333 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5336 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5340 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5342 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5343 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5344 DataArrayInt *conn1D=0,*conn1DI=0;
5345 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5346 DataArrayDouble *coordsTmp=0;
5347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5350 const int *c1DPtr=conn1D->begin();
5351 const int *c1DIPtr=conn1DI->begin();
5352 int nbOfCells=getNumberOfCells();
5353 const int *cPtr=_nodal_connec->getConstPointer();
5354 const int *icPtr=_nodal_connec_index->getConstPointer();
5355 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5356 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5358 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5359 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5360 if(!cm.isQuadratic())
5362 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5363 types.insert(typ2); newConn->pushBackSilent(typ2);
5364 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5365 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5366 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5367 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5368 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5369 newConnI->pushBackSilent(lastVal);
5370 ret->pushBackSilent(i);
5375 lastVal+=(icPtr[1]-icPtr[0]);
5376 newConnI->pushBackSilent(lastVal);
5377 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5380 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5381 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5386 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5387 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5388 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5390 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5392 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5393 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5394 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5397 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5400 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5401 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5402 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5408 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5409 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5410 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5411 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5412 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5415 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5416 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5417 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5419 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5420 int nbOfCells=getNumberOfCells();
5421 const int *cPtr=_nodal_connec->getConstPointer();
5422 const int *icPtr=_nodal_connec_index->getConstPointer();
5423 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5424 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5426 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5427 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5428 if(!cm.isQuadratic())
5430 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5431 if(typ2==INTERP_KERNEL::NORM_ERROR)
5433 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5434 throw INTERP_KERNEL::Exception(oss.str().c_str());
5436 types.insert(typ2); newConn->pushBackSilent(typ2);
5437 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5438 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5439 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5440 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5442 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5443 int tmpPos=newConn->getNumberOfTuples();
5444 newConn->pushBackSilent(nodeId2);
5445 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5447 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5448 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5449 newConnI->pushBackSilent(lastVal);
5450 ret->pushBackSilent(i);
5455 lastVal+=(icPtr[1]-icPtr[0]);
5456 newConnI->pushBackSilent(lastVal);
5457 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5462 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5463 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5464 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5465 int *c=newConn->getPointer();
5466 const int *cI(newConnI->begin());
5467 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5468 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5469 offset=coordsTmp2Safe->getNumberOfTuples();
5470 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5471 c[cI[(*elt)+1]-1]+=offset;
5472 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5477 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5478 * so that the number of cells remains the same. Quadratic faces are converted to
5479 * polygons. This method works only for 2D meshes in
5480 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5481 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5482 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5483 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5484 * a polylinized edge constituting the input polygon.
5485 * \throw If the coordinates array is not set.
5486 * \throw If the nodal connectivity of cells is not defined.
5487 * \throw If \a this->getMeshDimension() != 2.
5488 * \throw If \a this->getSpaceDimension() != 2.
5490 void MEDCouplingUMesh::tessellate2D(double eps)
5492 checkFullyDefined();
5493 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5494 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5495 double epsa=fabs(eps);
5496 if(epsa<std::numeric_limits<double>::min())
5497 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5499 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5500 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5501 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5502 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5503 revDesc1=0; revDescIndx1=0;
5504 mDesc->tessellate2DCurve(eps);
5505 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5506 setCoords(mDesc->getCoords());
5510 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5511 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5512 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5513 * a sub-divided edge.
5514 * \throw If the coordinates array is not set.
5515 * \throw If the nodal connectivity of cells is not defined.
5516 * \throw If \a this->getMeshDimension() != 1.
5517 * \throw If \a this->getSpaceDimension() != 2.
5519 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5521 checkFullyDefined();
5522 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5523 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5524 double epsa=fabs(eps);
5525 if(epsa<std::numeric_limits<double>::min())
5526 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5527 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5528 int nbCells=getNumberOfCells();
5529 int nbNodes=getNumberOfNodes();
5530 const int *conn=_nodal_connec->getConstPointer();
5531 const int *connI=_nodal_connec_index->getConstPointer();
5532 const double *coords=_coords->getConstPointer();
5533 std::vector<double> addCoo;
5534 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5536 newConnI->alloc(nbCells+1,1);
5537 int *newConnIPtr=newConnI->getPointer();
5540 INTERP_KERNEL::Node *tmp2[3];
5541 std::set<INTERP_KERNEL::NormalizedCellType> types;
5542 for(int i=0;i<nbCells;i++,newConnIPtr++)
5544 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5545 if(cm.isQuadratic())
5546 {//assert(connI[i+1]-connI[i]-1==3)
5547 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5548 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5549 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5550 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5551 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5554 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5555 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5557 newConnIPtr[1]=(int)newConn.size();
5561 types.insert(INTERP_KERNEL::NORM_SEG2);
5562 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5563 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5564 newConnIPtr[1]=newConnIPtr[0]+3;
5569 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5570 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5571 newConnIPtr[1]=newConnIPtr[0]+3;
5574 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5577 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5578 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5579 newConnArr->alloc((int)newConn.size(),1);
5580 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5581 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5582 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5583 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5584 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5585 std::copy(addCoo.begin(),addCoo.end(),work);
5586 DataArrayDouble::SetArrayIn(newCoords,_coords);
5591 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5592 * In addition, returns an array mapping new cells to old ones. <br>
5593 * This method typically increases the number of cells in \a this mesh
5594 * but the number of nodes remains \b unchanged.
5595 * That's why the 3D splitting policies
5596 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5597 * \param [in] policy - specifies a pattern used for splitting.
5598 * The semantic of \a policy is:
5599 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5600 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5601 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5602 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5605 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5606 * an id of old cell producing it. The caller is to delete this array using
5607 * decrRef() as it is no more needed.
5609 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5610 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5611 * and \a this->getMeshDimension() != 3.
5612 * \throw If \a policy is not one of the four discussed above.
5613 * \throw If the nodal connectivity of cells is not defined.
5614 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5616 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5621 return simplexizePol0();
5623 return simplexizePol1();
5624 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5625 return simplexizePlanarFace5();
5626 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5627 return simplexizePlanarFace6();
5629 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)");
5634 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5635 * - 1D: INTERP_KERNEL::NORM_SEG2
5636 * - 2D: INTERP_KERNEL::NORM_TRI3
5637 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5639 * This method is useful for users that need to use P1 field services as
5640 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5641 * All these methods need mesh support containing only simplex cells.
5642 * \return bool - \c true if there are only simplex cells in \a this mesh.
5643 * \throw If the coordinates array is not set.
5644 * \throw If the nodal connectivity of cells is not defined.
5645 * \throw If \a this->getMeshDimension() < 1.
5647 bool MEDCouplingUMesh::areOnlySimplexCells() const
5649 checkFullyDefined();
5650 int mdim=getMeshDimension();
5651 if(mdim<1 || mdim>3)
5652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5653 int nbCells=getNumberOfCells();
5654 const int *conn=_nodal_connec->getConstPointer();
5655 const int *connI=_nodal_connec_index->getConstPointer();
5656 for(int i=0;i<nbCells;i++)
5658 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5666 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5668 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5670 checkConnectivityFullyDefined();
5671 if(getMeshDimension()!=2)
5672 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5673 int nbOfCells=getNumberOfCells();
5674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5675 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5676 ret->alloc(nbOfCells+nbOfCutCells,1);
5677 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5678 int *retPt=ret->getPointer();
5679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5680 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5681 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5682 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5683 int *pt=newConn->getPointer();
5684 int *ptI=newConnI->getPointer();
5686 const int *oldc=_nodal_connec->getConstPointer();
5687 const int *ci=_nodal_connec_index->getConstPointer();
5688 for(int i=0;i<nbOfCells;i++,ci++)
5690 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5692 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5693 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5694 pt=std::copy(tmp,tmp+8,pt);
5703 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5704 ptI[1]=ptI[0]+ci[1]-ci[0];
5709 _nodal_connec->decrRef();
5710 _nodal_connec=newConn.retn();
5711 _nodal_connec_index->decrRef();
5712 _nodal_connec_index=newConnI.retn();
5719 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5721 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5723 checkConnectivityFullyDefined();
5724 if(getMeshDimension()!=2)
5725 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5726 int nbOfCells=getNumberOfCells();
5727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5728 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5729 ret->alloc(nbOfCells+nbOfCutCells,1);
5730 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5731 int *retPt=ret->getPointer();
5732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5734 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5735 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5736 int *pt=newConn->getPointer();
5737 int *ptI=newConnI->getPointer();
5739 const int *oldc=_nodal_connec->getConstPointer();
5740 const int *ci=_nodal_connec_index->getConstPointer();
5741 for(int i=0;i<nbOfCells;i++,ci++)
5743 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5745 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5746 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5747 pt=std::copy(tmp,tmp+8,pt);
5756 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5757 ptI[1]=ptI[0]+ci[1]-ci[0];
5762 _nodal_connec->decrRef();
5763 _nodal_connec=newConn.retn();
5764 _nodal_connec_index->decrRef();
5765 _nodal_connec_index=newConnI.retn();
5772 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5774 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5776 checkConnectivityFullyDefined();
5777 if(getMeshDimension()!=3)
5778 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5779 int nbOfCells=getNumberOfCells();
5780 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5781 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5782 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5783 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5784 int *retPt=ret->getPointer();
5785 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5787 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5788 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5789 int *pt=newConn->getPointer();
5790 int *ptI=newConnI->getPointer();
5792 const int *oldc=_nodal_connec->getConstPointer();
5793 const int *ci=_nodal_connec_index->getConstPointer();
5794 for(int i=0;i<nbOfCells;i++,ci++)
5796 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5798 for(int j=0;j<5;j++,pt+=5,ptI++)
5800 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5801 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];
5808 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5809 ptI[1]=ptI[0]+ci[1]-ci[0];
5814 _nodal_connec->decrRef();
5815 _nodal_connec=newConn.retn();
5816 _nodal_connec_index->decrRef();
5817 _nodal_connec_index=newConnI.retn();
5824 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5826 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5828 checkConnectivityFullyDefined();
5829 if(getMeshDimension()!=3)
5830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5831 int nbOfCells=getNumberOfCells();
5832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5833 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5834 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5835 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5836 int *retPt=ret->getPointer();
5837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5839 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5840 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5841 int *pt=newConn->getPointer();
5842 int *ptI=newConnI->getPointer();
5844 const int *oldc=_nodal_connec->getConstPointer();
5845 const int *ci=_nodal_connec_index->getConstPointer();
5846 for(int i=0;i<nbOfCells;i++,ci++)
5848 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5850 for(int j=0;j<6;j++,pt+=5,ptI++)
5852 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5853 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];
5860 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5861 ptI[1]=ptI[0]+ci[1]-ci[0];
5866 _nodal_connec->decrRef();
5867 _nodal_connec=newConn.retn();
5868 _nodal_connec_index->decrRef();
5869 _nodal_connec_index=newConnI.retn();
5876 * 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.
5877 * This method completly ignore coordinates.
5878 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5879 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5880 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5881 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5883 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5885 checkFullyDefined();
5886 if(getMeshDimension()!=2)
5887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5888 int nbOfCells=getNumberOfCells();
5889 int *connI=_nodal_connec_index->getPointer();
5891 for(int i=0;i<nbOfCells;i++,connI++)
5893 int offset=descIndex[i];
5894 int nbOfEdges=descIndex[i+1]-offset;
5896 bool ddirect=desc[offset+nbOfEdges-1]>0;
5897 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5898 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5899 for(int j=0;j<nbOfEdges;j++)
5901 bool direct=desc[offset+j]>0;
5902 int edgeId=std::abs(desc[offset+j])-1;
5903 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5905 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5906 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5907 int ref2=direct?id1:id2;
5910 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5911 newConnLgth+=nbOfSubNodes-1;
5916 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5917 throw INTERP_KERNEL::Exception(oss.str().c_str());
5922 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5925 newConnLgth++;//+1 is for cell type
5926 connI[1]=newConnLgth;
5929 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5930 newConn->alloc(newConnLgth,1);
5931 int *work=newConn->getPointer();
5932 for(int i=0;i<nbOfCells;i++)
5934 *work++=INTERP_KERNEL::NORM_POLYGON;
5935 int offset=descIndex[i];
5936 int nbOfEdges=descIndex[i+1]-offset;
5937 for(int j=0;j<nbOfEdges;j++)
5939 bool direct=desc[offset+j]>0;
5940 int edgeId=std::abs(desc[offset+j])-1;
5942 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5945 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5946 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5947 work=std::copy(it,it+nbOfSubNodes-1,work);
5951 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5954 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5958 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5959 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5960 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5961 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5962 * so it can be useful to call mergeNodes() before calling this method.
5963 * \throw If \a this->getMeshDimension() <= 1.
5964 * \throw If the coordinates array is not set.
5965 * \throw If the nodal connectivity of cells is not defined.
5967 void MEDCouplingUMesh::convertDegeneratedCells()
5969 checkFullyDefined();
5970 if(getMeshDimension()<=1)
5971 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5972 int nbOfCells=getNumberOfCells();
5975 int initMeshLgth=getMeshLength();
5976 int *conn=_nodal_connec->getPointer();
5977 int *index=_nodal_connec_index->getPointer();
5981 for(int i=0;i<nbOfCells;i++)
5983 lgthOfCurCell=index[i+1]-posOfCurCell;
5984 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5986 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5987 conn+newPos+1,newLgth);
5988 conn[newPos]=newType;
5990 posOfCurCell=index[i+1];
5993 if(newPos!=initMeshLgth)
5994 _nodal_connec->reAlloc(newPos);
5999 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6000 * A cell is considered to be oriented correctly if an angle between its
6001 * normal vector and a given vector is less than \c PI / \c 2.
6002 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6004 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6006 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6007 * is not cleared before filling in.
6008 * \throw If \a this->getMeshDimension() != 2.
6009 * \throw If \a this->getSpaceDimension() != 3.
6011 * \if ENABLE_EXAMPLES
6012 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6013 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6016 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6018 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6019 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6020 int nbOfCells=getNumberOfCells();
6021 const int *conn=_nodal_connec->getConstPointer();
6022 const int *connI=_nodal_connec_index->getConstPointer();
6023 const double *coordsPtr=_coords->getConstPointer();
6024 for(int i=0;i<nbOfCells;i++)
6026 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6027 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6029 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6030 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6037 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6038 * considered to be oriented correctly if an angle between its normal vector and a
6039 * given vector is less than \c PI / \c 2.
6040 * \param [in] vec - 3 components of the vector specifying the correct orientation of
6042 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6044 * \throw If \a this->getMeshDimension() != 2.
6045 * \throw If \a this->getSpaceDimension() != 3.
6047 * \if ENABLE_EXAMPLES
6048 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6049 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6052 * \sa changeOrientationOfCells
6054 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6056 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6057 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6058 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6059 const int *connI(_nodal_connec_index->getConstPointer());
6060 const double *coordsPtr(_coords->getConstPointer());
6061 bool isModified(false);
6062 for(int i=0;i<nbOfCells;i++)
6064 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6065 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6067 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6068 bool isQuadratic(cm.isQuadratic());
6069 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6072 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6077 _nodal_connec->declareAsNew();
6082 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6084 * \sa orientCorrectly2DCells
6086 void MEDCouplingUMesh::changeOrientationOfCells()
6088 int mdim(getMeshDimension());
6089 if(mdim!=2 && mdim!=1)
6090 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6091 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6092 const int *connI(_nodal_connec_index->getConstPointer());
6095 for(int i=0;i<nbOfCells;i++)
6097 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6098 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6099 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6104 for(int i=0;i<nbOfCells;i++)
6106 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6107 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6108 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6114 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6115 * oriented facets. The normal vector of the facet should point out of the cell.
6116 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6117 * is not cleared before filling in.
6118 * \throw If \a this->getMeshDimension() != 3.
6119 * \throw If \a this->getSpaceDimension() != 3.
6120 * \throw If the coordinates array is not set.
6121 * \throw If the nodal connectivity of cells is not defined.
6123 * \if ENABLE_EXAMPLES
6124 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6125 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6128 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6130 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6131 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6132 int nbOfCells=getNumberOfCells();
6133 const int *conn=_nodal_connec->getConstPointer();
6134 const int *connI=_nodal_connec_index->getConstPointer();
6135 const double *coordsPtr=_coords->getConstPointer();
6136 for(int i=0;i<nbOfCells;i++)
6138 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6139 if(type==INTERP_KERNEL::NORM_POLYHED)
6141 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6148 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6150 * \throw If \a this->getMeshDimension() != 3.
6151 * \throw If \a this->getSpaceDimension() != 3.
6152 * \throw If the coordinates array is not set.
6153 * \throw If the nodal connectivity of cells is not defined.
6154 * \throw If the reparation fails.
6156 * \if ENABLE_EXAMPLES
6157 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6158 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6160 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6162 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6164 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6165 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6166 int nbOfCells=getNumberOfCells();
6167 int *conn=_nodal_connec->getPointer();
6168 const int *connI=_nodal_connec_index->getConstPointer();
6169 const double *coordsPtr=_coords->getConstPointer();
6170 for(int i=0;i<nbOfCells;i++)
6172 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6173 if(type==INTERP_KERNEL::NORM_POLYHED)
6177 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6178 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6180 catch(INTERP_KERNEL::Exception& e)
6182 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6183 throw INTERP_KERNEL::Exception(oss.str().c_str());
6191 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6192 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6193 * according to which the first facet of the cell should be oriented to have the normal vector
6194 * pointing out of cell.
6195 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6196 * cells. The caller is to delete this array using decrRef() as it is no more
6198 * \throw If \a this->getMeshDimension() != 3.
6199 * \throw If \a this->getSpaceDimension() != 3.
6200 * \throw If the coordinates array is not set.
6201 * \throw If the nodal connectivity of cells is not defined.
6203 * \if ENABLE_EXAMPLES
6204 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6205 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6207 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6209 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6211 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6212 if(getMeshDimension()!=3)
6213 throw INTERP_KERNEL::Exception(msg);
6214 int spaceDim=getSpaceDimension();
6216 throw INTERP_KERNEL::Exception(msg);
6218 int nbOfCells=getNumberOfCells();
6219 int *conn=_nodal_connec->getPointer();
6220 const int *connI=_nodal_connec_index->getConstPointer();
6221 const double *coo=getCoords()->getConstPointer();
6222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6223 for(int i=0;i<nbOfCells;i++)
6225 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6226 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6228 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6230 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6231 cells->pushBackSilent(i);
6235 return cells.retn();
6239 * This method is a faster method to correct orientation of all 3D cells in \a this.
6240 * 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.
6241 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6243 * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6244 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6246 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6248 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6249 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6250 int nbOfCells=getNumberOfCells();
6251 int *conn=_nodal_connec->getPointer();
6252 const int *connI=_nodal_connec_index->getConstPointer();
6253 const double *coordsPtr=_coords->getConstPointer();
6254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6255 for(int i=0;i<nbOfCells;i++)
6257 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6260 case INTERP_KERNEL::NORM_TETRA4:
6262 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6264 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6265 ret->pushBackSilent(i);
6269 case INTERP_KERNEL::NORM_PYRA5:
6271 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6273 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6274 ret->pushBackSilent(i);
6278 case INTERP_KERNEL::NORM_PENTA6:
6279 case INTERP_KERNEL::NORM_HEXA8:
6280 case INTERP_KERNEL::NORM_HEXGP12:
6282 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6284 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6285 ret->pushBackSilent(i);
6289 case INTERP_KERNEL::NORM_POLYHED:
6291 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6293 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6294 ret->pushBackSilent(i);
6299 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 !");
6307 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6308 * If it is not the case an exception will be thrown.
6309 * This method is fast because the first cell of \a this is used to compute the plane.
6310 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6311 * \param pos output of size at least 3 used to store a point owned of searched plane.
6313 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6315 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6316 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6317 const int *conn=_nodal_connec->getConstPointer();
6318 const int *connI=_nodal_connec_index->getConstPointer();
6319 const double *coordsPtr=_coords->getConstPointer();
6320 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6321 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6325 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6326 * cells. Currently cells of the following types are treated:
6327 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6328 * For a cell of other type an exception is thrown.
6329 * Space dimension of a 2D mesh can be either 2 or 3.
6330 * The Edge Ratio of a cell \f$t\f$ is:
6331 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6332 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6333 * the smallest edge lengths of \f$t\f$.
6334 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6335 * cells and one time, lying on \a this mesh. The caller is to delete this
6336 * field using decrRef() as it is no more needed.
6337 * \throw If the coordinates array is not set.
6338 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6339 * \throw If the connectivity data array has more than one component.
6340 * \throw If the connectivity data array has a named component.
6341 * \throw If the connectivity index data array has more than one component.
6342 * \throw If the connectivity index data array has a named component.
6343 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6344 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6345 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6347 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6350 int spaceDim=getSpaceDimension();
6351 int meshDim=getMeshDimension();
6352 if(spaceDim!=2 && spaceDim!=3)
6353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6354 if(meshDim!=2 && meshDim!=3)
6355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6358 int nbOfCells=getNumberOfCells();
6359 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6360 arr->alloc(nbOfCells,1);
6361 double *pt=arr->getPointer();
6362 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6363 const int *conn=_nodal_connec->getConstPointer();
6364 const int *connI=_nodal_connec_index->getConstPointer();
6365 const double *coo=_coords->getConstPointer();
6367 for(int i=0;i<nbOfCells;i++,pt++)
6369 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6372 case INTERP_KERNEL::NORM_TRI3:
6374 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6375 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6378 case INTERP_KERNEL::NORM_QUAD4:
6380 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6381 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6384 case INTERP_KERNEL::NORM_TETRA4:
6386 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6387 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6393 conn+=connI[i+1]-connI[i];
6395 ret->setName("EdgeRatio");
6396 ret->synchronizeTimeWithSupport();
6401 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6402 * cells. Currently cells of the following types are treated:
6403 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6404 * For a cell of other type an exception is thrown.
6405 * Space dimension of a 2D mesh can be either 2 or 3.
6406 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6407 * cells and one time, lying on \a this mesh. The caller is to delete this
6408 * field using decrRef() as it is no more needed.
6409 * \throw If the coordinates array is not set.
6410 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6411 * \throw If the connectivity data array has more than one component.
6412 * \throw If the connectivity data array has a named component.
6413 * \throw If the connectivity index data array has more than one component.
6414 * \throw If the connectivity index data array has a named component.
6415 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6416 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6417 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6419 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6422 int spaceDim=getSpaceDimension();
6423 int meshDim=getMeshDimension();
6424 if(spaceDim!=2 && spaceDim!=3)
6425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6426 if(meshDim!=2 && meshDim!=3)
6427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6428 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6430 int nbOfCells=getNumberOfCells();
6431 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6432 arr->alloc(nbOfCells,1);
6433 double *pt=arr->getPointer();
6434 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6435 const int *conn=_nodal_connec->getConstPointer();
6436 const int *connI=_nodal_connec_index->getConstPointer();
6437 const double *coo=_coords->getConstPointer();
6439 for(int i=0;i<nbOfCells;i++,pt++)
6441 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6444 case INTERP_KERNEL::NORM_TRI3:
6446 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6447 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6450 case INTERP_KERNEL::NORM_QUAD4:
6452 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6453 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6456 case INTERP_KERNEL::NORM_TETRA4:
6458 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6459 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6465 conn+=connI[i+1]-connI[i];
6467 ret->setName("AspectRatio");
6468 ret->synchronizeTimeWithSupport();
6473 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6474 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6475 * treated: INTERP_KERNEL::NORM_QUAD4.
6476 * For a cell of other type an exception is thrown.
6477 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6478 * cells and one time, lying on \a this mesh. The caller is to delete this
6479 * field using decrRef() as it is no more needed.
6480 * \throw If the coordinates array is not set.
6481 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6482 * \throw If the connectivity data array has more than one component.
6483 * \throw If the connectivity data array has a named component.
6484 * \throw If the connectivity index data array has more than one component.
6485 * \throw If the connectivity index data array has a named component.
6486 * \throw If \a this->getMeshDimension() != 2.
6487 * \throw If \a this->getSpaceDimension() != 3.
6488 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6490 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6493 int spaceDim=getSpaceDimension();
6494 int meshDim=getMeshDimension();
6496 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6498 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6501 int nbOfCells=getNumberOfCells();
6502 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6503 arr->alloc(nbOfCells,1);
6504 double *pt=arr->getPointer();
6505 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6506 const int *conn=_nodal_connec->getConstPointer();
6507 const int *connI=_nodal_connec_index->getConstPointer();
6508 const double *coo=_coords->getConstPointer();
6510 for(int i=0;i<nbOfCells;i++,pt++)
6512 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6515 case INTERP_KERNEL::NORM_QUAD4:
6517 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6518 *pt=INTERP_KERNEL::quadWarp(tmp);
6522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6524 conn+=connI[i+1]-connI[i];
6526 ret->setName("Warp");
6527 ret->synchronizeTimeWithSupport();
6533 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6534 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6535 * treated: INTERP_KERNEL::NORM_QUAD4.
6536 * For a cell of other type an exception is thrown.
6537 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6538 * cells and one time, lying on \a this mesh. The caller is to delete this
6539 * field using decrRef() as it is no more needed.
6540 * \throw If the coordinates array is not set.
6541 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6542 * \throw If the connectivity data array has more than one component.
6543 * \throw If the connectivity data array has a named component.
6544 * \throw If the connectivity index data array has more than one component.
6545 * \throw If the connectivity index data array has a named component.
6546 * \throw If \a this->getMeshDimension() != 2.
6547 * \throw If \a this->getSpaceDimension() != 3.
6548 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6550 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6553 int spaceDim=getSpaceDimension();
6554 int meshDim=getMeshDimension();
6556 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6558 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6559 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6561 int nbOfCells=getNumberOfCells();
6562 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6563 arr->alloc(nbOfCells,1);
6564 double *pt=arr->getPointer();
6565 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6566 const int *conn=_nodal_connec->getConstPointer();
6567 const int *connI=_nodal_connec_index->getConstPointer();
6568 const double *coo=_coords->getConstPointer();
6570 for(int i=0;i<nbOfCells;i++,pt++)
6572 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6575 case INTERP_KERNEL::NORM_QUAD4:
6577 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6578 *pt=INTERP_KERNEL::quadSkew(tmp);
6582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6584 conn+=connI[i+1]-connI[i];
6586 ret->setName("Skew");
6587 ret->synchronizeTimeWithSupport();
6592 * 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.
6594 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6596 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6598 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6601 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6603 std::set<INTERP_KERNEL::NormalizedCellType> types;
6604 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6605 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6606 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6607 arr->alloc(nbCells,1);
6608 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6610 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6612 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6615 ret->setName("Diameter");
6620 * This method aggregate the bbox of each cell and put it into bbox parameter.
6622 * \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)
6623 * For all other cases this input parameter is ignored.
6624 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6626 * \throw If \a this is not fully set (coordinates and connectivity).
6627 * \throw If a cell in \a this has no valid nodeId.
6628 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6630 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6632 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6633 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.
6634 return getBoundingBoxForBBTreeFast();
6635 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6637 bool presenceOfQuadratic(false);
6638 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6640 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6641 if(cm.isQuadratic())
6642 presenceOfQuadratic=true;
6644 if(!presenceOfQuadratic)
6645 return getBoundingBoxForBBTreeFast();
6646 if(mDim==2 && sDim==2)
6647 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6649 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6651 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) !");
6655 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6656 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6658 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6660 * \throw If \a this is not fully set (coordinates and connectivity).
6661 * \throw If a cell in \a this has no valid nodeId.
6663 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6665 checkFullyDefined();
6666 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6667 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6668 double *bbox(ret->getPointer());
6669 for(int i=0;i<nbOfCells*spaceDim;i++)
6671 bbox[2*i]=std::numeric_limits<double>::max();
6672 bbox[2*i+1]=-std::numeric_limits<double>::max();
6674 const double *coordsPtr(_coords->getConstPointer());
6675 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6676 for(int i=0;i<nbOfCells;i++)
6678 int offset=connI[i]+1;
6679 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6680 for(int j=0;j<nbOfNodesForCell;j++)
6682 int nodeId=conn[offset+j];
6683 if(nodeId>=0 && nodeId<nbOfNodes)
6685 for(int k=0;k<spaceDim;k++)
6687 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6688 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6695 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6696 throw INTERP_KERNEL::Exception(oss.str().c_str());
6703 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6704 * useful for 2D meshes having quadratic cells
6705 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6706 * the two extremities of the arc of circle).
6708 * \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)
6709 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6710 * \throw If \a this is not fully defined.
6711 * \throw If \a this is not a mesh with meshDimension equal to 2.
6712 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6713 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6715 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6717 checkFullyDefined();
6718 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6719 if(spaceDim!=2 || mDim!=2)
6720 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!");
6721 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6722 double *bbox(ret->getPointer());
6723 const double *coords(_coords->getConstPointer());
6724 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6725 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6727 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6728 int sz(connI[1]-connI[0]-1);
6729 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6730 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6731 INTERP_KERNEL::QuadraticPolygon *pol(0);
6732 for(int j=0;j<sz;j++)
6734 int nodeId(conn[*connI+1+j]);
6735 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6737 if(!cm.isQuadratic())
6738 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6740 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6741 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6742 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6748 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6749 * useful for 2D meshes having quadratic cells
6750 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6751 * the two extremities of the arc of circle).
6753 * \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)
6754 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6755 * \throw If \a this is not fully defined.
6756 * \throw If \a this is not a mesh with meshDimension equal to 1.
6757 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6758 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6760 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6762 checkFullyDefined();
6763 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6764 if(spaceDim!=2 || mDim!=1)
6765 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!");
6766 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6767 double *bbox(ret->getPointer());
6768 const double *coords(_coords->getConstPointer());
6769 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6770 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6772 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6773 int sz(connI[1]-connI[0]-1);
6774 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6775 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6776 INTERP_KERNEL::Edge *edge(0);
6777 for(int j=0;j<sz;j++)
6779 int nodeId(conn[*connI+1+j]);
6780 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6782 if(!cm.isQuadratic())
6783 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6785 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6786 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6787 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6794 namespace ParaMEDMEMImpl
6799 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6800 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6809 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6810 bool operator() (const int& pos) { return _conn[pos]==_val; }
6820 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6821 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6822 * \a this is composed in cell types.
6823 * The returned array is of size 3*n where n is the number of different types present in \a this.
6824 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6825 * This parameter is kept only for compatibility with other methode listed above.
6827 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6829 checkConnectivityFullyDefined();
6830 const int *conn=_nodal_connec->getConstPointer();
6831 const int *connI=_nodal_connec_index->getConstPointer();
6832 const int *work=connI;
6833 int nbOfCells=getNumberOfCells();
6834 std::size_t n=getAllGeoTypes().size();
6835 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6836 std::set<INTERP_KERNEL::NormalizedCellType> types;
6837 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6839 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6840 if(types.find(typ)!=types.end())
6842 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6843 oss << " is not contiguous !";
6844 throw INTERP_KERNEL::Exception(oss.str().c_str());
6848 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6849 ret[3*i+1]=(int)std::distance(work,work2);
6856 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6857 * only for types cell, type node is not managed.
6858 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6859 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6860 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6861 * If 2 or more same geometric type is in \a code and exception is thrown too.
6863 * This method firstly checks
6864 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6865 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6866 * an exception is thrown too.
6868 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6869 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6870 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6872 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6875 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6876 std::size_t sz=code.size();
6879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6880 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6882 bool isNoPflUsed=true;
6883 for(std::size_t i=0;i<n;i++)
6884 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6886 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6888 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6889 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6890 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6893 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6896 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6898 if(types.size()==_types.size())
6901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6903 int *retPtr=ret->getPointer();
6904 const int *connI=_nodal_connec_index->getConstPointer();
6905 const int *conn=_nodal_connec->getConstPointer();
6906 int nbOfCells=getNumberOfCells();
6909 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6911 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6912 int offset=(int)std::distance(connI,i);
6913 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6914 int nbOfCellsOfCurType=(int)std::distance(i,j);
6915 if(code[3*kk+2]==-1)
6916 for(int k=0;k<nbOfCellsOfCurType;k++)
6920 int idInIdsPerType=code[3*kk+2];
6921 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6923 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6926 zePfl->checkAllocated();
6927 if(zePfl->getNumberOfComponents()==1)
6929 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6931 if(*k>=0 && *k<nbOfCellsOfCurType)
6932 *retPtr=(*k)+offset;
6935 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6936 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6937 throw INTERP_KERNEL::Exception(oss.str().c_str());
6942 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6945 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6949 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6950 oss << " should be in [0," << idsPerType.size() << ") !";
6951 throw INTERP_KERNEL::Exception(oss.str().c_str());
6960 * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6961 * 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.
6962 * 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.
6963 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6965 * \param [in] profile
6966 * \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.
6967 * \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,
6968 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6969 * \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.
6970 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6971 * \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
6973 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6976 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6977 if(profile->getNumberOfComponents()!=1)
6978 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6979 checkConnectivityFullyDefined();
6980 const int *conn=_nodal_connec->getConstPointer();
6981 const int *connI=_nodal_connec_index->getConstPointer();
6982 int nbOfCells=getNumberOfCells();
6983 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6984 std::vector<int> typeRangeVals(1);
6985 for(const int *i=connI;i!=connI+nbOfCells;)
6987 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6988 if(std::find(types.begin(),types.end(),curType)!=types.end())
6990 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6992 types.push_back(curType);
6993 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6994 typeRangeVals.push_back((int)std::distance(connI,i));
6997 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6998 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
7000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
7001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
7003 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7004 code.resize(3*nbOfCastsFinal);
7005 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7006 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7007 for(int i=0;i<nbOfCastsFinal;i++)
7009 int castId=castsPresent->getIJ(i,0);
7010 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7011 idsInPflPerType2.push_back(tmp3);
7012 code[3*i]=(int)types[castId];
7013 code[3*i+1]=tmp3->getNumberOfTuples();
7014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7015 if(!tmp4->isIdentity2(typeRangeVals[castId+1]-typeRangeVals[castId]))
7017 tmp4->copyStringInfoFrom(*profile);
7018 idsPerType2.push_back(tmp4);
7019 code[3*i+2]=(int)idsPerType2.size()-1;
7026 std::size_t sz2=idsInPflPerType2.size();
7027 idsInPflPerType.resize(sz2);
7028 for(std::size_t i=0;i<sz2;i++)
7030 DataArrayInt *locDa=idsInPflPerType2[i];
7032 idsInPflPerType[i]=locDa;
7034 std::size_t sz=idsPerType2.size();
7035 idsPerType.resize(sz);
7036 for(std::size_t i=0;i<sz;i++)
7038 DataArrayInt *locDa=idsPerType2[i];
7040 idsPerType[i]=locDa;
7045 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7046 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7047 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7048 * 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.
7050 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7052 checkFullyDefined();
7053 nM1LevMesh->checkFullyDefined();
7054 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7055 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7056 if(_coords!=nM1LevMesh->getCoords())
7057 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7060 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7062 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7063 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7064 tmp->setConnectivity(tmp0,tmp1);
7065 tmp->renumberCells(ret0->getConstPointer(),false);
7066 revDesc=tmp->getNodalConnectivity();
7067 revDescIndx=tmp->getNodalConnectivityIndex();
7068 DataArrayInt *ret=0;
7069 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7072 ret->getMaxValue(tmp2);
7074 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7075 throw INTERP_KERNEL::Exception(oss.str().c_str());
7080 revDescIndx->incrRef();
7083 meshnM1Old2New=ret0;
7088 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7089 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7090 * in "Old to New" mode.
7091 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7092 * this array using decrRef() as it is no more needed.
7093 * \throw If the nodal connectivity of cells is not defined.
7095 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7097 checkConnectivityFullyDefined();
7098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7099 renumberCells(ret->getConstPointer(),false);
7104 * This methods checks that cells are sorted by their types.
7105 * This method makes asumption (no check) that connectivity is correctly set before calling.
7107 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7109 checkFullyDefined();
7110 const int *conn=_nodal_connec->getConstPointer();
7111 const int *connI=_nodal_connec_index->getConstPointer();
7112 int nbOfCells=getNumberOfCells();
7113 std::set<INTERP_KERNEL::NormalizedCellType> types;
7114 for(const int *i=connI;i!=connI+nbOfCells;)
7116 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7117 if(types.find(curType)!=types.end())
7119 types.insert(curType);
7120 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7126 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7127 * The geometric type order is specified by MED file.
7129 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7131 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7133 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7137 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7138 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7139 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7140 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7142 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7144 checkFullyDefined();
7145 const int *conn=_nodal_connec->getConstPointer();
7146 const int *connI=_nodal_connec_index->getConstPointer();
7147 int nbOfCells=getNumberOfCells();
7151 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7152 for(const int *i=connI;i!=connI+nbOfCells;)
7154 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7155 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7156 if(isTypeExists!=orderEnd)
7158 int pos=(int)std::distance(orderBg,isTypeExists);
7162 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7166 if(sg.find(curType)==sg.end())
7168 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7179 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7180 * 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
7181 * 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'.
7183 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7185 checkConnectivityFullyDefined();
7186 int nbOfCells=getNumberOfCells();
7187 const int *conn=_nodal_connec->getConstPointer();
7188 const int *connI=_nodal_connec_index->getConstPointer();
7189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7190 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7191 tmpa->alloc(nbOfCells,1);
7192 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7193 tmpb->fillWithZero();
7194 int *tmp=tmpa->getPointer();
7195 int *tmp2=tmpb->getPointer();
7196 for(const int *i=connI;i!=connI+nbOfCells;i++)
7198 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7201 int pos=(int)std::distance(orderBg,where);
7203 tmp[std::distance(connI,i)]=pos;
7207 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7208 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7209 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7210 throw INTERP_KERNEL::Exception(oss.str().c_str());
7213 nbPerType=tmpb.retn();
7218 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7220 * \return a new object containing the old to new correspondance.
7222 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7224 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7226 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7230 * 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.
7231 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7232 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7233 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7235 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7237 DataArrayInt *nbPerType=0;
7238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7239 nbPerType->decrRef();
7240 return tmpa->buildPermArrPerLevel();
7244 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7245 * The number of cells remains unchanged after the call of this method.
7246 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7247 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7249 * \return the array giving the correspondance old to new.
7251 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7253 checkFullyDefined();
7255 const int *conn=_nodal_connec->getConstPointer();
7256 const int *connI=_nodal_connec_index->getConstPointer();
7257 int nbOfCells=getNumberOfCells();
7258 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7259 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7260 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7262 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7263 types.push_back(curType);
7264 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7266 DataArrayInt *ret=DataArrayInt::New();
7267 ret->alloc(nbOfCells,1);
7268 int *retPtr=ret->getPointer();
7269 std::fill(retPtr,retPtr+nbOfCells,-1);
7271 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7273 for(const int *i=connI;i!=connI+nbOfCells;i++)
7274 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7275 retPtr[std::distance(connI,i)]=newCellId++;
7277 renumberCells(retPtr,false);
7282 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7283 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7284 * This method makes asumption that connectivity is correctly set before calling.
7286 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7288 checkConnectivityFullyDefined();
7289 const int *conn=_nodal_connec->getConstPointer();
7290 const int *connI=_nodal_connec_index->getConstPointer();
7291 int nbOfCells=getNumberOfCells();
7292 std::vector<MEDCouplingUMesh *> ret;
7293 for(const int *i=connI;i!=connI+nbOfCells;)
7295 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7296 int beginCellId=(int)std::distance(connI,i);
7297 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7298 int endCellId=(int)std::distance(connI,i);
7299 int sz=endCellId-beginCellId;
7300 int *cells=new int[sz];
7301 for(int j=0;j<sz;j++)
7302 cells[j]=beginCellId+j;
7303 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7311 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7312 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7313 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7315 * \return a newly allocated instance, that the caller must manage.
7316 * \throw If \a this contains more than one geometric type.
7317 * \throw If the nodal connectivity of \a this is not fully defined.
7318 * \throw If the internal data is not coherent.
7320 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7322 checkConnectivityFullyDefined();
7323 if(_types.size()!=1)
7324 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7325 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7326 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7327 ret->setCoords(getCoords());
7328 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7332 retC->setNodalConnectivity(c);
7336 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7339 DataArrayInt *c=0,*ci=0;
7340 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7342 retD->setNodalConnectivity(cs,cis);
7347 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7349 checkConnectivityFullyDefined();
7350 if(_types.size()!=1)
7351 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7352 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7353 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7356 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7357 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7358 throw INTERP_KERNEL::Exception(oss.str().c_str());
7360 int nbCells=getNumberOfCells();
7362 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7364 int *outPtr=connOut->getPointer();
7365 const int *conn=_nodal_connec->begin();
7366 const int *connI=_nodal_connec_index->begin();
7368 for(int i=0;i<nbCells;i++,connI++)
7370 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7371 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7374 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 << ") !";
7375 throw INTERP_KERNEL::Exception(oss.str().c_str());
7378 return connOut.retn();
7382 * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7383 * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7387 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7389 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7390 checkConnectivityFullyDefined();
7391 if(_types.size()!=1)
7392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7393 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7395 throw INTERP_KERNEL::Exception(msg0);
7396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7397 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7398 int *cp(c->getPointer()),*cip(ci->getPointer());
7399 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7401 for(int i=0;i<nbCells;i++,cip++,incip++)
7403 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7404 int delta(stop-strt);
7407 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7408 cp=std::copy(incp+strt,incp+stop,cp);
7410 throw INTERP_KERNEL::Exception(msg0);
7413 throw INTERP_KERNEL::Exception(msg0);
7414 cip[1]=cip[0]+delta;
7416 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7420 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7421 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7422 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7423 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7424 * are not used here to avoid the build of big permutation array.
7426 * \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
7427 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7428 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7429 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7430 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7431 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7432 * \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
7433 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7435 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7436 DataArrayInt *&szOfCellGrpOfSameType,
7437 DataArrayInt *&idInMsOfCellGrpOfSameType)
7439 std::vector<const MEDCouplingUMesh *> ms2;
7440 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7443 (*it)->checkConnectivityFullyDefined();
7447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7448 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7449 int meshDim=ms2[0]->getMeshDimension();
7450 std::vector<const MEDCouplingUMesh *> m1ssm;
7451 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7453 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7454 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7457 ret1->alloc(0,1); ret2->alloc(0,1);
7458 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7460 if(meshDim!=(*it)->getMeshDimension())
7461 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7462 if(refCoo!=(*it)->getCoords())
7463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7464 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7465 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7466 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7467 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7469 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7470 m1ssmSingleAuto.push_back(singleCell);
7471 m1ssmSingle.push_back(singleCell);
7472 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7475 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7477 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7478 for(std::size_t i=0;i<m1ssm.size();i++)
7479 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7480 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7481 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7482 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7487 * This method returns a newly created DataArrayInt instance.
7488 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7490 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7492 checkFullyDefined();
7493 const int *conn=_nodal_connec->getConstPointer();
7494 const int *connIndex=_nodal_connec_index->getConstPointer();
7495 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7496 for(const int *w=begin;w!=end;w++)
7497 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7498 ret->pushBackSilent(*w);
7503 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7504 * are in [0:getNumberOfCells())
7506 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7508 checkFullyDefined();
7509 const int *conn=_nodal_connec->getConstPointer();
7510 const int *connI=_nodal_connec_index->getConstPointer();
7511 int nbOfCells=getNumberOfCells();
7512 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7513 int *tmp=new int[nbOfCells];
7514 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7517 for(const int *i=connI;i!=connI+nbOfCells;i++)
7518 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7519 tmp[std::distance(connI,i)]=j++;
7521 DataArrayInt *ret=DataArrayInt::New();
7522 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7523 ret->copyStringInfoFrom(*da);
7524 int *retPtr=ret->getPointer();
7525 const int *daPtr=da->getConstPointer();
7526 int nbOfElems=da->getNbOfElems();
7527 for(int k=0;k<nbOfElems;k++)
7528 retPtr[k]=tmp[daPtr[k]];
7534 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7535 * This method \b works \b for mesh sorted by type.
7536 * cells whose ids is in 'idsPerGeoType' array.
7537 * This method conserves coords and name of mesh.
7539 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7541 std::vector<int> code=getDistributionOfTypes();
7542 std::size_t nOfTypesInThis=code.size()/3;
7543 int sz=0,szOfType=0;
7544 for(std::size_t i=0;i<nOfTypesInThis;i++)
7549 szOfType=code[3*i+1];
7551 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7552 if(*work<0 || *work>=szOfType)
7554 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7555 oss << ". It should be in [0," << szOfType << ") !";
7556 throw INTERP_KERNEL::Exception(oss.str().c_str());
7558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7559 int *idsPtr=idsTokeep->getPointer();
7561 for(std::size_t i=0;i<nOfTypesInThis;i++)
7564 for(int j=0;j<code[3*i+1];j++)
7567 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7568 offset+=code[3*i+1];
7570 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7571 ret->copyTinyInfoFrom(this);
7576 * This method returns a vector of size 'this->getNumberOfCells()'.
7577 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7579 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7581 int ncell=getNumberOfCells();
7582 std::vector<bool> ret(ncell);
7583 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7584 const int *c=getNodalConnectivity()->getConstPointer();
7585 for(int i=0;i<ncell;i++)
7587 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7588 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7589 ret[i]=cm.isQuadratic();
7595 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7597 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7599 if(other->getType()!=UNSTRUCTURED)
7600 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7601 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7602 return MergeUMeshes(this,otherC);
7606 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7607 * computed by averaging coordinates of cell nodes, so this method is not a right
7608 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7609 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7610 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7611 * components. The caller is to delete this array using decrRef() as it is
7613 * \throw If the coordinates array is not set.
7614 * \throw If the nodal connectivity of cells is not defined.
7615 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7617 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7619 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7620 int spaceDim=getSpaceDimension();
7621 int nbOfCells=getNumberOfCells();
7622 ret->alloc(nbOfCells,spaceDim);
7623 ret->copyStringInfoFrom(*getCoords());
7624 double *ptToFill=ret->getPointer();
7625 const int *nodal=_nodal_connec->getConstPointer();
7626 const int *nodalI=_nodal_connec_index->getConstPointer();
7627 const double *coor=_coords->getConstPointer();
7628 for(int i=0;i<nbOfCells;i++)
7630 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7631 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7638 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7639 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7641 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7642 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7644 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7645 * \throw If \a this is not fully defined (coordinates and connectivity)
7646 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7648 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7650 checkFullyDefined();
7651 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7652 int spaceDim=getSpaceDimension();
7653 int nbOfCells=getNumberOfCells();
7654 int nbOfNodes=getNumberOfNodes();
7655 ret->alloc(nbOfCells,spaceDim);
7656 double *ptToFill=ret->getPointer();
7657 const int *nodal=_nodal_connec->getConstPointer();
7658 const int *nodalI=_nodal_connec_index->getConstPointer();
7659 const double *coor=_coords->getConstPointer();
7660 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7662 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7663 std::fill(ptToFill,ptToFill+spaceDim,0.);
7664 if(type!=INTERP_KERNEL::NORM_POLYHED)
7666 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7668 if(*conn>=0 && *conn<nbOfNodes)
7669 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7672 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7673 throw INTERP_KERNEL::Exception(oss.str().c_str());
7676 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7677 if(nbOfNodesInCell>0)
7678 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7681 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7682 throw INTERP_KERNEL::Exception(oss.str().c_str());
7687 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7689 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7691 if(*it>=0 && *it<nbOfNodes)
7692 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7695 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7696 throw INTERP_KERNEL::Exception(oss.str().c_str());
7700 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7703 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7704 throw INTERP_KERNEL::Exception(oss.str().c_str());
7712 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7713 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7714 * are specified via an array of cell ids.
7715 * \warning Validity of the specified cell ids is not checked!
7716 * Valid range is [ 0, \a this->getNumberOfCells() ).
7717 * \param [in] begin - an array of cell ids of interest.
7718 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7719 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7720 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7721 * caller is to delete this array using decrRef() as it is no more needed.
7722 * \throw If the coordinates array is not set.
7723 * \throw If the nodal connectivity of cells is not defined.
7725 * \if ENABLE_EXAMPLES
7726 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7727 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7730 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7732 DataArrayDouble *ret=DataArrayDouble::New();
7733 int spaceDim=getSpaceDimension();
7734 int nbOfTuple=(int)std::distance(begin,end);
7735 ret->alloc(nbOfTuple,spaceDim);
7736 double *ptToFill=ret->getPointer();
7737 double *tmp=new double[spaceDim];
7738 const int *nodal=_nodal_connec->getConstPointer();
7739 const int *nodalI=_nodal_connec_index->getConstPointer();
7740 const double *coor=_coords->getConstPointer();
7741 for(const int *w=begin;w!=end;w++)
7743 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7744 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7752 * 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".
7753 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7754 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7755 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7756 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7758 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7759 * \throw If spaceDim!=3 or meshDim!=2.
7760 * \throw If connectivity of \a this is invalid.
7761 * \throw If connectivity of a cell in \a this points to an invalid node.
7763 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7765 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7766 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7767 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7768 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7769 ret->alloc(nbOfCells,4);
7770 double *retPtr(ret->getPointer());
7771 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7772 const double *coor(_coords->begin());
7773 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7775 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7776 if(nodalI[1]-nodalI[0]>=3)
7778 for(int j=0;j<3;j++)
7780 int nodeId(nodal[nodalI[0]+1+j]);
7781 if(nodeId>=0 && nodeId<nbOfNodes)
7782 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7785 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7786 throw INTERP_KERNEL::Exception(oss.str().c_str());
7792 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7793 throw INTERP_KERNEL::Exception(oss.str().c_str());
7795 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7796 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7802 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7805 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7809 da->checkAllocated();
7810 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7812 int nbOfTuples=da->getNumberOfTuples();
7813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7814 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7815 c->alloc(2*nbOfTuples,1);
7816 cI->alloc(nbOfTuples+1,1);
7817 int *cp=c->getPointer();
7818 int *cip=cI->getPointer();
7820 for(int i=0;i<nbOfTuples;i++)
7822 *cp++=INTERP_KERNEL::NORM_POINT1;
7826 ret->setConnectivity(c,cI,true);
7830 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7831 * Cells and nodes of
7832 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7833 * \param [in] mesh1 - the first mesh.
7834 * \param [in] mesh2 - the second mesh.
7835 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7836 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7837 * is no more needed.
7838 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7839 * \throw If the coordinates array is not set in none of the meshes.
7840 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7841 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7843 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7845 std::vector<const MEDCouplingUMesh *> tmp(2);
7846 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7847 return MergeUMeshes(tmp);
7851 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7852 * Cells and nodes of
7853 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7854 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7855 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7856 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7857 * is no more needed.
7858 * \throw If \a a.size() == 0.
7859 * \throw If \a a[ *i* ] == NULL.
7860 * \throw If the coordinates array is not set in none of the meshes.
7861 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7862 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7864 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7866 std::size_t sz=a.size();
7868 return MergeUMeshesLL(a);
7869 for(std::size_t ii=0;ii<sz;ii++)
7872 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7873 throw INTERP_KERNEL::Exception(oss.str().c_str());
7875 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7876 std::vector< const MEDCouplingUMesh * > aa(sz);
7878 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7880 const MEDCouplingUMesh *cur=a[i];
7881 const DataArrayDouble *coo=cur->getCoords();
7883 spaceDim=coo->getNumberOfComponents();
7886 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7887 for(std::size_t i=0;i<sz;i++)
7889 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7892 return MergeUMeshesLL(aa);
7897 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7900 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7901 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7902 int meshDim=(*it)->getMeshDimension();
7903 int nbOfCells=(*it)->getNumberOfCells();
7904 int meshLgth=(*it++)->getMeshLength();
7905 for(;it!=a.end();it++)
7907 if(meshDim!=(*it)->getMeshDimension())
7908 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7909 nbOfCells+=(*it)->getNumberOfCells();
7910 meshLgth+=(*it)->getMeshLength();
7912 std::vector<const MEDCouplingPointSet *> aps(a.size());
7913 std::copy(a.begin(),a.end(),aps.begin());
7914 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7915 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7916 ret->setCoords(pts);
7917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7918 c->alloc(meshLgth,1);
7919 int *cPtr=c->getPointer();
7920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7921 cI->alloc(nbOfCells+1,1);
7922 int *cIPtr=cI->getPointer();
7926 for(it=a.begin();it!=a.end();it++)
7928 int curNbOfCell=(*it)->getNumberOfCells();
7929 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7930 const int *curC=(*it)->_nodal_connec->getConstPointer();
7931 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7932 for(int j=0;j<curNbOfCell;j++)
7934 const int *src=curC+curCI[j];
7936 for(;src!=curC+curCI[j+1];src++,cPtr++)
7944 offset+=curCI[curNbOfCell];
7945 offset2+=(*it)->getNumberOfNodes();
7948 ret->setConnectivity(c,cI,true);
7955 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7956 * dimension and sharing the node coordinates array.
7957 * All cells of the first mesh precede all cells of the second mesh
7958 * within the result mesh.
7959 * \param [in] mesh1 - the first mesh.
7960 * \param [in] mesh2 - the second mesh.
7961 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7962 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7963 * is no more needed.
7964 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7965 * \throw If the meshes do not share the node coordinates array.
7966 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7967 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7969 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7971 std::vector<const MEDCouplingUMesh *> tmp(2);
7972 tmp[0]=mesh1; tmp[1]=mesh2;
7973 return MergeUMeshesOnSameCoords(tmp);
7977 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7978 * dimension and sharing the node coordinates array.
7979 * All cells of the *i*-th mesh precede all cells of the
7980 * (*i*+1)-th mesh within the result mesh.
7981 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7982 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7983 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7984 * is no more needed.
7985 * \throw If \a a.size() == 0.
7986 * \throw If \a a[ *i* ] == NULL.
7987 * \throw If the meshes do not share the node coordinates array.
7988 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7989 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7991 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7994 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7995 for(std::size_t ii=0;ii<meshes.size();ii++)
7998 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7999 throw INTERP_KERNEL::Exception(oss.str().c_str());
8001 const DataArrayDouble *coords=meshes.front()->getCoords();
8002 int meshDim=meshes.front()->getMeshDimension();
8003 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8005 int meshIndexLgth=0;
8006 for(;iter!=meshes.end();iter++)
8008 if(coords!=(*iter)->getCoords())
8009 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8010 if(meshDim!=(*iter)->getMeshDimension())
8011 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8012 meshLgth+=(*iter)->getMeshLength();
8013 meshIndexLgth+=(*iter)->getNumberOfCells();
8015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8016 nodal->alloc(meshLgth,1);
8017 int *nodalPtr=nodal->getPointer();
8018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8019 nodalIndex->alloc(meshIndexLgth+1,1);
8020 int *nodalIndexPtr=nodalIndex->getPointer();
8022 for(iter=meshes.begin();iter!=meshes.end();iter++)
8024 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8025 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8026 int nbOfCells=(*iter)->getNumberOfCells();
8027 int meshLgth2=(*iter)->getMeshLength();
8028 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8029 if(iter!=meshes.begin())
8030 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8032 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8035 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8036 ret->setName("merge");
8037 ret->setMeshDimension(meshDim);
8038 ret->setConnectivity(nodal,nodalIndex,true);
8039 ret->setCoords(coords);
8044 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8045 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8046 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8047 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8048 * New" mode are returned for each input mesh.
8049 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8050 * \param [in] compType - specifies a cell comparison technique. For meaning of its
8051 * valid values [0,1,2], see zipConnectivityTraducer().
8052 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8053 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8054 * mesh. The caller is to delete each of the arrays using decrRef() as it is
8056 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8057 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8058 * is no more needed.
8059 * \throw If \a meshes.size() == 0.
8060 * \throw If \a meshes[ *i* ] == NULL.
8061 * \throw If the meshes do not share the node coordinates array.
8062 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8063 * \throw If the \a meshes are of different dimension (getMeshDimension()).
8064 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8065 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
8067 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8069 //All checks are delegated to MergeUMeshesOnSameCoords
8070 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8072 corr.resize(meshes.size());
8073 std::size_t nbOfMeshes=meshes.size();
8075 const int *o2nPtr=o2n->getConstPointer();
8076 for(std::size_t i=0;i<nbOfMeshes;i++)
8078 DataArrayInt *tmp=DataArrayInt::New();
8079 int curNbOfCells=meshes[i]->getNumberOfCells();
8080 tmp->alloc(curNbOfCells,1);
8081 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8082 offset+=curNbOfCells;
8083 tmp->setName(meshes[i]->getName());
8090 * Makes all given meshes share the nodal connectivity array. The common connectivity
8091 * array is created by concatenating the connectivity arrays of all given meshes. All
8092 * the given meshes must be of the same space dimension but dimension of cells **can
8093 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8094 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8095 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8096 * \param [in,out] meshes - a vector of meshes to update.
8097 * \throw If any of \a meshes is NULL.
8098 * \throw If the coordinates array is not set in any of \a meshes.
8099 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8100 * \throw If \a meshes are of different space dimension.
8102 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8104 std::size_t sz=meshes.size();
8107 std::vector< const DataArrayDouble * > coords(meshes.size());
8108 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8109 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8113 (*it)->checkConnectivityFullyDefined();
8114 const DataArrayDouble *coo=(*it)->getCoords();
8119 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8120 oss << " has no coordinate array defined !";
8121 throw INTERP_KERNEL::Exception(oss.str().c_str());
8126 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8127 oss << " is null !";
8128 throw INTERP_KERNEL::Exception(oss.str().c_str());
8131 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8132 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8133 int offset=(*it)->getNumberOfNodes();
8134 (*it++)->setCoords(res);
8135 for(;it!=meshes.end();it++)
8137 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8138 (*it)->setCoords(res);
8139 (*it)->shiftNodeNumbersInConn(offset);
8140 offset+=oldNumberOfNodes;
8145 * Merges nodes coincident with a given precision within all given meshes that share
8146 * the nodal connectivity array. The given meshes **can be of different** mesh
8147 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8148 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8149 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8150 * \param [in,out] meshes - a vector of meshes to update.
8151 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8152 * \throw If any of \a meshes is NULL.
8153 * \throw If the \a meshes do not share the same node coordinates array.
8154 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8156 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8160 std::set<const DataArrayDouble *> s;
8161 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8164 s.insert((*it)->getCoords());
8167 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 !";
8168 throw INTERP_KERNEL::Exception(oss.str().c_str());
8173 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 !";
8174 throw INTERP_KERNEL::Exception(oss.str().c_str());
8176 const DataArrayDouble *coo=*(s.begin());
8180 DataArrayInt *comm,*commI;
8181 coo->findCommonTuples(eps,-1,comm,commI);
8182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8183 int oldNbOfNodes=coo->getNumberOfTuples();
8185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8186 if(oldNbOfNodes==newNbOfNodes)
8188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8189 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8191 (*it)->renumberNodesInConn(o2n->getConstPointer());
8192 (*it)->setCoords(newCoords);
8197 * 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.
8198 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8199 * \param isQuad specifies the policy of connectivity.
8200 * @ret in/out parameter in which the result will be append
8202 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8204 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8205 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8206 ret.push_back(cm.getExtrudedType());
8207 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8210 case INTERP_KERNEL::NORM_POINT1:
8212 ret.push_back(connBg[1]);
8213 ret.push_back(connBg[1]+nbOfNodesPerLev);
8216 case INTERP_KERNEL::NORM_SEG2:
8218 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8219 ret.insert(ret.end(),conn,conn+4);
8222 case INTERP_KERNEL::NORM_SEG3:
8224 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8225 ret.insert(ret.end(),conn,conn+8);
8228 case INTERP_KERNEL::NORM_QUAD4:
8230 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8231 ret.insert(ret.end(),conn,conn+8);
8234 case INTERP_KERNEL::NORM_TRI3:
8236 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8237 ret.insert(ret.end(),conn,conn+6);
8240 case INTERP_KERNEL::NORM_TRI6:
8242 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,
8243 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8244 ret.insert(ret.end(),conn,conn+15);
8247 case INTERP_KERNEL::NORM_QUAD8:
8250 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8251 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8252 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8254 ret.insert(ret.end(),conn,conn+20);
8257 case INTERP_KERNEL::NORM_POLYGON:
8259 std::back_insert_iterator< std::vector<int> > ii(ret);
8260 std::copy(connBg+1,connEnd,ii);
8262 std::reverse_iterator<const int *> rConnBg(connEnd);
8263 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8264 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8265 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8266 for(std::size_t i=0;i<nbOfRadFaces;i++)
8269 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8270 std::copy(conn,conn+4,ii);
8275 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8280 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8282 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8285 double v[3]={0.,0.,0.};
8286 std::size_t sz=std::distance(begin,end);
8291 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];
8292 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8293 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8295 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8297 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8298 // SEG3 forming a circle):
8299 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8301 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8302 for(std::size_t j=0;j<sz;j++)
8304 if (j%2) // current point i is quadratic, next point i+1 is standard
8307 ip1 = (j+1)%sz; // ip1 = "i+1"
8309 else // current point i is standard, next point i+1 is quadratic
8314 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8315 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8316 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8318 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8324 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8326 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8328 std::vector<std::pair<int,int> > edges;
8329 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8330 const int *bgFace=begin;
8331 for(std::size_t i=0;i<nbOfFaces;i++)
8333 const int *endFace=std::find(bgFace+1,end,-1);
8334 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8335 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8337 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8338 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8340 edges.push_back(p1);
8344 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8348 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8350 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8352 double vec0[3],vec1[3];
8353 std::size_t sz=std::distance(begin,end);
8355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8356 int nbOfNodes=(int)sz/2;
8357 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8358 const double *pt0=coords+3*begin[0];
8359 const double *pt1=coords+3*begin[nbOfNodes];
8360 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8361 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8364 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8366 std::size_t sz=std::distance(begin,end);
8367 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8368 std::size_t nbOfNodes(sz/2);
8369 std::copy(begin,end,(int *)tmp);
8370 for(std::size_t j=1;j<nbOfNodes;j++)
8372 begin[j]=tmp[nbOfNodes-j];
8373 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8377 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8379 std::size_t sz=std::distance(begin,end);
8381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8382 double vec0[3],vec1[3];
8383 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8384 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];
8385 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;
8388 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8390 std::size_t sz=std::distance(begin,end);
8392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8394 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8395 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8396 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8400 * 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 )
8401 * 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
8404 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8405 * \param [in] coords the coordinates with nb of components exactly equal to 3
8406 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8407 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8408 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8410 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8412 int nbFaces=std::count(begin+1,end,-1)+1;
8413 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8414 double *vPtr=v->getPointer();
8415 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8416 double *pPtr=p->getPointer();
8417 const int *stFaceConn=begin+1;
8418 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8420 const int *endFaceConn=std::find(stFaceConn,end,-1);
8421 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8422 stFaceConn=endFaceConn+1;
8424 pPtr=p->getPointer(); vPtr=v->getPointer();
8425 DataArrayInt *comm1=0,*commI1=0;
8426 v->findCommonTuples(eps,-1,comm1,commI1);
8427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8428 const int *comm1Ptr=comm1->getConstPointer();
8429 const int *commI1Ptr=commI1->getConstPointer();
8430 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8431 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8434 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8435 mm->finishInsertingCells();
8437 for(int i=0;i<nbOfGrps1;i++)
8439 int vecId=comm1Ptr[commI1Ptr[i]];
8440 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8441 DataArrayInt *comm2=0,*commI2=0;
8442 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8443 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8444 const int *comm2Ptr=comm2->getConstPointer();
8445 const int *commI2Ptr=commI2->getConstPointer();
8446 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8447 for(int j=0;j<nbOfGrps2;j++)
8449 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8451 res->insertAtTheEnd(begin,end);
8452 res->pushBackSilent(-1);
8456 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8458 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8459 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8460 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8463 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8464 const int *idsNodePtr=idsNode->getConstPointer();
8465 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];
8466 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8467 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8468 if(std::abs(norm)>eps)
8470 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8471 mm3->rotate(center,vec,angle);
8473 mm3->changeSpaceDimension(2);
8474 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8475 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8476 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8477 int nbOfCells=mm4->getNumberOfCells();
8478 for(int k=0;k<nbOfCells;k++)
8481 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8482 res->pushBackSilent(idsNodePtr[*work]);
8483 res->pushBackSilent(-1);
8488 res->popBackSilent();
8492 * 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
8493 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8495 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8496 * \param [in] coords coordinates expected to have 3 components.
8497 * \param [in] begin start of the nodal connectivity of the face.
8498 * \param [in] end end of the nodal connectivity (excluded) of the face.
8499 * \param [out] v the normalized vector of size 3
8500 * \param [out] p the pos of plane
8502 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8504 std::size_t nbPoints=std::distance(begin,end);
8506 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8507 double vec[3]={0.,0.,0.};
8509 bool refFound=false;
8510 for(;j<nbPoints-1 && !refFound;j++)
8512 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8513 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8514 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8515 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8519 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8522 for(std::size_t i=j;i<nbPoints-1;i++)
8525 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8526 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8527 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8528 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8531 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8532 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];
8533 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8536 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8537 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8541 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8545 * This method tries to obtain a well oriented polyhedron.
8546 * If the algorithm fails, an exception will be thrown.
8548 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8550 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8551 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8552 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8554 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8555 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8556 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8558 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8561 std::size_t smthChanged=0;
8562 for(std::size_t i=0;i<nbOfFaces;i++)
8564 endFace=std::find(bgFace+1,end,-1);
8565 nbOfEdgesInFace=std::distance(bgFace,endFace);
8569 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8571 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8572 std::pair<int,int> p2(p1.second,p1.first);
8573 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8574 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8575 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8580 std::reverse(bgFace+1,endFace);
8581 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8583 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8584 std::pair<int,int> p2(p1.second,p1.first);
8585 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8586 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8587 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8588 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8589 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8590 if(it!=edgesOK.end())
8593 edgesFinished.push_back(p1);
8596 edgesOK.push_back(p1);
8603 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8605 if(!edgesOK.empty())
8606 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8607 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8608 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8610 for(std::size_t i=0;i<nbOfFaces;i++)
8612 endFace=std::find(bgFace+1,end,-1);
8613 std::reverse(bgFace+1,endFace);
8619 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8621 int nbOfNodesExpected(skin->getNumberOfNodes());
8622 const int *n2oPtr(n2o->getConstPointer());
8623 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8624 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8625 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8626 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8627 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8629 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8630 if(nbOfNodesExpected<1)
8632 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8633 *work++=n2oPtr[prevNode];
8634 for(int i=1;i<nbOfNodesExpected;i++)
8636 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8638 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8639 conn.erase(prevNode);
8642 int curNode(*(conn.begin()));
8643 *work++=n2oPtr[curNode];
8644 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8645 shar.erase(prevCell);
8648 prevCell=*(shar.begin());
8652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8655 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8658 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8663 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8665 int nbOfNodesExpected(skin->getNumberOfNodes());
8666 int nbOfTurn(nbOfNodesExpected/2);
8667 const int *n2oPtr(n2o->getConstPointer());
8668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8669 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8670 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8671 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8672 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8674 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8675 if(nbOfNodesExpected<1)
8677 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8678 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8679 for(int i=1;i<nbOfTurn;i++)
8681 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8683 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8684 conn.erase(prevNode);
8687 int curNode(*(conn.begin()));
8688 *work=n2oPtr[curNode];
8689 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8690 shar.erase(prevCell);
8693 int curCell(*(shar.begin()));
8694 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8706 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8712 * This method makes the assumption spacedimension == meshdimension == 2.
8713 * This method works only for linear cells.
8715 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8717 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8719 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8720 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8721 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8722 int oldNbOfNodes(skin->getNumberOfNodes());
8723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8724 int nbOfNodesExpected(skin->getNumberOfNodes());
8725 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8726 int nbCells(skin->getNumberOfCells());
8727 if(nbCells==nbOfNodesExpected)
8728 return buildUnionOf2DMeshLinear(skin,n2o);
8729 else if(2*nbCells==nbOfNodesExpected)
8730 return buildUnionOf2DMeshQuadratic(skin,n2o);
8732 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8736 * This method makes the assumption spacedimension == meshdimension == 3.
8737 * This method works only for linear cells.
8739 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8741 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8743 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8745 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8746 const int *conn=m->getNodalConnectivity()->getConstPointer();
8747 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8748 int nbOfCells=m->getNumberOfCells();
8749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8750 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8753 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8754 for(int i=1;i<nbOfCells;i++)
8757 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8763 * \brief Creates a graph of cell neighbors
8764 * \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8765 * In the sky line array, graph arcs are stored in terms of (index,value) notation.
8767 * - index: 0 3 5 6 6
8768 * - value: 1 2 3 2 3 3
8769 * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8770 * Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8772 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8774 checkConnectivityFullyDefined();
8776 int meshDim = this->getMeshDimension();
8777 ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8778 ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8779 this->getReverseNodalConnectivity(revConn,indexr);
8780 const int* indexr_ptr=indexr->getConstPointer();
8781 const int* revConn_ptr=revConn->getConstPointer();
8783 const ParaMEDMEM::DataArrayInt* index;
8784 const ParaMEDMEM::DataArrayInt* conn;
8785 conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8786 index=this->getNodalConnectivityIndex();
8787 int nbCells=this->getNumberOfCells();
8788 const int* index_ptr=index->getConstPointer();
8789 const int* conn_ptr=conn->getConstPointer();
8791 //creating graph arcs (cell to cell relations)
8792 //arcs are stored in terms of (index,value) notation
8795 // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8796 // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8798 //warning here one node have less than or equal effective number of cell with it
8799 //but cell could have more than effective nodes
8800 //because other equals nodes in other domain (with other global inode)
8801 std::vector <int> cell2cell_index(nbCells+1,0);
8802 std::vector <int> cell2cell;
8803 cell2cell.reserve(3*nbCells);
8805 for (int icell=0; icell<nbCells;icell++)
8807 std::map<int,int > counter;
8808 for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8810 int inode=conn_ptr[iconn];
8811 for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8813 int icell2=revConn_ptr[iconnr];
8814 std::map<int,int>::iterator iter=counter.find(icell2);
8815 if (iter!=counter.end()) (iter->second)++;
8816 else counter.insert(std::make_pair(icell2,1));
8819 for (std::map<int,int>::const_iterator iter=counter.begin();
8820 iter!=counter.end(); iter++)
8821 if (iter->second >= meshDim)
8823 cell2cell_index[icell+1]++;
8824 cell2cell.push_back(iter->first);
8829 cell2cell_index[0]=0;
8830 for (int icell=0; icell<nbCells;icell++)
8831 cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8833 //filling up index and value to create skylinearray structure
8834 MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8839 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8840 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8842 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8846 for(int i=0;i<nbOfNodesInCell;i++)
8847 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8848 else if(spaceDim==2)
8850 for(int i=0;i<nbOfNodesInCell;i++)
8852 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8860 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8862 int nbOfCells=getNumberOfCells();
8864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8865 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};
8866 ofs << " <" << getVTKDataSetType() << ">\n";
8867 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8868 ofs << " <PointData>\n" << pointData << std::endl;
8869 ofs << " </PointData>\n";
8870 ofs << " <CellData>\n" << cellData << std::endl;
8871 ofs << " </CellData>\n";
8872 ofs << " <Points>\n";
8873 if(getSpaceDimension()==3)
8874 _coords->writeVTK(ofs,8,"Points",byteData);
8877 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8878 coo->writeVTK(ofs,8,"Points",byteData);
8880 ofs << " </Points>\n";
8881 ofs << " <Cells>\n";
8882 const int *cPtr=_nodal_connec->getConstPointer();
8883 const int *cIPtr=_nodal_connec_index->getConstPointer();
8884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8888 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8889 int szFaceOffsets=0,szConn=0;
8890 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8893 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8896 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8897 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8901 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8902 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8903 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8904 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8905 w4=std::copy(c.begin(),c.end(),w4);
8908 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8909 types->writeVTK(ofs,8,"UInt8","types",byteData);
8910 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8911 if(szFaceOffsets!=0)
8912 {//presence of Polyhedra
8913 connectivity->reAlloc(szConn);
8914 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8916 w1=faces->getPointer();
8917 for(int i=0;i<nbOfCells;i++)
8918 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8920 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8922 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8923 for(int j=0;j<nbFaces;j++)
8925 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8926 *w1++=(int)std::distance(w6,w5);
8927 w1=std::copy(w6,w5,w1);
8931 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8933 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8934 ofs << " </Cells>\n";
8935 ofs << " </Piece>\n";
8936 ofs << " </" << getVTKDataSetType() << ">\n";
8939 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8941 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8943 { stream << " Not set !"; return ; }
8944 stream << " Mesh dimension : " << _mesh_dim << ".";
8948 { stream << " No coordinates set !"; return ; }
8949 if(!_coords->isAllocated())
8950 { stream << " Coordinates set but not allocated !"; return ; }
8951 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8952 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8953 if(!_nodal_connec_index)
8954 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8955 if(!_nodal_connec_index->isAllocated())
8956 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8957 int lgth=_nodal_connec_index->getNumberOfTuples();
8958 int cpt=_nodal_connec_index->getNumberOfComponents();
8959 if(cpt!=1 || lgth<1)
8961 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8964 std::string MEDCouplingUMesh::getVTKDataSetType() const
8966 return std::string("UnstructuredGrid");
8969 std::string MEDCouplingUMesh::getVTKFileExtension() const
8971 return std::string("vtu");
8975 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8976 * returns a result mesh constituted by polygons.
8977 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8978 * all nodes from m2.
8979 * The meshes should be in 2D space. In
8980 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8982 * \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
8983 * 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)
8984 * \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
8985 * 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)
8986 * \param [in] eps - precision used to detect coincident mesh entities.
8987 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8988 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8989 * this array using decrRef() as it is no more needed.
8990 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8991 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8992 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8993 * any cell of \a m2. The caller is to delete this array using decrRef() as
8994 * it is no more needed.
8995 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8996 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8997 * is no more needed.
8998 * \throw If the coordinates array is not set in any of the meshes.
8999 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
9000 * \throw If any of the meshes is not a 2D mesh in 2D space.
9002 * \sa conformize2D, mergeNodes
9004 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9005 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9008 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9009 m1->checkFullyDefined();
9010 m2->checkFullyDefined();
9011 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
9014 // Step 1: compute all edge intersections (new nodes)
9015 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9016 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9017 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9018 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9019 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9020 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9021 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9022 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9024 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9026 // Step 2: re-order newly created nodes according to the ordering found in m2
9027 std::vector< std::vector<int> > intersectEdge2;
9028 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9029 subDiv2.clear(); dd5=0; dd6=0;
9032 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9033 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9034 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9035 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9037 // Step 4: Prepare final result:
9038 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9039 addCooDa->alloc((int)(addCoo.size())/2,2);
9040 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9042 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9043 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9044 std::vector<const DataArrayDouble *> coordss(4);
9045 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9046 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9047 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9052 ret->setConnectivity(conn,connI,true);
9053 ret->setCoords(coo);
9054 cellNb1=c1.retn(); cellNb2=c2.retn();
9060 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9062 if(candidates.empty())
9064 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9066 const std::vector<int>& pool(intersectEdge1[*it]);
9067 int tmp[2]; tmp[0]=start; tmp[1]=stop;
9068 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9073 tmp[0]=stop; tmp[1]=start;
9074 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9083 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,
9084 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9086 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9087 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9088 int nCells(mesh1D->getNumberOfCells());
9089 if(nCells!=(int)intersectEdge2.size())
9090 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9091 const DataArrayDouble *coo2(mesh1D->getCoords());
9092 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9093 const double *coo2Ptr(coo2->begin());
9094 int offset1(coords1->getNumberOfTuples());
9095 int offset2(offset1+coo2->getNumberOfTuples());
9096 int offset3(offset2+addCoo.size()/2);
9097 std::vector<double> addCooQuad;
9098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9099 int tmp[4],cicnt(0),kk(0);
9100 for(int i=0;i<nCells;i++)
9102 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9103 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9104 const std::vector<int>& subEdges(intersectEdge2[i]);
9105 int nbSubEdge(subEdges.size()/2);
9106 for(int j=0;j<nbSubEdge;j++,kk++)
9108 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));
9109 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9110 INTERP_KERNEL::Edge *e2Ptr(e2);
9111 std::map<int,int>::const_iterator itm;
9112 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9114 tmp[0]=INTERP_KERNEL::NORM_SEG3;
9115 itm=mergedNodes.find(subEdges[2*j]);
9116 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9117 itm=mergedNodes.find(subEdges[2*j+1]);
9118 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9119 tmp[3]=offset3+(int)addCooQuad.size()/2;
9121 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9123 cOut->insertAtTheEnd(tmp,tmp+4);
9124 ciOut->pushBackSilent(cicnt);
9128 tmp[0]=INTERP_KERNEL::NORM_SEG2;
9129 itm=mergedNodes.find(subEdges[2*j]);
9130 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9131 itm=mergedNodes.find(subEdges[2*j+1]);
9132 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9134 cOut->insertAtTheEnd(tmp,tmp+3);
9135 ciOut->pushBackSilent(cicnt);
9138 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9140 idsInRetColinear->pushBackSilent(kk);
9141 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9146 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9147 ret->setConnectivity(cOut,ciOut,true);
9148 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9149 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9150 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9151 std::vector<const DataArrayDouble *> coordss(4);
9152 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9153 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9154 ret->setCoords(arr);
9158 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9160 std::vector<int> allEdges;
9161 for(const int *it2(descBg);it2!=descEnd;it2++)
9163 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9165 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9167 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9169 std::size_t nb(allEdges.size());
9171 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9172 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9173 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9174 ret->setCoords(coords);
9175 ret->allocateCells(1);
9176 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9177 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9178 connOut[kk]=allEdges[2*kk];
9179 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9183 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9185 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9186 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9188 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9189 if(sz!=std::distance(descBg,descEnd))
9190 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9191 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9192 std::vector<int> allEdges,centers;
9193 const double *coordsPtr(coords->begin());
9194 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9195 int offset(coords->getNumberOfTuples());
9196 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9198 INTERP_KERNEL::NormalizedCellType typeOfSon;
9199 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
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 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9208 {//the current edge has been subsplit -> create corresponding centers.
9209 std::size_t nbOfCentersToAppend(edge1.size()/2);
9210 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9211 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9212 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9213 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9216 const double *aa(coordsPtr+2*(*it3++));
9217 const double *bb(coordsPtr+2*(*it3++));
9218 ee->getMiddleOfPoints(aa,bb,tmpp);
9219 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9220 centers.push_back(offset+k);
9224 std::size_t nb(allEdges.size());
9226 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9227 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9228 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9230 ret->setCoords(coords);
9233 addCoo->rearrange(2);
9234 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9235 ret->setCoords(addCoo);
9237 ret->allocateCells(1);
9238 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9239 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9240 connOut[kk]=allEdges[2*kk];
9241 connOut.insert(connOut.end(),centers.begin(),centers.end());
9242 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9247 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9250 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9252 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9254 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9255 if(!cm.isQuadratic())
9256 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9258 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9261 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9264 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9266 const INTERP_KERNEL::Edge *ee(*it);
9267 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9271 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9274 const double *coo(mesh2D->getCoords()->begin());
9275 std::size_t sz(conn.size());
9276 std::vector<double> addCoo;
9277 std::vector<int> conn2(conn);
9278 int offset(mesh2D->getNumberOfNodes());
9279 for(std::size_t i=0;i<sz;i++)
9282 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9283 addCoo.insert(addCoo.end(),tmp,tmp+2);
9284 conn2.push_back(offset+(int)i);
9286 mesh2D->getCoords()->rearrange(1);
9287 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9288 mesh2D->getCoords()->rearrange(2);
9289 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9294 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9296 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9297 * a set of edges defined in \a splitMesh1D.
9299 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9300 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9302 std::size_t nb(edge1Bis.size()/2);
9303 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9304 int iEnd(splitMesh1D->getNumberOfCells());
9306 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9308 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9309 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9310 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9313 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9314 out0.resize(1); out1.resize(1);
9315 std::vector<int>& connOut(out0[0]);
9316 connOut.resize(nbOfEdgesOf2DCellSplit);
9317 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9318 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9319 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9321 connOut[kk]=edge1Bis[2*kk];
9322 edgesPtr[kk]=edge1BisPtr[2*kk];
9327 // [i,iEnd[ contains the
9328 out0.resize(2); out1.resize(2);
9329 std::vector<int>& connOutLeft(out0[0]);
9330 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9331 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9332 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9333 for(std::size_t k=ii;k<jj+1;k++)
9334 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9335 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9336 for(int ik=0;ik<iEnd;ik++)
9338 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9339 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9342 for(int ik=iEnd-1;ik>=0;ik--)
9343 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9344 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9345 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9346 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9347 for(int ik=0;ik<iEnd;ik++)
9348 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9349 eright.insert(eright.end(),ees.begin(),ees.end());
9361 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9363 std::vector<int> _edges;
9364 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9367 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9369 std::size_t nbe(edges.size());
9370 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9371 for(std::size_t i=0;i<nbe;i++)
9373 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9374 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9376 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9377 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9378 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9384 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9385 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9386 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9387 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9388 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9393 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9398 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9400 const MEDCouplingUMesh *mesh(_mesh);
9406 { _left++; _right++; return ; }
9409 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9410 if((isLeft && isRight) || (!isLeft && !isRight))
9411 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9422 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9423 if((isLeft && isRight) || (!isLeft && !isRight))
9424 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9439 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9441 const MEDCouplingUMesh *mesh(_mesh);
9444 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9447 {// not fully splitting cell case
9448 if(mesh2D->getNumberOfCells()==1)
9449 {//little optimization. 1 cell no need to find in which cell mesh is !
9450 neighbors[0]=offset; neighbors[1]=offset;
9455 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9456 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9458 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9459 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9464 class VectorOfCellInfo
9467 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9468 std::size_t size() const { return _pool.size(); }
9469 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9470 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);
9471 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9472 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9473 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9474 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9476 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9477 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9478 const CellInfo& get(int pos) const;
9479 CellInfo& get(int pos);
9481 std::vector<CellInfo> _pool;
9482 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9483 std::vector<EdgeInfo> _edge_info;
9486 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9488 _pool[0]._edges=edges;
9489 _pool[0]._edges_ptr=edgesPtr;
9492 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9495 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9498 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9500 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9501 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9502 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9505 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)
9507 get(pos);//to check pos
9508 bool isFast(pos==0 && _pool.size()==1);
9509 std::size_t sz(edges.size());
9510 // dealing with edges
9512 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9514 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9516 std::vector<CellInfo> pool(_pool.size()-1+sz);
9517 for(int i=0;i<pos;i++)
9519 for(std::size_t j=0;j<sz;j++)
9520 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9521 for(int i=pos+1;i<(int)_pool.size();i++)
9522 pool[i+sz-1]=_pool[i];
9526 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9534 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9537 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9541 if(pos<_ze_mesh->getNumberOfCells()-1)
9543 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9546 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9547 for(std::size_t j=0;j<ms2.size();j++)
9549 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9552 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9554 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9557 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9560 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9562 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9564 if((*it).isInMyRange(pos))
9567 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9570 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9572 get(pos);//to check;
9573 if(_edge_info.empty())
9575 std::size_t sz(_edge_info.size()-1);
9576 for(std::size_t i=0;i<sz;i++)
9577 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9580 const CellInfo& VectorOfCellInfo::get(int pos) const
9582 if(pos<0 || pos>=(int)_pool.size())
9583 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9587 CellInfo& VectorOfCellInfo::get(int pos)
9589 if(pos<0 || pos>=(int)_pool.size())
9590 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9596 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9597 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9599 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9601 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9603 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9605 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9606 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9608 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9609 if(nbCellsInSplitMesh1D==0)
9610 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9611 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9612 std::size_t nb(allEdges.size()),jj;
9614 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9615 std::vector<int> edge1Bis(nb*2);
9616 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9617 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9618 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9619 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9620 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9622 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9623 int *idsLeftRightPtr(idsLeftRight->getPointer());
9624 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9625 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9626 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9628 for(;iEnd<nbCellsInSplitMesh1D;)
9630 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9636 if(iEnd<nbCellsInSplitMesh1D)
9639 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9640 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9642 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9643 retTmp->setCoords(splitMesh1D->getCoords());
9644 retTmp->allocateCells();
9646 std::vector< std::vector<int> > out0;
9647 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9649 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9650 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9651 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9652 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9656 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9657 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9658 return pool.getZeMesh().retn();
9661 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9662 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9665 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9667 std::vector<int> allEdges;
9668 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9669 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9671 int edgeId(std::abs(*it)-1);
9672 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9673 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9674 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9676 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9678 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9679 std::size_t sz(edge1.size());
9680 for(std::size_t cnt=0;cnt<sz;cnt++)
9681 allEdgesPtr.push_back(ee);
9684 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9687 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9689 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9690 {//easy case comparison not
9691 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9693 else if(typ1.isQuadratic() && typ2.isQuadratic())
9695 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9698 if(conn1[2]==conn2[2])
9700 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9701 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9705 {//only one is quadratic
9706 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9709 const double *a(0),*bb(0),*be(0);
9710 if(typ1.isQuadratic())
9712 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9716 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9718 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9719 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9725 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9726 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9728 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9730 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9732 if(candidatesIn2DEnd==candidatesIn2DBg)
9733 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9734 const double *coo(mesh2DSplit->getCoords()->begin());
9735 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9736 return *candidatesIn2DBg;
9737 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9738 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9739 if(cellIdInMesh1DSplitRelative<0)
9740 cur1D->changeOrientationOfCells();
9741 const int *c1D(cur1D->getNodalConnectivity()->begin());
9742 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9743 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9745 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9746 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9747 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9748 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9749 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9750 for(unsigned it2=0;it2<sz;it2++)
9752 INTERP_KERNEL::NormalizedCellType typeOfSon;
9753 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9754 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9755 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9759 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9765 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9766 * 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
9767 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9768 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9770 * \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
9771 * 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)
9772 * \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
9773 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9774 * \param [in] eps - precision used to perform intersections and localization operations.
9775 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9776 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9777 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9778 * 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.
9779 * \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
9780 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9781 * 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.
9783 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9785 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9787 if(!mesh2D || !mesh1D)
9788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9789 mesh2D->checkFullyDefined();
9790 mesh1D->checkFullyDefined();
9791 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9792 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9794 // Step 1: compute all edge intersections (new nodes)
9795 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9796 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9797 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9798 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9800 // Build desc connectivity
9801 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9803 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9804 std::map<int,int> mergedNodes;
9805 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9806 // use mergeNodes to fix intersectEdge1
9807 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9809 std::size_t n((*it0).size()/2);
9810 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9811 std::map<int,int>::const_iterator it1;
9812 it1=mergedNodes.find(eltStart);
9813 if(it1!=mergedNodes.end())
9814 (*it0)[0]=(*it1).second;
9815 it1=mergedNodes.find(eltEnd);
9816 if(it1!=mergedNodes.end())
9817 (*it0)[2*n-1]=(*it1).second;
9820 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9821 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9822 // Step 2: re-order newly created nodes according to the ordering found in m2
9823 std::vector< std::vector<int> > intersectEdge2;
9824 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9826 // Step 3: compute splitMesh1D
9827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9829 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9830 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9833 // deal with cells in mesh2D that are not cut but only some of their edges are
9834 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9835 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9836 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9837 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
9838 if(!idsInDesc2DToBeRefined->empty())
9840 DataArrayInt *out0(0),*outi0(0);
9841 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9844 out0s=out0s->buildUnique();
9848 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9849 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9851 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9854 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9855 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9858 if((DataArrayInt *)out0s)
9859 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9860 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9861 // OK all is ready to insert in ret2 mesh
9862 if(!untouchedCells->empty())
9863 {// the most easy part, cells in mesh2D not impacted at all
9864 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9865 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9866 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9868 if((DataArrayInt *)out0s)
9869 {// here dealing with cells in out0s but not in cellsToBeModified
9870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9871 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9872 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9874 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9875 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9877 int offset(ret2->getNumberOfTuples());
9878 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9879 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9880 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9881 int kk(0),*ret3ptr(partOfRet3->getPointer());
9882 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9884 int faceId(std::abs(*it)-1);
9885 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9887 int tmp(fewModifiedCells->locateValue(*it2));
9890 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9891 ret3ptr[2*kk]=tmp+offset;
9892 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9893 ret3ptr[2*kk+1]=tmp+offset;
9896 {//the current edge is shared by a 2D cell that will be split just after
9897 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9898 ret3ptr[2*kk]=-(*it2+1);
9899 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9900 ret3ptr[2*kk+1]=-(*it2+1);
9904 m1Desc->setCoords(ret1->getCoords());
9905 ret1NonCol->setCoords(ret1->getCoords());
9906 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9907 if(!outMesh2DSplit.empty())
9909 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9910 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9911 (*itt)->setCoords(da);
9914 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9915 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9918 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9920 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9922 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));
9923 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9924 outMesh2DSplit.push_back(splitOfOneCell);
9925 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9926 ret2->pushBackSilent(*it);
9929 std::size_t nbOfMeshes(outMesh2DSplit.size());
9930 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9931 for(std::size_t i=0;i<nbOfMeshes;i++)
9932 tmp[i]=outMesh2DSplit[i];
9934 ret1->getCoords()->setInfoOnComponents(compNames);
9935 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9936 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9939 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9941 int old2DCellId(-ret3->getIJ(*it,0)-1);
9942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9943 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
9945 ret3->changeValue(std::numeric_limits<int>::max(),-1);
9948 splitMesh1D=ret1.retn();
9949 splitMesh2D=ret2D.retn();
9950 cellIdInMesh2D=ret2.retn();
9951 cellIdInMesh1D=ret3.retn();
9955 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9956 * (newly created) nodes corresponding to the edge intersections.
9958 * @param[out] cr, crI connectivity of the resulting mesh
9959 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9960 * TODO: describe input parameters
9962 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9963 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9964 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9965 const std::vector<double>& addCoords,
9966 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9968 static const int SPACEDIM=2;
9969 const double *coo1(m1->getCoords()->getConstPointer());
9970 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9971 int offset1(m1->getNumberOfNodes());
9972 const double *coo2(m2->getCoords()->getConstPointer());
9973 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9974 int offset2(offset1+m2->getNumberOfNodes());
9975 int offset3(offset2+((int)addCoords.size())/2);
9976 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9977 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9978 // Here a BBTree on 2D-cells, not on segments:
9979 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9980 int ncell1(m1->getNumberOfCells());
9982 for(int i=0;i<ncell1;i++)
9984 std::vector<int> candidates2;
9985 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9986 std::map<INTERP_KERNEL::Node *,int> mapp;
9987 std::map<int,INTERP_KERNEL::Node *> mappRev;
9988 INTERP_KERNEL::QuadraticPolygon pol1;
9989 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9990 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9991 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9992 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9993 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9994 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9995 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9997 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
9998 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9999 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10000 for(it1.first();!it1.finished();it1.next())
10001 edges1.insert(it1.current()->getPtr());
10003 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10004 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10006 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10008 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10009 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10010 // Complete mapping with elements coming from the current cell it2 in mesh2:
10011 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10012 // pol2 is the new QP in the final merged result.
10013 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10014 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10017 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10019 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10020 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10021 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10022 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10024 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10025 // by m2 but that we still want to keep in the final result.
10026 if(!edges1.empty())
10030 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10032 catch(INTERP_KERNEL::Exception& e)
10034 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();
10035 throw INTERP_KERNEL::Exception(oss.str().c_str());
10038 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10039 (*it).second->decrRef();
10044 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10045 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10046 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10047 * The caller is to deal with the resulting DataArrayInt.
10048 * \throw If the coordinate array is not set.
10049 * \throw If the nodal connectivity of the cells is not defined.
10050 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10051 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10053 * \sa DataArrayInt::sortEachPairToMakeALinkedList
10055 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10057 checkFullyDefined();
10058 if(getMeshDimension()!=1)
10059 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10061 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10064 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10065 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10066 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10068 const int * dsi(_dsi->getConstPointer());
10069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10071 if (dsii->getNumberOfTuples())
10072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10074 int nc(getNumberOfCells());
10075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10076 result->alloc(nc,1);
10078 // set of edges not used so far
10079 std::set<int> edgeSet;
10080 for (int i=0; i<nc; edgeSet.insert(i), i++);
10084 // while we have points with only one neighbor segments
10087 std::list<int> linePiece;
10088 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10089 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10091 // Fill the list forward (resp. backward) from the start segment:
10092 int activeSeg = startSeg;
10093 int prevPointId = -20;
10095 while (!edgeSet.empty())
10097 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10100 linePiece.push_back(activeSeg);
10102 linePiece.push_front(activeSeg);
10103 edgeSet.erase(activeSeg);
10106 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10107 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10108 if (dsi[ptId] == 1) // hitting the end of the line
10110 prevPointId = ptId;
10111 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10112 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10115 // Done, save final piece into DA:
10116 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10117 newIdx += linePiece.size();
10119 // identify next valid start segment (one which is not consumed)
10120 if(!edgeSet.empty())
10121 startSeg = *(edgeSet.begin());
10123 while (!edgeSet.empty());
10124 return result.retn();
10129 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10131 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10132 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10134 throw INTERP_KERNEL::Exception("Internal error in remapping !");
10135 int v((*it).second);
10136 if(v==forbVal0 || v==forbVal1)
10138 if(std::find(isect.begin(),isect.end(),v)==isect.end())
10139 isect.push_back(v);
10142 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10147 bool presenceOfOn(false);
10148 for(int i=0;i<sz;i++)
10150 INTERP_KERNEL::ElementaryEdge *e(c[i]);
10151 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10153 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10154 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10156 return presenceOfOn;
10162 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10163 * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10164 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10165 * a minimal creation of new nodes is wanted.
10166 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10167 * nodes if a SEG3 is split without information of middle.
10168 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10169 * avoid to have a non conform mesh.
10171 * \return int - the number of new nodes created (in most of cases 0).
10173 * \throw If \a this is not coherent.
10174 * \throw If \a this has not spaceDim equal to 2.
10175 * \throw If \a this has not meshDim equal to 2.
10176 * \throw If some subcells needed to be split are orphan.
10177 * \sa MEDCouplingUMesh::conformize2D
10179 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10181 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10182 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10183 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10184 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10186 if(midOpt==0 && midOptI==0)
10188 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10191 else if(midOpt!=0 && midOptI!=0)
10192 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10194 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10198 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10199 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10200 * 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
10201 * 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).
10202 * 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.
10204 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10205 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10207 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10208 * This method expects that all nodes in \a this are not closer than \a eps.
10209 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10211 * \param [in] eps the relative error to detect merged edges.
10212 * \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
10213 * that the user is expected to deal with.
10215 * \throw If \a this is not coherent.
10216 * \throw If \a this has not spaceDim equal to 2.
10217 * \throw If \a this has not meshDim equal to 2.
10218 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10220 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10222 static const int SPACEDIM=2;
10224 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10225 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10227 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10228 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10229 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10230 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10231 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10232 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10233 std::vector<double> addCoo;
10234 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10235 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10236 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10237 for(int i=0;i<nDescCell;i++)
10239 std::vector<int> candidates;
10240 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10241 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10244 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10245 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10246 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10247 INTERP_KERNEL::MergePoints merge;
10248 INTERP_KERNEL::QuadraticPolygon c1,c2;
10249 e1->intersectWith(e2,merge,c1,c2);
10250 e1->decrRef(); e2->decrRef();
10251 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10252 overlapEdge[i].push_back(*it);
10253 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10254 overlapEdge[*it].push_back(i);
10257 // splitting done. sort intersect point in intersectEdge.
10258 std::vector< std::vector<int> > middle(nDescCell);
10259 int nbOf2DCellsToBeSplit(0);
10260 bool middleNeedsToBeUsed(false);
10261 std::vector<bool> cells2DToTreat(nDescCell,false);
10262 for(int i=0;i<nDescCell;i++)
10264 std::vector<int>& isect(intersectEdge[i]);
10265 int sz((int)isect.size());
10268 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10269 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10270 e->sortSubNodesAbs(coords,isect);
10275 int idx0(rdi[i]),idx1(rdi[i+1]);
10277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10278 if(!cells2DToTreat[rd[idx0]])
10280 cells2DToTreat[rd[idx0]]=true;
10281 nbOf2DCellsToBeSplit++;
10283 // try to reuse at most eventual 'middle' of SEG3
10284 std::vector<int>& mid(middle[i]);
10285 mid.resize(sz+1,-1);
10286 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10288 middleNeedsToBeUsed=true;
10289 const std::vector<int>& candidates(overlapEdge[i]);
10290 std::vector<int> trueCandidates;
10291 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10292 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10293 trueCandidates.push_back(*itc);
10294 int stNode(c[ci[i]+1]),endNode(isect[0]);
10295 for(int j=0;j<sz+1;j++)
10297 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10299 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10300 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10301 { mid[j]=*itc; break; }
10304 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10310 if(nbOf2DCellsToBeSplit==0)
10313 int *retPtr(ret->getPointer());
10314 for(int i=0;i<nCell;i++)
10315 if(cells2DToTreat[i])
10318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10319 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10320 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10321 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10322 if(middleNeedsToBeUsed)
10323 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10324 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10325 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10326 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.
10327 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10329 bool areNodesMerged; int newNbOfNodes;
10330 if(nbOfNodesCreated!=0)
10331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10337 * 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.
10338 * 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).
10339 * 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
10340 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10341 * 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
10342 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10344 * 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
10345 * using new instance, idem for coordinates.
10347 * 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.
10349 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10351 * \throw If \a this is not coherent.
10352 * \throw If \a this has not spaceDim equal to 2.
10353 * \throw If \a this has not meshDim equal to 2.
10355 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10357 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10361 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10363 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10364 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10365 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10366 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10367 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10368 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10369 const double *coords(_coords->begin());
10370 int *newciptr(newci->getPointer());
10371 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10373 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10374 ret->pushBackSilent(i);
10375 newciptr[1]=newc->getNumberOfTuples();
10380 if(!appendedCoords->empty())
10382 appendedCoords->rearrange(2);
10383 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10385 setCoords(newCoords);
10388 setConnectivity(newc,newci,true);
10393 * \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.
10394 * 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.
10395 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10396 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10397 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10398 * \param [out] addCoo - nodes to be append at the end
10399 * \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.
10401 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10402 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)
10404 static const int SPACEDIM=2;
10405 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10406 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10407 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10408 // Build BB tree of all edges in the tool mesh (second mesh)
10409 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10410 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10411 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10412 intersectEdge1.resize(nDescCell1);
10413 colinear2.resize(nDescCell2);
10414 subDiv2.resize(nDescCell2);
10415 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10417 std::vector<int> candidates1(1);
10418 int offset1(m1Desc->getNumberOfNodes());
10419 int offset2(offset1+m2Desc->getNumberOfNodes());
10420 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10422 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10423 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10424 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10426 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10427 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10428 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10430 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10431 // 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
10432 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10433 std::set<INTERP_KERNEL::Node *> nodes;
10434 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10435 std::size_t szz(nodes.size());
10436 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10437 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10438 for(std::size_t iii=0;iii<szz;iii++,itt++)
10439 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10440 // end of protection
10441 // Performs egde cutting:
10442 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10447 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10448 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10453 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10454 * It builds the descending connectivity of the two meshes, and then using a binary tree
10455 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10456 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10458 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10459 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10460 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10461 std::vector<double>& addCoo,
10462 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10464 // Build desc connectivity
10465 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10466 desc2=DataArrayInt::New();
10467 descIndx2=DataArrayInt::New();
10468 revDesc2=DataArrayInt::New();
10469 revDescIndx2=DataArrayInt::New();
10470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10472 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10473 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10474 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10475 std::map<int,int> notUsedMap;
10476 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10477 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10478 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10482 * This method performs the 2nd step of Partition of 2D mesh.
10483 * This method has 4 inputs :
10484 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10485 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10486 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10487 * 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'
10488 * Nodes end up lying consecutively on a cutted edge.
10489 * \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.
10490 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10491 * \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.
10492 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10493 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10495 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10496 const std::vector<double>& addCoo,
10497 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10499 int offset1=m1->getNumberOfNodes();
10500 int ncell=m2->getNumberOfCells();
10501 const int *c=m2->getNodalConnectivity()->getConstPointer();
10502 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10503 const double *coo=m2->getCoords()->getConstPointer();
10504 const double *cooBis=m1->getCoords()->getConstPointer();
10505 int offset2=offset1+m2->getNumberOfNodes();
10506 intersectEdge.resize(ncell);
10507 for(int i=0;i<ncell;i++,cI++)
10509 const std::vector<int>& divs=subDiv[i];
10510 int nnode=cI[1]-cI[0]-1;
10511 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10512 std::map<INTERP_KERNEL::Node *, int> mapp22;
10513 for(int j=0;j<nnode;j++)
10515 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10516 int nnid=c[(*cI)+j+1];
10517 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10518 mapp22[nn]=nnid+offset1;
10520 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10521 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10522 ((*it).second.first)->decrRef();
10523 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10524 std::map<INTERP_KERNEL::Node *,int> mapp3;
10525 for(std::size_t j=0;j<divs.size();j++)
10528 INTERP_KERNEL::Node *tmp=0;
10530 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10531 else if(id<offset2)
10532 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10534 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10538 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10539 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10546 * 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).
10547 * 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
10548 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10549 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10550 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10551 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10552 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10553 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10554 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10555 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10556 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10557 * \param [out] cut3DSuf input/output param.
10559 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10560 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10561 const int *desc, const int *descIndx,
10562 std::vector< std::pair<int,int> >& cut3DSurf)
10564 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10565 int nbOf3DSurfCell=(int)cut3DSurf.size();
10566 for(int i=0;i<nbOf3DSurfCell;i++)
10568 std::vector<int> res;
10569 int offset=descIndx[i];
10570 int nbOfSeg=descIndx[i+1]-offset;
10571 for(int j=0;j<nbOfSeg;j++)
10573 int edgeId=desc[offset+j];
10574 int status=cut3DCurve[edgeId];
10578 res.push_back(status);
10581 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10582 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10590 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10596 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10597 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10600 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10604 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10609 {// case when plane is on a multi colinear edge of a polyhedron
10610 if((int)res.size()==2*nbOfSeg)
10612 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10622 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10623 * 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).
10624 * 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
10625 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10626 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10627 * \param desc is the descending connectivity 3D->3DSurf
10628 * \param descIndx is the descending connectivity index 3D->3DSurf
10630 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10631 const int *desc, const int *descIndx,
10632 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10634 checkFullyDefined();
10635 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10636 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10637 const int *nodal3D=_nodal_connec->getConstPointer();
10638 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10639 int nbOfCells=getNumberOfCells();
10640 for(int i=0;i<nbOfCells;i++)
10642 std::map<int, std::set<int> > m;
10643 int offset=descIndx[i];
10644 int nbOfFaces=descIndx[i+1]-offset;
10647 for(int j=0;j<nbOfFaces;j++)
10649 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10650 if(p.first!=-1 && p.second!=-1)
10654 start=p.first; end=p.second;
10655 m[p.first].insert(p.second);
10656 m[p.second].insert(p.first);
10660 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10661 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10662 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10663 INTERP_KERNEL::NormalizedCellType cmsId;
10664 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10665 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10666 for(unsigned k=0;k<nbOfNodesSon;k++)
10668 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10669 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10676 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10680 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10681 const std::set<int>& s=(*it).second;
10682 std::set<int> s2; s2.insert(prev);
10684 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10687 int val=*s3.begin();
10688 conn.push_back(start);
10695 conn.push_back(end);
10698 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10699 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10700 cellIds->pushBackSilent(i);
10706 * 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
10707 * 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
10708 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10709 * 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
10710 * 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.
10712 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10714 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10716 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10719 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10720 if(cm.getDimension()==2)
10722 const int *node=nodalConnBg+1;
10723 int startNode=*node++;
10724 double refX=coords[2*startNode];
10725 for(;node!=nodalConnEnd;node++)
10727 if(coords[2*(*node)]<refX)
10730 refX=coords[2*startNode];
10733 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10737 double angle0=-M_PI/2;
10742 double angleNext=0.;
10743 while(nextNode!=startNode)
10747 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10749 if(*node!=tmpOut.back() && *node!=prevNode)
10751 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10752 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10757 res=angle0-angleM+2.*M_PI;
10766 if(nextNode!=startNode)
10768 angle0=angleNext-M_PI;
10771 prevNode=tmpOut.back();
10772 tmpOut.push_back(nextNode);
10775 std::vector<int> tmp3(2*(sz-1));
10776 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10777 std::copy(nodalConnBg+1,nodalConnEnd,it);
10778 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10780 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10783 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10785 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10790 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10791 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10796 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10799 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10803 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10804 * 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.
10806 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10807 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10808 * \param [in,out] arr array in which the remove operation will be done.
10809 * \param [in,out] arrIndx array in the remove operation will modify
10810 * \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])
10811 * \return true if \b arr and \b arrIndx have been modified, false if not.
10813 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10815 if(!arrIndx || !arr)
10816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10817 if(offsetForRemoval<0)
10818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10819 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10820 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10821 int *arrIPtr=arrIndx->getPointer();
10823 int previousArrI=0;
10824 const int *arrPtr=arr->getConstPointer();
10825 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10826 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10828 if(*arrIPtr-previousArrI>offsetForRemoval)
10830 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10832 if(s.find(*work)==s.end())
10833 arrOut.push_back(*work);
10836 previousArrI=*arrIPtr;
10837 *arrIPtr=(int)arrOut.size();
10839 if(arr->getNumberOfTuples()==(int)arrOut.size())
10841 arr->alloc((int)arrOut.size(),1);
10842 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10847 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10848 * (\ref numbering-indirect).
10849 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10850 * The selection of extraction is done standardly in new2old format.
10851 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10853 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10854 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10855 * \param [in] arrIn arr origin array from which the extraction will be done.
10856 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10857 * \param [out] arrOut the resulting array
10858 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10859 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10861 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10862 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10864 if(!arrIn || !arrIndxIn)
10865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10866 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10867 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10869 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10870 const int *arrInPtr=arrIn->getConstPointer();
10871 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10872 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10875 int maxSizeOfArr=arrIn->getNumberOfTuples();
10876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10878 arrIo->alloc((int)(sz+1),1);
10879 const int *idsIt=idsOfSelectBg;
10880 int *work=arrIo->getPointer();
10883 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10885 if(*idsIt>=0 && *idsIt<nbOfGrps)
10886 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10889 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10890 throw INTERP_KERNEL::Exception(oss.str().c_str());
10896 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10897 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10898 throw INTERP_KERNEL::Exception(oss.str().c_str());
10901 arro->alloc(lgth,1);
10902 work=arro->getPointer();
10903 idsIt=idsOfSelectBg;
10904 for(std::size_t i=0;i<sz;i++,idsIt++)
10906 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10907 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10910 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10911 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10912 throw INTERP_KERNEL::Exception(oss.str().c_str());
10915 arrOut=arro.retn();
10916 arrIndexOut=arrIo.retn();
10920 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10921 * (\ref numbering-indirect).
10922 * 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 ).
10923 * The selection of extraction is done standardly in new2old format.
10924 * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10926 * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10927 * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10928 * \param [in] idsOfSelectStep
10929 * \param [in] arrIn arr origin array from which the extraction will be done.
10930 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10931 * \param [out] arrOut the resulting array
10932 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10933 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10935 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10936 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10938 if(!arrIn || !arrIndxIn)
10939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10940 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10941 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10942 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10943 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10944 const int *arrInPtr=arrIn->getConstPointer();
10945 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10946 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10948 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10949 int maxSizeOfArr=arrIn->getNumberOfTuples();
10950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10952 arrIo->alloc((int)(sz+1),1);
10953 int idsIt=idsOfSelectStart;
10954 int *work=arrIo->getPointer();
10957 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10959 if(idsIt>=0 && idsIt<nbOfGrps)
10960 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10963 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10964 throw INTERP_KERNEL::Exception(oss.str().c_str());
10970 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10971 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10972 throw INTERP_KERNEL::Exception(oss.str().c_str());
10975 arro->alloc(lgth,1);
10976 work=arro->getPointer();
10977 idsIt=idsOfSelectStart;
10978 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10980 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10981 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10984 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10985 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10986 throw INTERP_KERNEL::Exception(oss.str().c_str());
10989 arrOut=arro.retn();
10990 arrIndexOut=arrIo.retn();
10994 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10995 * 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
10996 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10997 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10999 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11000 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11001 * \param [in] arrIn arr origin array from which the extraction will be done.
11002 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11003 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11004 * \param [in] srcArrIndex index array of \b srcArr
11005 * \param [out] arrOut the resulting array
11006 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11008 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11010 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11011 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11012 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11014 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11018 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11019 std::vector<bool> v(nbOfTuples,true);
11021 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11022 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11023 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11025 if(*it>=0 && *it<nbOfTuples)
11028 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11032 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11033 throw INTERP_KERNEL::Exception(oss.str().c_str());
11036 srcArrIndexPtr=srcArrIndex->getConstPointer();
11037 arrIo->alloc(nbOfTuples+1,1);
11038 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11039 const int *arrInPtr=arrIn->getConstPointer();
11040 const int *srcArrPtr=srcArr->getConstPointer();
11041 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11042 int *arroPtr=arro->getPointer();
11043 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11047 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11048 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11052 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11053 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11054 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11057 arrOut=arro.retn();
11058 arrIndexOut=arrIo.retn();
11062 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11063 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11065 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11066 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11067 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11068 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11069 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11070 * \param [in] srcArrIndex index array of \b srcArr
11072 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11074 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11075 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11077 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11078 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11079 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11080 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11081 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11082 int *arrInOutPtr=arrInOut->getPointer();
11083 const int *srcArrPtr=srcArr->getConstPointer();
11084 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11086 if(*it>=0 && *it<nbOfTuples)
11088 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11089 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11092 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] !";
11093 throw INTERP_KERNEL::Exception(oss.str().c_str());
11098 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11099 throw INTERP_KERNEL::Exception(oss.str().c_str());
11105 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11106 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11107 * 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]].
11108 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11109 * A negative value in \b arrIn means that it is ignored.
11110 * 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.
11112 * \param [in] arrIn arr origin array from which the extraction will be done.
11113 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11114 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11115 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11117 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11119 int seed=0,nbOfDepthPeelingPerformed=0;
11120 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11124 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11125 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11126 * 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]].
11127 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11128 * A negative value in \b arrIn means that it is ignored.
11129 * 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.
11130 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11131 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11132 * \param [in] arrIn arr origin array from which the extraction will be done.
11133 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11134 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11135 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11136 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11137 * \sa MEDCouplingUMesh::partitionBySpreadZone
11139 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11141 nbOfDepthPeelingPerformed=0;
11143 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11144 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11147 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11151 std::vector<bool> fetched(nbOfTuples,false);
11152 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11155 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11157 nbOfDepthPeelingPerformed=0;
11158 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11159 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11160 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11161 std::vector<bool> fetched2(nbOfTuples,false);
11163 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11165 if(*seedElt>=0 && *seedElt<nbOfTuples)
11166 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11168 { 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()); }
11170 const int *arrInPtr=arrIn->getConstPointer();
11171 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11172 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11173 std::vector<int> idsToFetch1(seedBg,seedEnd);
11174 std::vector<int> idsToFetch2;
11175 std::vector<int> *idsToFetch=&idsToFetch1;
11176 std::vector<int> *idsToFetchOther=&idsToFetch2;
11177 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11179 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11180 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11182 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11183 std::swap(idsToFetch,idsToFetchOther);
11184 idsToFetchOther->clear();
11185 nbOfDepthPeelingPerformed++;
11187 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11190 int *retPtr=ret->getPointer();
11191 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11198 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11199 * 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
11200 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11201 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11203 * \param [in] start begin of set of ids of the input extraction (included)
11204 * \param [in] end end of set of ids of the input extraction (excluded)
11205 * \param [in] step step of the set of ids in range mode.
11206 * \param [in] arrIn arr origin array from which the extraction will be done.
11207 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11208 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11209 * \param [in] srcArrIndex index array of \b srcArr
11210 * \param [out] arrOut the resulting array
11211 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11213 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11215 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11216 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11217 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11219 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11220 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11223 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11225 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11226 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11227 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11229 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11231 if(it>=0 && it<nbOfTuples)
11232 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11235 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11236 throw INTERP_KERNEL::Exception(oss.str().c_str());
11239 srcArrIndexPtr=srcArrIndex->getConstPointer();
11240 arrIo->alloc(nbOfTuples+1,1);
11241 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11242 const int *arrInPtr=arrIn->getConstPointer();
11243 const int *srcArrPtr=srcArr->getConstPointer();
11244 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11245 int *arroPtr=arro->getPointer();
11246 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11248 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11251 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11252 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11256 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11257 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11260 arrOut=arro.retn();
11261 arrIndexOut=arrIo.retn();
11265 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11266 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11268 * \param [in] start begin of set of ids of the input extraction (included)
11269 * \param [in] end end of set of ids of the input extraction (excluded)
11270 * \param [in] step step of the set of ids in range mode.
11271 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11272 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11273 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11274 * \param [in] srcArrIndex index array of \b srcArr
11276 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11278 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11279 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11281 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11283 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11284 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11285 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11286 int *arrInOutPtr=arrInOut->getPointer();
11287 const int *srcArrPtr=srcArr->getConstPointer();
11288 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11290 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11292 if(it>=0 && it<nbOfTuples)
11294 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11295 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11298 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11299 throw INTERP_KERNEL::Exception(oss.str().c_str());
11304 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11305 throw INTERP_KERNEL::Exception(oss.str().c_str());
11311 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11312 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11313 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11314 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11315 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11317 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11319 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11321 checkFullyDefined();
11322 int mdim=getMeshDimension();
11323 int spaceDim=getSpaceDimension();
11325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11326 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11327 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11328 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11330 ret->setCoords(getCoords());
11331 ret->allocateCells((int)partition.size());
11333 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11335 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11340 cell=tmp->buildUnionOf2DMesh();
11343 cell=tmp->buildUnionOf3DMesh();
11346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11349 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11352 ret->finishInsertingCells();
11357 * This method partitions \b this into contiguous zone.
11358 * This method only needs a well defined connectivity. Coordinates are not considered here.
11359 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11361 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11363 int nbOfCellsCur=getNumberOfCells();
11364 std::vector<DataArrayInt *> ret;
11365 if(nbOfCellsCur<=0)
11367 DataArrayInt *neigh=0,*neighI=0;
11368 computeNeighborsOfCells(neigh,neighI);
11369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11370 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11371 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11373 while(seed<nbOfCellsCur)
11375 int nbOfPeelPerformed=0;
11376 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11377 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11379 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11380 ret.push_back((*it).retn());
11385 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11386 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11388 * \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.
11389 * \return a newly allocated DataArrayInt to be managed by the caller.
11390 * \throw In case of \a code has not the right format (typically of size 3*n)
11392 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11395 std::size_t nb=code.size()/3;
11396 if(code.size()%3!=0)
11397 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11398 ret->alloc((int)nb,2);
11399 int *retPtr=ret->getPointer();
11400 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11402 retPtr[0]=code[3*i+2];
11403 retPtr[1]=code[3*i+2]+code[3*i+1];
11409 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11410 * All cells in \a this are expected to be linear 3D cells.
11411 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11412 * It leads to an increase to number of cells.
11413 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11414 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11415 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11417 * \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.
11418 * For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11419 * \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.
11420 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11421 * an id of old cell producing it. The caller is to delete this array using
11422 * decrRef() as it is no more needed.
11423 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11425 * \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
11426 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11428 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11429 * \throw If \a this is not fully constituted with linear 3D cells.
11430 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11432 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11434 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11435 checkConnectivityFullyDefined();
11436 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11437 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11438 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11439 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11440 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11441 int *retPt(ret->getPointer());
11442 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11443 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11444 const int *oldc(_nodal_connec->begin());
11445 const int *oldci(_nodal_connec_index->begin());
11446 const double *coords(_coords->begin());
11447 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11449 std::vector<int> a; std::vector<double> b;
11450 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11451 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11452 const int *aa(&a[0]);
11455 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11457 *it=(-(*(it))-1+nbNodes);
11458 addPts->insertAtTheEnd(b.begin(),b.end());
11459 nbNodes+=(int)b.size()/3;
11461 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11462 newConn->insertAtTheEnd(aa,aa+4);
11464 if(!addPts->empty())
11466 addPts->rearrange(3);
11467 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11468 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11469 ret0->setCoords(addPts);
11473 nbOfAdditionalPoints=0;
11474 ret0->setCoords(getCoords());
11476 ret0->setNodalConnectivity(newConn);
11478 ret->computeOffsets2();
11479 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11480 return ret0.retn();
11484 * 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).
11486 * \sa MEDCouplingUMesh::split2DCells
11488 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11490 checkConnectivityFullyDefined();
11491 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11492 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11493 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11494 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11495 int prevPosOfCi(ciPtr[0]);
11496 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11498 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11499 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11500 for(int j=0;j<sz;j++)
11502 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11503 for(int k=0;k<sz2;k++)
11504 *cPtr++=subPtr[offset2+k];
11506 *cPtr++=oldConn[prevPosOfCi+j+2];
11509 prevPosOfCi=ciPtr[1];
11510 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11513 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11514 _nodal_connec->decrRef();
11515 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11518 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11524 int ret(nodesCnter++);
11526 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11527 addCoo.insertAtTheEnd(newPt,newPt+2);
11532 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11538 int ret(nodesCnter++);
11540 e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11541 addCoo.insertAtTheEnd(newPt,newPt+2);
11549 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)
11552 int trueStart(start>=0?start:nbOfEdges+start);
11553 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11554 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11559 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11560 InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11561 middles.push_back(tmp3+offset);
11564 middles.push_back(connBg[trueStart+nbOfEdges]);
11568 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)
11570 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11571 newConnOfCell->pushBackSilent(tmpEnd);
11576 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11577 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11578 middles.push_back(tmp3+offset);
11581 middles.push_back(connBg[start+nbOfEdges]);
11585 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)
11587 // only the quadratic point to deal with:
11592 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11593 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11594 InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11595 middles.push_back(tmp3+offset);
11598 middles.push_back(connBg[start+nbOfEdges]);
11605 * 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 ) .
11606 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11608 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11610 std::size_t sz(std::distance(connBg,connEnd));
11611 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11614 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11615 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11616 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11617 unsigned nbOfHit(0); // number of fusions operated
11618 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11619 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
11620 INTERP_KERNEL::NormalizedCellType typeOfSon;
11621 std::vector<int> middles;
11623 for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11625 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11626 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11627 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11628 posEndElt = posBaseElt+1;
11630 // Look backward first: are the final edges of the cells colinear with the first ones?
11631 // This initializes posBaseElt.
11634 for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11636 cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11637 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11638 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11639 bool isColinear=eint->areColinears();
11652 // Now move forward:
11653 const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt); // the first element to be inspected going forward
11654 for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++) // 2nd condition is to avoid ending with a cell wih one single edge
11656 cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11657 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11658 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11659 bool isColinear(eint->areColinears());
11671 //push [posBaseElt,posEndElt) in newConnOfCell using e
11672 // 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!
11674 // at the begining of the connectivity (insert type)
11675 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11676 else if((nbOfHit+nbOfTurn) != (nbs-1))
11678 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11679 if ((nbOfHit+nbOfTurn) == (nbs-1))
11680 // at the end (only quad points to deal with)
11681 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11682 posBaseElt=posEndElt;
11685 if(!middles.empty())
11686 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11691 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11693 * \return int - the number of new nodes created.
11694 * \sa MEDCouplingUMesh::split2DCells
11696 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11699 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11701 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11702 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11703 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11704 const double *oldCoordsPtr(getCoords()->begin());
11705 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11706 int prevPosOfCi(ciPtr[0]);
11707 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11709 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11710 for(int j=0;j<sz;j++)
11711 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11712 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11713 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11715 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11719 cPtr[1]=oldConn[prevPosOfCi+2+j];
11720 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11723 std::vector<INTERP_KERNEL::Node *> ns(3);
11724 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11725 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11726 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11727 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11728 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11730 cPtr[1]=subPtr[offset2+k];
11731 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11733 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11735 { cPtr[1]=tmpEnd; }
11736 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11738 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11739 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11742 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11743 _nodal_connec->decrRef();
11744 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11745 addCoo->rearrange(2);
11746 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11748 return addCoo->getNumberOfTuples();
11751 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11753 if(nodalConnec && nodalConnecIndex)
11756 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11757 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11759 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11760 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11764 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11765 _own_cell(true),_cell_id(-1),_nb_cell(0)
11770 _nb_cell=mesh->getNumberOfCells();
11774 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11782 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11783 _own_cell(false),_cell_id(bg-1),
11790 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11793 if(_cell_id<_nb_cell)
11802 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11808 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11810 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11813 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11819 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11827 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11833 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11838 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11843 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11845 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11848 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11853 _nb_cell=mesh->getNumberOfCells();
11857 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11864 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11866 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11867 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11868 if(_cell_id<_nb_cell)
11870 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11871 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11872 int startId=_cell_id;
11873 _cell_id+=nbOfElems;
11874 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11880 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11884 _conn=mesh->getNodalConnectivity()->getPointer();
11885 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11889 void MEDCouplingUMeshCell::next()
11891 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11896 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11899 std::string MEDCouplingUMeshCell::repr() const
11901 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11903 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11905 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11909 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11912 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11914 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11915 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11917 return INTERP_KERNEL::NORM_ERROR;
11920 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11923 if(_conn_lgth!=NOTICABLE_FIRST_VAL)