1 // Copyright (C) 2007-2012 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.
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
20 #include "MEDCouplingUMesh.hxx"
21 #include "MEDCouplingMemArray.txx"
22 #include "MEDCouplingFieldDouble.hxx"
23 #include "CellModel.hxx"
24 #include "VolSurfUser.txx"
25 #include "InterpolationUtils.hxx"
26 #include "PointLocatorAlgos.txx"
28 #include "DirectedBoundingBox.hxx"
29 #include "InterpKernelMeshQuality.hxx"
30 #include "InterpKernelCellSimplify.hxx"
31 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
32 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
33 #include "InterpKernelAutoPtr.hxx"
34 #include "InterpKernelGeo2DNode.hxx"
35 #include "InterpKernelGeo2DEdgeLin.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
46 using namespace ParaMEDMEM;
48 const char MEDCouplingUMesh::PART_OF_NAME[]="PartOf_";
50 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52 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 };
54 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 return new MEDCouplingUMesh;
59 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
62 ret->setName(meshName);
63 ret->setMeshDimension(meshDim);
67 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
72 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
74 return new MEDCouplingUMesh(*this,recDeepCpy);
77 void MEDCouplingUMesh::updateTime() const
79 MEDCouplingPointSet::updateTime();
82 updateTimeWith(*_nodal_connec);
84 if(_nodal_connec_index)
86 updateTimeWith(*_nodal_connec_index);
90 MEDCouplingUMesh::MEDCouplingUMesh():_iterator(-1),_mesh_dim(-2),
91 _nodal_connec(0),_nodal_connec_index(0)
96 * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity.
97 * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be
98 * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check
99 * that all is in order in 'this'.
101 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
104 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
105 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
107 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
109 std::ostringstream message;
110 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
111 throw INTERP_KERNEL::Exception(message.str().c_str());
116 if(_nodal_connec->getNumberOfComponents()!=1)
117 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
118 if(_nodal_connec->getInfoOnComponent(0)!="")
119 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
121 if(_nodal_connec_index)
123 if(_nodal_connec_index->getNumberOfComponents()!=1)
124 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
125 if(_nodal_connec_index->getInfoOnComponent(0)!="")
126 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
130 throw INTERP_KERNEL::Exception("It appears that finishInsertingCells method has not been invoked after a insertNextCell session !");
135 * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does.
136 * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids.
137 * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2.
139 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
144 int meshDim=getMeshDimension();
145 int nbOfNodes=getNumberOfNodes();
146 int nbOfCells=getNumberOfCells();
147 const int *ptr=_nodal_connec->getConstPointer();
148 const int *ptrI=_nodal_connec_index->getConstPointer();
149 for(int i=0;i<nbOfCells;i++)
151 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
152 if((int)cm.getDimension()!=meshDim)
154 std::ostringstream oss;
155 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
156 throw INTERP_KERNEL::Exception(oss.str().c_str());
158 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
160 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
162 std::ostringstream oss;
163 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
164 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
165 throw INTERP_KERNEL::Exception(oss.str().c_str());
167 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
172 if(nodeId>=nbOfNodes)
174 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
175 throw INTERP_KERNEL::Exception(oss.str().c_str());
180 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
181 throw INTERP_KERNEL::Exception(oss.str().c_str());
185 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
187 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
188 throw INTERP_KERNEL::Exception(oss.str().c_str());
195 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
197 checkCoherency1(eps);
200 void MEDCouplingUMesh::setMeshDimension(int meshDim)
203 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 !");
208 void MEDCouplingUMesh::allocateCells(int nbOfCells)
210 if(_nodal_connec_index)
212 _nodal_connec_index->decrRef();
216 _nodal_connec->decrRef();
219 _nodal_connec_index=DataArrayInt::New();
220 _nodal_connec_index->alloc(nbOfCells+1,1);
221 int *pt=_nodal_connec_index->getPointer();
223 _nodal_connec=DataArrayInt::New();
224 _nodal_connec->alloc(2*nbOfCells,1);
231 * Appends a cell in connectivity array.
232 * @param type type of cell to add.
233 * @param size number of nodes constituting this cell.
234 * @param nodalConnOfCell the connectivity of the cell to add.
236 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
238 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
239 if(_nodal_connec_index==0)
240 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
241 if((int)cm.getDimension()==_mesh_dim)
243 int nbOfElems=_nodal_connec_index->getNbOfElems()-1;
244 if(_iterator>=nbOfElems)
245 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : allocation of cells was wide enough ! Call insertNextCell with higher value or call finishInsertingCells !");
246 int *pt=_nodal_connec_index->getPointer();
247 int idx=pt[_iterator];
249 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
251 pt[++_iterator]=idx+size+1;
255 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
256 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
257 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
258 throw INTERP_KERNEL::Exception(oss.str().c_str());
263 * Method to be called to cloture the insertion of cells using this->insertNextCell.
265 void MEDCouplingUMesh::finishInsertingCells()
267 const int *pt=_nodal_connec_index->getConstPointer();
268 int idx=pt[_iterator];
270 _nodal_connec->reAlloc(idx);
271 _nodal_connec_index->reAlloc(_iterator+1);
273 _nodal_connec->declareAsNew();
274 _nodal_connec_index->declareAsNew();
279 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
280 * Useful for python users.
282 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
284 return new MEDCouplingUMeshCellIterator(this);
288 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
289 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
290 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
291 * Useful for python users.
293 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
295 if(!checkConsecutiveCellTypes())
296 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
297 return new MEDCouplingUMeshCellByTypeEntry(this);
300 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
306 * This method is a method that compares 'this' and 'other'.
307 * This method compares \b all attributes, even names and component names.
309 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
313 std::ostringstream oss; oss.precision(15);
314 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
317 reason="mesh given in input is not castable in MEDCouplingUMesh !";
320 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
322 if(_mesh_dim!=otherC->_mesh_dim)
324 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
328 if(_types!=otherC->_types)
330 oss << "umesh geometric type mismatch :\nThis geometric types are :";
331 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
332 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
333 oss << "\nOther geometric types are :";
334 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
335 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
339 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
340 if(_nodal_connec==0 || otherC->_nodal_connec==0)
342 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
345 if(_nodal_connec!=otherC->_nodal_connec)
346 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
348 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
351 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
352 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
354 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
357 if(_nodal_connec_index!=otherC->_nodal_connec_index)
358 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
360 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
366 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
368 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
371 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
373 if(_mesh_dim!=otherC->_mesh_dim)
375 if(_types!=otherC->_types)
377 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
378 if(_nodal_connec==0 || otherC->_nodal_connec==0)
380 if(_nodal_connec!=otherC->_nodal_connec)
381 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
383 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
384 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
386 if(_nodal_connec_index!=otherC->_nodal_connec_index)
387 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
393 * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
394 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
396 * In case of success cellCor and nodeCor are informed both.
397 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
398 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
399 * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
401 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
402 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
404 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
406 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
407 MEDCouplingMesh::checkFastEquivalWith(other,prec);
408 if(_types!=otherC->_types)
409 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
410 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
413 int oldNbOfNodes=getNumberOfNodes();
414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
417 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
418 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
419 if(pt!=da->getConstPointer()+da->getNbOfElems())
420 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
421 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
424 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
427 da=m->zipConnectivityTraducer(cellCompPol);
428 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
429 pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
430 if(pt!=da->getConstPointer()+da->getNbOfElems())
431 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=DataArrayInt::New();
433 cellCor2->alloc(otherC->getNumberOfCells(),1);
434 std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor2->getPointer());
435 bool nident=nodeCor2->isIdentity();
436 bool cident=cellCor2->isIdentity();
437 if(!nident) { nodeCor=nodeCor2; nodeCor2->incrRef(); } else nodeCor=0;
438 if(!cident) { cellCor=cellCor2; cellCor2->incrRef(); } else cellCor=0;
442 * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
443 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
444 * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
445 * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception !
447 * In case of success cellCor are informed both.
448 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
449 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
451 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
452 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
454 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
456 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
457 MEDCouplingMesh::checkFastEquivalWith(other,prec);
458 if(_types!=otherC->_types)
459 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
460 if(_coords!=otherC->_coords)
461 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
462 std::vector<const MEDCouplingUMesh *> ms(2);
465 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
467 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
468 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
469 if(pt!=da->getConstPointer()+da->getNbOfElems())
471 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=DataArrayInt::New();
474 cellCor2->alloc(otherC->getNumberOfCells(),1);
475 std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor2->getPointer());
476 if(!cellCor2->isIdentity()) { cellCor=cellCor2; cellCor2->incrRef(); } else cellCor=0;
480 * This method checks fastly that 'this' and 'other' are equal.
482 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
484 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
486 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
487 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
488 int nbOfCells=getNumberOfCells();
492 status&=areCellsFrom2MeshEqual(otherC,0,prec);
493 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
494 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
496 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
500 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
501 * For speed reasons no check of this will be done.
503 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
506 int nbOfNodes=getNumberOfNodes();
507 int *revNodalIndxPtr=new int[nbOfNodes+1];
508 revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
509 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
510 const int *conn=_nodal_connec->getConstPointer();
511 const int *connIndex=_nodal_connec_index->getConstPointer();
512 int nbOfCells=getNumberOfCells();
513 int nbOfEltsInRevNodal=0;
514 for(int eltId=0;eltId<nbOfCells;eltId++)
516 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
517 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
518 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
519 if(*iter>=0)//for polyhedrons
521 nbOfEltsInRevNodal++;
522 revNodalIndxPtr[(*iter)+1]++;
525 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
526 int *revNodalPtr=new int[nbOfEltsInRevNodal];
527 revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
528 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
529 for(int eltId=0;eltId<nbOfCells;eltId++)
531 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
532 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
533 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
534 if(*iter>=0)//for polyhedrons
535 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
541 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
546 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
552 if(cm.getOrientationStatus(nb,conn1,conn2))
562 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
563 * For speed reasons no check of this will be done.
564 * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
565 * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
566 * The algorithm to compute this p-1 mesh is the following :
567 * For each cell in 'this' it splits into p-1 elements.
568 * If this p-1 element does not already exists it is appended to the returned mesh
569 * If this p-1 element already exists, it is not appended.
570 * This method returns or 4 arrays plus the returned mesh.
571 * 'desc' and 'descIndx' are the descending connectivity. These 2 arrays tell for each cell in 'this', to wich p-1 dimension cell in returned mesh it refers.
572 * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
574 * Reversely 'revDesc' and 'revDescIndx' are the reverse descending connectivity. These 2 arrays tell for each cell in returned mesh, to wich cell in 'this' it refers.
575 * For a cell with a cellid d in returned p-1 mesh it is shared by the following cells in 'this' [revDesc+revDescIndx[d],revDesc+revDescIndx[d+1])
577 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
578 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
580 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
582 return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
586 * WARNING this method do the assumption that connectivity lies on the coordinates set.
587 * For speed reasons no check of this will be done.
588 * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
589 * This method is more precise because it returns in descending connectivity giving the direction. If value is positive the n-1 dim element is taken in the same direction,
590 * if it is in the opposite direction it is retrieved negative. So the problem is for elemt #0 in C convention. That's why this method is the only one that retrieves
591 * an array in relative "FORTRAN" mode.
593 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
594 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
596 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
598 return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
602 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
603 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
604 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
605 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
607 * \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
608 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
609 * \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.
611 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
613 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
617 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
619 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
623 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
624 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
625 * excluding a set of meshdim-1 cells in input descending connectivity.
626 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
627 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
628 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
630 * \param [in] desc descending connectivity array.
631 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
632 * \param [in] revDesc reverse descending connectivity array.
633 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
634 * \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
635 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
636 * \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.
638 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
639 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
641 if(!desc || !descIndx || !revDesc || !revDescIndx)
642 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
643 const int *descPtr=desc->getConstPointer();
644 const int *descIPtr=descIndx->getConstPointer();
645 const int *revDescPtr=revDesc->getConstPointer();
646 const int *revDescIPtr=revDescIndx->getConstPointer();
648 int nbCells=descIndx->getNumberOfTuples()-1;
649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
651 int *out1Ptr=out1->getPointer();
653 std::vector<int> out0v;
654 out0v.reserve(desc->getNumberOfTuples());
655 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
657 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
659 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
661 out0v.insert(out0v.end(),s.begin(),s.end());
663 *out1Ptr=out0v.size();
665 out0->alloc((int)out0v.size(),1);
666 std::copy(out0v.begin(),out0v.end(),out0->getPointer());
667 neighbors=out0; out0->incrRef();
668 neighborsIndx=out1; out1->incrRef();
674 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
675 * For speed reasons no check of this will be done.
677 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
679 checkConnectivityFullyDefined();
680 int nbOfCells=getNumberOfCells();
681 int nbOfNodes=getNumberOfNodes();
682 const int *conn=_nodal_connec->getConstPointer();
683 const int *connIndex=_nodal_connec_index->getConstPointer();
684 std::vector< std::vector<int> > descMeshConnB(nbOfCells);
685 std::vector< std::vector<int> > revDescMeshConnB;
686 std::vector< std::vector<int> > revNodalB(nbOfNodes);
687 std::vector<int> meshDM1Conn;
688 std::vector<int> meshDM1ConnIndex(1); meshDM1ConnIndex[0]=0;
689 std::vector<int> meshDM1Type;
690 for(int eltId=0;eltId<nbOfCells;eltId++)
692 int pos=connIndex[eltId];
693 int posP1=connIndex[eltId+1];
694 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
695 unsigned nbOfSons=cm.getNumberOfSons2(conn+pos+1,posP1-pos-1);
696 int *tmp=new int[posP1-pos];
697 for(unsigned i=0;i<nbOfSons;i++)
699 INTERP_KERNEL::NormalizedCellType cmsId;
700 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
701 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel(cmsId);
702 std::set<int> shareableCells(revNodalB[tmp[0]].begin(),revNodalB[tmp[0]].end());
703 for(unsigned j=1;j<nbOfNodesSon && !shareableCells.empty();j++)
705 std::set<int> tmp2(revNodalB[tmp[j]].begin(),revNodalB[tmp[j]].end());
707 std::set_intersection(tmp2.begin(),tmp2.end(),shareableCells.begin(),shareableCells.end(),inserter(tmp3,tmp3.begin()));
710 std::list<int> shareableCellsL(shareableCells.begin(),shareableCells.end());
711 std::set<int> ref(tmp,tmp+nbOfNodesSon);
712 for(std::list<int>::iterator iter=shareableCellsL.begin();iter!=shareableCellsL.end();)
714 if(cms.isCompatibleWith((INTERP_KERNEL::NormalizedCellType)meshDM1Type[*iter]))
716 std::set<int> ref2(meshDM1Conn.begin()+meshDM1ConnIndex[*iter],meshDM1Conn.begin()+meshDM1ConnIndex[(*iter)+1]);
720 iter=shareableCellsL.erase(iter);
723 iter=shareableCellsL.erase(iter);
725 if(shareableCellsL.empty())
727 meshDM1Conn.insert(meshDM1Conn.end(),tmp,tmp+nbOfNodesSon);
728 meshDM1ConnIndex.push_back(meshDM1ConnIndex.back()+nbOfNodesSon);
729 int cellDM1Id=(int)meshDM1Type.size();
730 meshDM1Type.push_back((int)cmsId);
731 for(unsigned k=0;k<nbOfNodesSon;k++)
732 revNodalB[tmp[k]].push_back(cellDM1Id);
733 revDescMeshConnB.resize(cellDM1Id+1);
734 revDescMeshConnB.back().push_back(eltId);
735 descMeshConnB[eltId].push_back(nbrer(cellDM1Id,0,cms,false,0,0));
739 int DM1cellId=shareableCellsL.front();
740 revDescMeshConnB[DM1cellId].push_back(eltId);
741 descMeshConnB[eltId].push_back(nbrer(DM1cellId,nbOfNodesSon,cms,true,tmp,&meshDM1Conn[meshDM1ConnIndex[DM1cellId]]));
748 std::string name="Mesh constituent of "; name+=getName();
749 MEDCouplingUMesh *ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-1);
750 ret->setCoords(getCoords());
751 int nbOfCellsInConstituent=(int)meshDM1Type.size();
752 ret->allocateCells(nbOfCellsInConstituent);
753 revDescIndx->alloc(nbOfCellsInConstituent+1,1);
754 int *tmp3=revDescIndx->getPointer(); tmp3[0]=0;
755 for(int ii=0;ii<nbOfCellsInConstituent;ii++)
757 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)meshDM1Type[ii],meshDM1ConnIndex[ii+1]-meshDM1ConnIndex[ii],&meshDM1Conn[meshDM1ConnIndex[ii]]);
758 tmp3[ii+1]=tmp3[ii]+((int)revDescMeshConnB[ii].size());
760 ret->finishInsertingCells();
761 revDesc->alloc(tmp3[nbOfCellsInConstituent],1);
762 tmp3=revDesc->getPointer();
763 for(std::vector< std::vector<int> >::const_iterator iter2=revDescMeshConnB.begin();iter2!=revDescMeshConnB.end();iter2++)
764 tmp3=std::copy((*iter2).begin(),(*iter2).end(),tmp3);
765 meshDM1Type.clear(); meshDM1ConnIndex.clear(); meshDM1Conn.clear();
766 descIndx->alloc(nbOfCells+1,1);
767 tmp3=descIndx->getPointer(); tmp3[0]=0;
768 for(int jj=0;jj<nbOfCells;jj++)
769 tmp3[jj+1]=tmp3[jj]+((int)descMeshConnB[jj].size());
770 desc->alloc(tmp3[nbOfCells],1);
771 tmp3=desc->getPointer();
772 for(std::vector< std::vector<int> >::const_iterator iter3=descMeshConnB.begin();iter3!=descMeshConnB.end();iter3++)
773 tmp3=std::copy((*iter3).begin(),(*iter3).end(),tmp3);
778 struct MEDCouplingAccVisit
780 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
781 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
782 int _new_nb_of_nodes;
789 * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
790 * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
791 * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
792 * If mesh dimension is not in [2,3] an exception is thrown.
793 * Of course pay attention that the resulting mesh is slower than previous one.
794 * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
795 * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
796 * If mesh==3, after throw the mesh is \b unconsistent !
797 * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
799 * \warning This method modifies can modify significantly the geometric type order in \a this.
800 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
802 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
805 int dim=getMeshDimension();
807 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
808 int nbOfCells=getNumberOfCells();
811 const int *connIndex=_nodal_connec_index->getConstPointer();
812 int *conn=_nodal_connec->getPointer();
813 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
815 if(*iter>=0 && *iter<nbOfCells)
817 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
819 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
821 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
825 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
826 oss << " in range [0," << nbOfCells << ") !";
827 throw INTERP_KERNEL::Exception(oss.str().c_str());
833 int *connIndex=_nodal_connec_index->getPointer();
834 int connIndexLgth=_nodal_connec_index->getNbOfElems();
835 const int *connOld=_nodal_connec->getConstPointer();
836 int connOldLgth=_nodal_connec->getNbOfElems();
837 std::vector<int> connNew(connOld,connOld+connOldLgth);
838 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
840 if(*iter>=0 && *iter<nbOfCells)
842 int pos=connIndex[*iter];
843 int posP1=connIndex[(*iter)+1];
844 int lgthOld=posP1-pos-1;
845 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
846 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
847 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
848 int *tmp=new int[nbOfFaces*lgthOld];
850 for(int j=0;j<(int)nbOfFaces;j++)
852 INTERP_KERNEL::NormalizedCellType type;
853 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
857 std::size_t newLgth=std::distance(tmp,work)-1;
858 std::size_t delta=newLgth-lgthOld;
859 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
860 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
861 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
866 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
867 oss << " in range [0," << nbOfCells << ") !";
868 throw INTERP_KERNEL::Exception(oss.str().c_str());
871 _nodal_connec->alloc((int)connNew.size(),1);
872 int *newConnPtr=_nodal_connec->getPointer();
873 std::copy(connNew.begin(),connNew.end(),newConnPtr);
879 * This method converts all cells into poly type if possible.
880 * This method is purely for userfriendliness.
881 * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
883 void MEDCouplingUMesh::convertAllToPoly()
885 int nbOfCells=getNumberOfCells();
886 std::vector<int> cellIds(nbOfCells);
887 for(int i=0;i<nbOfCells;i++)
889 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
893 * This method expects that 'this' has a spacedim equal to 3 and a mesh dimension equal to 3 too, if not an exception will be thrown.
894 * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
895 * For such polyhedra, they are expected to have only 1 face (containing 2 faces in opposition), having 2*n number of nodes (n nodes on
896 * each 2 faces hidden in the single face of polyhedron).
897 * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
898 * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
899 * In case of presence of polyhedron that has not the extruded aspect (2 faces with the same number of nodes) an exception is thrown and 'this'
901 * This method is usefull only for users that wants to build extruded unstructured mesh.
902 * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
903 * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
905 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
908 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
910 int nbOfCells=getNumberOfCells();
911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
912 newCi->alloc(nbOfCells+1,1);
913 int *newci=newCi->getPointer();
914 const int *ci=_nodal_connec_index->getConstPointer();
915 const int *c=_nodal_connec->getConstPointer();
917 for(int i=0;i<nbOfCells;i++)
919 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
920 if(type==INTERP_KERNEL::NORM_POLYHED)
922 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
924 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
925 throw INTERP_KERNEL::Exception(oss.str().c_str());
927 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
930 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 !";
931 throw INTERP_KERNEL::Exception(oss.str().c_str());
934 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)
937 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
940 newC->alloc(newci[nbOfCells],1);
941 int *newc=newC->getPointer();
942 for(int i=0;i<nbOfCells;i++)
944 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
945 if(type==INTERP_KERNEL::NORM_POLYHED)
947 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
948 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
950 for(std::size_t j=0;j<n1;j++)
952 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
954 newc[n1+5*j+1]=c[ci[i]+1+j];
955 newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
956 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
957 newc[n1+5*j+4]=c[ci[i]+1+j+n1];
962 newc=std::copy(c+ci[i],c+ci[i+1],newc);
964 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi;
965 _nodal_connec->decrRef(); _nodal_connec=newC;
966 newC->incrRef(); newCi->incrRef();
970 * This method is the opposite of ParaMEDMEM::MEDCouplingUMesh::convertToPolyTypes method.
971 * The aim is to take all polygons or polyhedrons cell and to try to traduce them into classical cells.
973 * \return If true at least one cell has been unpolyzed.
974 \n If false has been returned the nodal connectivity of \a this has **not** been altered and \a this has remains unchanged.
976 * \warning This method modifies can modify significantly the geometric type order in \a this.
977 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
979 bool MEDCouplingUMesh::unPolyze()
982 int mdim=getMeshDimension();
984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
987 int nbOfCells=getNumberOfCells();
990 int initMeshLgth=getMeshLength();
991 int *conn=_nodal_connec->getPointer();
992 int *index=_nodal_connec_index->getPointer();
997 for(int i=0;i<nbOfCells;i++)
999 lgthOfCurCell=index[i+1]-posOfCurCell;
1000 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1001 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1002 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1006 switch(cm.getDimension())
1010 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1011 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1012 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1017 int nbOfFaces,lgthOfPolyhConn;
1018 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1019 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1024 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1028 ret=ret || (newType!=type);
1029 conn[newPos]=newType;
1031 posOfCurCell=index[i+1];
1036 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1037 newPos+=lgthOfCurCell;
1038 posOfCurCell+=lgthOfCurCell;
1042 if(newPos!=initMeshLgth)
1043 _nodal_connec->reAlloc(newPos);
1050 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1051 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1052 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1054 * \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
1057 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1059 checkFullyDefined();
1060 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1062 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1063 coords->recenterForMaxPrecision(eps);
1064 const double *coordsPtr=coords->getConstPointer();
1066 int nbOfCells=getNumberOfCells();
1067 const int *conn=_nodal_connec->getConstPointer();
1068 const int *index=_nodal_connec_index->getConstPointer();
1069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1070 connINew->alloc(nbOfCells+1,1);
1071 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1072 std::vector<int> connNew;
1074 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1076 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1078 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1082 connNew.insert(connNew.end(),conn+index[i],conn+index[i+1]);
1083 *connINewPtr=(int)connNew.size();
1087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew2=DataArrayInt::New();
1088 connNew2->alloc((int)connNew.size(),1);
1089 std::copy(connNew.begin(),connNew.end(),connNew2->getPointer());
1090 setConnectivity(connNew2,connINew,false);
1095 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1096 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1097 * the format of returned DataArrayInt instance.
1099 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1100 * \sa MEDCouplingUMesh::getNodeIdsInUse
1102 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1104 checkConnectivityFullyDefined();
1106 int nbOfCells=getNumberOfCells();
1107 const int *connIndex=_nodal_connec_index->getConstPointer();
1108 const int *conn=_nodal_connec->getConstPointer();
1109 for(int i=0;i<nbOfCells;i++)
1110 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1112 retS.insert(conn[j]);
1113 DataArrayInt *ret=DataArrayInt::New();
1114 ret->alloc((int)retS.size(),1);
1115 std::copy(retS.begin(),retS.end(),ret->getPointer());
1120 * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
1121 * The returned array is newly created and should be dealt by the caller.
1122 * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
1123 * The size of returned array is the number of nodes of 'this'.
1124 * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
1125 * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
1126 * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
1128 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1131 int nbOfNodes=getNumberOfNodes();
1132 DataArrayInt *ret=DataArrayInt::New();
1133 ret->alloc(nbOfNodes,1);
1134 int *traducer=ret->getPointer();
1135 std::fill(traducer,traducer+nbOfNodes,-1);
1136 int nbOfCells=getNumberOfCells();
1137 const int *connIndex=_nodal_connec_index->getConstPointer();
1138 const int *conn=_nodal_connec->getConstPointer();
1139 for(int i=0;i<nbOfCells;i++)
1140 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1142 traducer[conn[j]]=1;
1143 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1144 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1149 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1150 * For each cell in \b this the number of nodes constituting cell is computed.
1151 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1152 * For polyhedrons, the face separation (-1) are excluded from the couting.
1154 * \return a newly allocated array
1156 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1158 checkConnectivityFullyDefined();
1159 int nbOfCells=getNumberOfCells();
1160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1161 ret->alloc(nbOfCells,1);
1162 int *retPtr=ret->getPointer();
1163 const int *conn=getNodalConnectivity()->getConstPointer();
1164 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1165 for(int i=0;i<nbOfCells;i++,retPtr++)
1167 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1168 *retPtr=connI[i+1]-connI[i]-1;
1170 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1172 ret->incrRef(); return ret;
1176 * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
1177 * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
1178 * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
1179 * -1 values in returned array means that the corresponding old node is no more used.
1181 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1183 int newNbOfNodes=-1;
1184 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1185 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1190 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1191 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1193 int MEDCouplingUMesh::areCellsEqual(int cell1, int cell2, int compType) const
1198 return areCellsEqual0(cell1,cell2);
1200 return areCellsEqual1(cell1,cell2);
1202 return areCellsEqual2(cell1,cell2);
1204 return areCellsEqual7(cell1,cell2);
1206 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1 or 2.");
1210 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1212 int MEDCouplingUMesh::areCellsEqual0(int cell1, int cell2) const
1214 const int *conn=getNodalConnectivity()->getConstPointer();
1215 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1216 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1217 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1222 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1224 int MEDCouplingUMesh::areCellsEqual1(int cell1, int cell2) const
1226 const int *conn=getNodalConnectivity()->getConstPointer();
1227 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1228 int sz=connI[cell1+1]-connI[cell1];
1229 if(sz==connI[cell2+1]-connI[cell2])
1231 if(conn[connI[cell1]]==conn[connI[cell2]])
1233 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1234 unsigned dim=cm.getDimension();
1240 int *tmp=new int[sz1];
1241 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],tmp);
1242 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1243 work=std::search(tmp,tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1245 return work!=tmp+sz1?1:0;
1248 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1251 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areCellsEqual1 : not implemented yet for meshdim == 3 !");
1258 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1260 int MEDCouplingUMesh::areCellsEqual2(int cell1, int cell2) const
1262 const int *conn=getNodalConnectivity()->getConstPointer();
1263 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1264 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1266 if(conn[connI[cell1]]==conn[connI[cell2]])
1268 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1269 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1277 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1279 int MEDCouplingUMesh::areCellsEqual7(int cell1, int cell2) const
1281 const int *conn=getNodalConnectivity()->getConstPointer();
1282 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1283 int sz=connI[cell1+1]-connI[cell1];
1284 if(sz==connI[cell2+1]-connI[cell2])
1286 if(conn[connI[cell1]]==conn[connI[cell2]])
1288 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1289 unsigned dim=cm.getDimension();
1295 int *tmp=new int[sz1];
1296 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],tmp);
1297 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1298 work=std::search(tmp,tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1306 std::reverse_iterator<int *> it1(tmp+sz1);
1307 std::reverse_iterator<int *> it2(tmp);
1308 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1320 return work!=tmp+sz1?1:0;
1323 {//case of SEG2 and SEG3
1324 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1326 if(!cm.isQuadratic())
1328 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1329 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1330 if(std::equal(it1,it2,conn+connI[cell2]+1))
1336 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])
1343 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areCellsEqual7 : not implemented yet for meshdim == 3 !");
1351 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1352 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1354 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1356 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1358 std::vector<int> c1,c2;
1359 getNodeIdsOfCell(cellId,c1);
1360 other->getNodeIdsOfCell(cellId,c2);
1361 std::size_t sz=c1.size();
1364 for(std::size_t i=0;i<sz;i++)
1366 std::vector<double> n1,n2;
1367 getCoordinatesOfNode(c1[0],n1);
1368 other->getCoordinatesOfNode(c2[0],n2);
1369 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1370 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1371 if(*std::max_element(n1.begin(),n1.end())>prec)
1378 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1379 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1380 * and result remains unchanged.
1381 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1382 * If in 'candidates' pool -1 value is considered as an empty value.
1383 * WARNING this method returns only ONE set of result !
1385 bool MEDCouplingUMesh::areCellsEqualInPool(const std::vector<int>& candidates, int compType, std::vector<int>& result) const
1387 std::set<int> cand(candidates.begin(),candidates.end());
1392 std::set<int>::const_iterator iter=cand.begin();
1393 int start=(*iter++);
1394 for(;iter!=cand.end();iter++)
1396 int status=areCellsEqual(start,*iter,compType);
1401 result.push_back(start);
1405 result.push_back(*iter);
1407 result.push_back(status==2?(*iter+1):-(*iter+1));
1414 * This method common cells base regarding 'compType' comparison policy described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for details.
1415 * This method returns 2 values 'res' and 'resI'.
1416 * If 'res' and 'resI' are not empty before calling this method they will be cleared before set.
1417 * The format of 'res' and 'resI' is as explained here.
1418 * resI.size()-1 is the number of set of cells equal.
1419 * The nth set is [res.begin()+resI[n];res.begin()+resI[n+1]) with 0<=n<resI.size()-1
1421 template<int SPACEDIM>
1422 void MEDCouplingUMesh::findCommonCellsBase(int compType, std::vector<int>& res, std::vector<int>& resI) const
1424 res.clear(); resI.clear();
1426 std::vector<double> bbox;
1427 int nbOfCells=getNumberOfCells();
1428 getBoundingBoxForBBTree(bbox);
1429 double bb[2*SPACEDIM];
1430 double eps=getCaracteristicDimension();
1432 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
1433 const int *conn=getNodalConnectivity()->getConstPointer();
1434 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1435 const double *coords=getCoords()->getConstPointer();
1436 std::vector<bool> isFetched(nbOfCells);
1437 for(int k=0;k<nbOfCells;k++)
1441 for(int j=0;j<SPACEDIM;j++)
1442 { bb[2*j]=std::numeric_limits<double>::max(); bb[2*j+1]=-std::numeric_limits<double>::max(); }
1443 for(const int *pt=conn+connI[k]+1;pt!=conn+connI[k+1];pt++)
1446 for(int j=0;j<SPACEDIM;j++)
1448 bb[2*j]=std::min(bb[2*j],coords[SPACEDIM*(*pt)+j]);
1449 bb[2*j+1]=std::max(bb[2*j+1],coords[SPACEDIM*(*pt)+j]);
1452 std::vector<int> candidates1;
1453 myTree.getIntersectingElems(bb,candidates1);
1454 std::vector<int> candidates;
1455 for(std::vector<int>::const_iterator iter=candidates1.begin();iter!=candidates1.end();iter++)
1456 if(!isFetched[*iter])
1457 candidates.push_back(*iter);
1458 if(areCellsEqualInPool(candidates,compType,res))
1460 int pos=resI.back();
1461 resI.push_back((int)res.size());
1462 for(std::vector<int>::const_iterator it=res.begin()+pos;it!=res.end();it++)
1463 isFetched[*it]=true;
1471 * This method could potentially modify 'this'. This method merges cells if there are cells equal in 'this'. The comparison is specified by 'compType'.
1472 * This method keeps the coordiantes of 'this'.
1474 * @param compType input specifying the technique used to compare cells each other.
1475 * - 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.
1476 * - 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)
1477 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1478 * - 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
1479 * can be used for users not sensitive to orientation of cell
1480 * @return the correspondance array old to new.
1482 * \warning This method modifies can modify significantly the geometric type order in \a this.
1483 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1485 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType) throw(INTERP_KERNEL::Exception)
1487 int spaceDim=getSpaceDimension();
1488 int nbOfCells=getNumberOfCells();
1489 std::vector<int> commonCells;
1490 std::vector<int> commonCellsI;
1495 findCommonCellsBase<3>(compType,commonCells,commonCellsI);
1500 findCommonCellsBase<2>(compType,commonCells,commonCellsI);
1505 findCommonCellsBase<1>(compType,commonCells,commonCellsI);
1509 throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3.");
1511 DataArrayInt *ret=DataArrayInt::New();
1512 ret->alloc(nbOfCells,1);
1513 int *retPtr=ret->getPointer();
1514 std::fill(retPtr,retPtr+nbOfCells,0);
1515 const std::size_t nbOfTupleSmCells=commonCellsI.size()-1;
1517 std::vector<int> cellsToKeep;
1518 for(std::size_t i=0;i<nbOfTupleSmCells;i++)
1520 for(std::vector<int>::const_iterator it=commonCells.begin()+commonCellsI[i];it!=commonCells.begin()+commonCellsI[i+1];it++)
1525 std::map<int,int> m;
1526 for(int i=0;i<nbOfCells;i++)
1532 cellsToKeep.push_back(i);
1536 std::map<int,int>::const_iterator iter=m.find(val);
1541 cellsToKeep.push_back(i);
1544 retPtr[i]=(*iter).second;
1547 MEDCouplingUMesh *self=(MEDCouplingUMesh *)buildPartOfMySelf(&cellsToKeep[0],&cellsToKeep[0]+cellsToKeep.size(),true);
1548 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1554 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1555 * This method tries to determine if 'other' is fully included in 'this'. To compute that, this method works with connectivity as MEDCouplingUMesh::zipConnectivityTraducer method does.
1556 * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
1557 * The main difference is that this method is not expected to throw exception.
1558 * This method has two outputs :
1560 * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
1561 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1562 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1564 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1566 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType);
1568 int nbOfCells=getNumberOfCells();
1569 arr=o2n->substr(nbOfCells);
1570 arr->setName(other->getName());
1572 if(other->getNumberOfCells()==0)
1574 return arr->getMaxValue(tmp)<nbOfCells;
1578 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1579 * This method tries to determine if \b other is fully included in \b this.
1580 * The main difference is that this method is not expected to throw exception.
1581 * This method has two outputs :
1583 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1584 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1586 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1588 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1589 int spaceDim=mesh->getSpaceDimension();
1590 std::vector<int> commonCells;
1591 std::vector<int> commonCellsI;
1596 findCommonCellsBase<3>(7,commonCells,commonCellsI);
1601 findCommonCellsBase<2>(7,commonCells,commonCellsI);
1606 findCommonCellsBase<1>(7,commonCells,commonCellsI);
1610 throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3.");
1612 int thisNbCells=getNumberOfCells();
1613 int otherNbCells=other->getNumberOfCells();
1614 int nbOfCells=mesh->getNumberOfCells();
1615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1616 arr2->alloc(otherNbCells,1);
1617 arr2->fillWithZero();
1618 int *arr2Ptr=arr2->getPointer();
1619 int nbOfCommon=(int)commonCellsI.size()-1;
1620 for(int i=0;i<nbOfCommon;i++)
1622 int start=commonCells[commonCellsI[i]];
1623 if(start<thisNbCells)
1625 for(int j=commonCellsI[i]+1;j!=commonCellsI[i+1];j++)
1627 int sig=commonCells[j]>0?1:-1;
1628 int val=std::abs(commonCells[j])-1;
1629 if(val>=thisNbCells)
1630 arr2Ptr[val-thisNbCells]=sig*(start+1);
1634 arr2->setName(other->getName());
1635 if(arr2->presenceOfValue(0))
1643 * @param areNodesMerged if at least two nodes have been merged.
1644 * @return old to new node correspondance.
1646 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1648 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1650 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1655 * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
1657 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1659 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1661 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1666 * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
1667 * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
1668 * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
1669 * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
1671 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
1673 const DataArrayDouble *coords=other.getCoords();
1675 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
1677 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1678 int otherNbOfNodes=other.getNumberOfNodes();
1679 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1681 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1682 setCoords(newCoords);
1683 bool areNodesMerged;
1685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1688 setCoords(oldCoords);
1689 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1691 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1692 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1693 if(pt!=da->getConstPointer()+da->getNbOfElems())
1695 setCoords(oldCoords);
1696 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1698 setCoords(oldCoords);
1699 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1704 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1705 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1706 * cellIds is not given explicitely but by a range python like.
1708 * \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.
1709 * \return a newly allocated
1711 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1712 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1714 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1716 if(getMeshDimension()!=-1)
1718 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
1725 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1727 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1729 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1731 return const_cast<MEDCouplingUMesh *>(this);
1736 * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
1737 * @param begin begin of array containing the cell ids to keep.
1738 * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
1739 * @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.
1741 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1742 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1744 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1746 if(getMeshDimension()!=-1)
1748 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
1756 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1758 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1760 return const_cast<MEDCouplingUMesh *>(this);
1765 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1767 * 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.
1768 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1769 * The number of cells of \b this will remain the same with this method.
1771 * \param [in] begin begin of cell ids (included) of cells in this to assign
1772 * \param [in] end end of cell ids (excluded) of cells in this to assign
1773 * \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).
1774 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1776 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1778 checkConnectivityFullyDefined();
1779 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1780 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1782 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1784 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1785 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1786 throw INTERP_KERNEL::Exception(oss.str().c_str());
1788 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1789 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1791 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1792 throw INTERP_KERNEL::Exception(oss.str().c_str());
1794 int nbOfCells=getNumberOfCells();
1795 bool easyAssign=true;
1796 const int *conn=_nodal_connec->getConstPointer();
1797 const int *connI=_nodal_connec_index->getConstPointer();
1798 const int *connOther=otherOnSameCoordsThanThis._nodal_connec->getConstPointer();
1799 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1800 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1802 if(*it>=0 && *it<nbOfCells)
1804 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1808 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1809 throw INTERP_KERNEL::Exception(oss.str().c_str());
1814 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1819 DataArrayInt *arrOut=0,*arrIOut=0;
1820 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1823 setConnectivity(arrOut,arrIOut,true);
1827 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1829 checkConnectivityFullyDefined();
1830 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1831 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1832 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1833 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1835 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1836 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1837 throw INTERP_KERNEL::Exception(oss.str().c_str());
1839 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1840 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1842 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1843 throw INTERP_KERNEL::Exception(oss.str().c_str());
1845 int nbOfCells=getNumberOfCells();
1846 bool easyAssign=true;
1847 const int *conn=_nodal_connec->getConstPointer();
1848 const int *connI=_nodal_connec_index->getConstPointer();
1849 const int *connOther=otherOnSameCoordsThanThis._nodal_connec->getConstPointer();
1850 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1852 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1854 if(it>=0 && it<nbOfCells)
1856 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1860 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1861 throw INTERP_KERNEL::Exception(oss.str().c_str());
1866 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1871 DataArrayInt *arrOut=0,*arrIOut=0;
1872 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1875 setConnectivity(arrOut,arrIOut,true);
1879 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1881 std::vector<int> cellIdsKept;
1882 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
1883 DataArrayInt *ret=DataArrayInt::New();
1884 ret->alloc((int)cellIdsKept.size(),1);
1885 std::copy(cellIdsKept.begin(),cellIdsKept.end(),ret->getPointer());
1890 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1891 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
1892 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1893 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1895 * @param begin input start of array of node ids.
1896 * @param end input end of array of node ids.
1897 * @param fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
1898 * @param cellIdsKept in/out array where all candidate cell ids are put at the end.
1900 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, std::vector<int>& cellIdsKept) const
1902 std::set<int> fastFinder(begin,end);
1903 int nbOfCells=getNumberOfCells();
1904 const int *conn=getNodalConnectivity()->getConstPointer();
1905 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
1906 for(int i=0;i<nbOfCells;i++)
1908 std::set<int> connOfCell(conn+connIndex[i]+1,conn+connIndex[i+1]);
1909 connOfCell.erase(-1);//polyhedron separator
1910 int refLgth=(int)connOfCell.size();
1911 std::set<int> locMerge;
1912 std::insert_iterator< std::set<int> > it(locMerge,locMerge.begin());
1913 std::set_intersection(connOfCell.begin(),connOfCell.end(),fastFinder.begin(),fastFinder.end(),it);
1914 if(((int)locMerge.size()==refLgth && fullyIn) || (locMerge.size()!=0 && !fullyIn))
1915 cellIdsKept.push_back(i);
1920 * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
1922 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1924 std::vector<int> cellIdsKept;
1925 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1926 DataArrayInt *ret=DataArrayInt::New();
1927 ret->alloc((int)cellIdsKept.size(),1);
1928 std::copy(cellIdsKept.begin(),cellIdsKept.end(),ret->getPointer());
1929 ret->setName(getName());
1934 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1935 * The return newly allocated mesh will share the same coordinates as 'this'.
1936 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1937 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1939 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1941 std::vector<int> cellIdsKept;
1942 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1943 return buildPartOfMySelf(&cellIdsKept[0],&cellIdsKept[0]+cellIdsKept.size(),true);
1947 * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
1948 * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
1949 * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
1950 * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
1952 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
1955 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
1956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
1957 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
1958 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
1962 * This method returns a mesh with meshDim=this->getMeshDimension()-1.
1963 * This returned mesh contains cells that are linked with one and only one cell of this.
1964 * @param keepCoords specifies if ParaMEDMEM::MEDCouplingUMesh::zipCoords is called on returned mesh before being returned. If true zipCoords is \b NOT called, if false, zipCoords is called.
1965 * @return mesh with ref counter equal to 1.
1967 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
1969 DataArrayInt *desc=DataArrayInt::New();
1970 DataArrayInt *descIndx=DataArrayInt::New();
1971 DataArrayInt *revDesc=DataArrayInt::New();
1972 DataArrayInt *revDescIndx=DataArrayInt::New();
1974 MEDCouplingUMesh *meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
1977 descIndx->decrRef();
1978 int nbOfCells=meshDM1->getNumberOfCells();
1979 const int *revDescIndxC=revDescIndx->getConstPointer();
1980 std::vector<int> boundaryCells;
1981 for(int i=0;i<nbOfCells;i++)
1982 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
1983 boundaryCells.push_back(i);
1984 revDescIndx->decrRef();
1985 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
1991 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
1992 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
1993 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
1995 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
1997 checkFullyDefined();
1998 DataArrayInt *desc=DataArrayInt::New();
1999 DataArrayInt *descIndx=DataArrayInt::New();
2000 DataArrayInt *revDesc=DataArrayInt::New();
2001 DataArrayInt *revDescIndx=DataArrayInt::New();
2003 MEDCouplingUMesh *meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2006 descIndx->decrRef();
2008 DataArrayInt *tmp=revDescIndx->deltaShiftIndex();
2009 DataArrayInt *faceIds=tmp->getIdsEqual(1);
2011 int nbOfFaces=faceIds->getNumberOfTuples();
2012 const int *faces=faceIds->getConstPointer();
2014 for(const int *w=faces;w!=faces+nbOfFaces;w++)
2015 ret.insert(revDesc->getIJ(revDescIndx->getIJ(*w,0),0));
2018 revDescIndx->decrRef();
2021 DataArrayInt *ret2=DataArrayInt::New();
2022 ret2->alloc((int)ret.size(),1);
2023 std::copy(ret.begin(),ret.end(),ret2->getPointer());
2024 ret2->setName("BoundaryCells");
2029 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2030 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2031 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2032 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2034 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2035 * This method method returns cells ids set s = s1 + s2 where :
2037 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2038 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2040 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2041 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2043 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2044 * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2045 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2047 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2049 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2051 checkConnectivityFullyDefined();
2052 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2053 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2054 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2057 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2059 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2060 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2061 DataArrayInt *idsOtherInConsti=0;
2062 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2065 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2067 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2068 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2071 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2072 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2073 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2074 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2075 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2076 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2077 neighThisPartAuto=0;
2078 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2079 const int li[2]={0,1};
2080 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2081 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2082 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2085 s0arr->incrRef(); cellIdsRk0=s0arr;
2086 s_renum1->incrRef(); cellIdsRk1=s_renum1;
2090 * 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
2091 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2093 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2095 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2103 revDesc=0; desc=0; descIndx=0;
2104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2106 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2110 * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2111 * The returned nodes ids are those lying on the boundary of \b this.
2113 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2115 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2116 return skin->computeFetchedNodeIds();
2119 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2122 return const_cast<MEDCouplingUMesh *>(this);
2126 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2127 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2128 * This value is asked because often known by the caller of this method.
2129 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2131 * @param newNodeNumbers array specifying the new numbering in old2New convention.
2132 * @param newNbOfNodes the new number of nodes.
2134 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2136 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2137 renumberNodesInConn(newNodeNumbers);
2141 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2142 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2143 * This value is asked because often known by the caller of this method.
2144 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2145 * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2147 * @param newNodeNumbers array specifying the new numbering.
2148 * @param newNbOfNodes the new number of nodes.
2151 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2153 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2154 renumberNodesInConn(newNodeNumbers);
2158 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2159 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2160 * 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.
2161 * 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.
2162 * 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.
2164 * \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
2165 * parameter is altered during the call.
2166 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2167 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2168 * \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.
2170 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2172 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2173 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2175 checkFullyDefined();
2176 otherDimM1OnSameCoords.checkFullyDefined();
2177 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2178 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2179 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2180 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2181 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2182 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2185 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2190 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2192 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2194 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2195 DataArrayInt *idsTmp=0;
2196 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2199 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2200 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2201 DataArrayInt *tmp0=0,*tmp1=0;
2202 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2207 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2208 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2210 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum; cellsToModifyConn0_torenum->incrRef();
2211 cellIdsNotModified=cellsToModifyConn1_torenum; cellsToModifyConn1_torenum->incrRef();
2212 nodeIdsToDuplicate=s3; s3->incrRef();
2216 * This method operates a modification of the connectivity and coords in \b this.
2217 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2218 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2219 * 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
2220 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2221 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2223 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2225 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2226 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2228 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2230 int nbOfNodes=getNumberOfNodes();
2231 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2232 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2236 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2237 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2238 * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2239 * @param [in] newNodeNumbers in old2New convention
2241 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2243 checkConnectivityFullyDefined();
2244 int *conn=getNodalConnectivity()->getPointer();
2245 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2246 int nbOfCells=getNumberOfCells();
2247 for(int i=0;i<nbOfCells;i++)
2248 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2250 int& node=conn[iconn];
2251 if(node>=0)//avoid polyhedron separator
2253 node=newNodeNumbersO2N[node];
2256 _nodal_connec->declareAsNew();
2261 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2262 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2263 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2265 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2267 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2269 checkConnectivityFullyDefined();
2270 int *conn=getNodalConnectivity()->getPointer();
2271 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2272 int nbOfCells=getNumberOfCells();
2273 for(int i=0;i<nbOfCells;i++)
2274 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2276 int& node=conn[iconn];
2277 if(node>=0)//avoid polyhedron separator
2282 _nodal_connec->declareAsNew();
2287 * This method operates a modification of the connectivity in \b this.
2288 * 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.
2289 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2290 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2291 * 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
2292 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2293 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2295 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2296 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2298 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2299 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2300 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2302 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2304 checkConnectivityFullyDefined();
2305 std::map<int,int> m;
2307 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2309 int *conn=getNodalConnectivity()->getPointer();
2310 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2311 int nbOfCells=getNumberOfCells();
2312 for(int i=0;i<nbOfCells;i++)
2313 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2315 int& node=conn[iconn];
2316 if(node>=0)//avoid polyhedron separator
2318 std::map<int,int>::iterator it=m.find(node);
2327 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2329 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2330 * After the call of this method the number of cells remains the same as before.
2332 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2333 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2334 * be strictly in [0;this->getNumberOfCells()).
2336 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2337 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2338 * should be contained in[0;this->getNumberOfCells()).
2340 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2342 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2344 checkConnectivityFullyDefined();
2345 int nbCells=getNumberOfCells();
2346 const int *array=old2NewBg;
2348 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2350 const int *conn=_nodal_connec->getConstPointer();
2351 const int *connI=_nodal_connec_index->getConstPointer();
2352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2353 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2354 newConn->copyStringInfoFrom(*_nodal_connec);
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2356 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2357 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2359 int *newC=newConn->getPointer();
2360 int *newCI=newConnI->getPointer();
2363 for(int i=0;i<nbCells;i++)
2365 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2366 int nbOfElts=connI[pos+1]-connI[pos];
2367 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2372 setConnectivity(newConn,newConnI);
2374 delete [] const_cast<int *>(array);
2378 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2379 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2380 * added in 'elems' parameter.
2382 void MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps, std::vector<int>& elems) const
2384 if(getMeshDimension()==-1)
2389 int dim=getSpaceDimension();
2390 double* elem_bb=new double[2*dim];
2391 const int* conn = getNodalConnectivity()->getConstPointer();
2392 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2393 const double* coords = getCoords()->getConstPointer();
2394 int nbOfCells=getNumberOfCells();
2395 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2397 for (int i=0; i<dim; i++)
2399 elem_bb[i*2]=std::numeric_limits<double>::max();
2400 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2403 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2405 int node= conn[inode];
2406 if(node>=0)//avoid polyhedron separator
2408 for (int idim=0; idim<dim; idim++)
2410 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2412 elem_bb[idim*2] = coords[node*dim+idim] ;
2414 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2416 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2421 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2423 elems.push_back(ielem);
2430 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2431 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2432 * added in 'elems' parameter.
2434 void MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps, std::vector<int>& elems)
2436 if(getMeshDimension()==-1)
2441 int dim=getSpaceDimension();
2442 double* elem_bb=new double[2*dim];
2443 const int* conn = getNodalConnectivity()->getConstPointer();
2444 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2445 const double* coords = getCoords()->getConstPointer();
2446 int nbOfCells=getNumberOfCells();
2447 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2449 for (int i=0; i<dim; i++)
2451 elem_bb[i*2]=std::numeric_limits<double>::max();
2452 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2455 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2457 int node= conn[inode];
2458 if(node>=0)//avoid polyhedron separator
2460 for (int idim=0; idim<dim; idim++)
2462 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2464 elem_bb[idim*2] = coords[node*dim+idim] ;
2466 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2468 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2473 if (intersectsBoundingBox(bbox, elem_bb, dim, eps))
2475 elems.push_back(ielem);
2482 * Returns the cell type of cell with id 'cellId'.
2484 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2486 const int *ptI=_nodal_connec_index->getConstPointer();
2487 const int *pt=_nodal_connec->getConstPointer();
2488 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2492 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2493 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2494 * The coordinates array is not considered here.
2496 * \param [in] type the geometric type
2499 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2503 checkConnectivityFullyDefined();
2504 int nbCells=getNumberOfCells();
2505 int mdim=getMeshDimension();
2506 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2507 if(mdim!=(int)cm.getDimension())
2508 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2509 const int *ptI=_nodal_connec_index->getConstPointer();
2510 const int *pt=_nodal_connec->getConstPointer();
2511 for(int i=0;i<nbCells;i++)
2513 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2516 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc((int)v.size(),1);
2517 std::copy(v.begin(),v.end(),ret->getPointer());
2523 * Returns nb of cells having the geometric type 'type'.
2525 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2527 const int *ptI=_nodal_connec_index->getConstPointer();
2528 const int *pt=_nodal_connec->getConstPointer();
2529 int nbOfCells=getNumberOfCells();
2531 for(int i=0;i<nbOfCells;i++)
2532 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2538 * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2539 * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2540 * That is to say -1 separator is omitted in returned conn.
2542 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2544 const int *ptI=_nodal_connec_index->getConstPointer();
2545 const int *pt=_nodal_connec->getConstPointer();
2546 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2551 std::string MEDCouplingUMesh::simpleRepr() const
2553 static const char msg0[]="No coordinates specified !";
2554 std::ostringstream ret;
2555 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2556 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2558 double tt=getTime(tmpp1,tmpp2);
2559 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2560 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2561 ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2564 const int spaceDim=getSpaceDimension();
2565 ret << spaceDim << "\nInfo attached on space dimension : ";
2566 for(int i=0;i<spaceDim;i++)
2567 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2571 ret << msg0 << "\n";
2572 ret << "Number of nodes : ";
2574 ret << getNumberOfNodes() << "\n";
2576 ret << msg0 << "\n";
2577 ret << "Number of cells : ";
2578 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2579 ret << getNumberOfCells() << "\n";
2581 ret << "No connectivity specified !" << "\n";
2582 ret << "Cell types present : ";
2583 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2585 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2586 ret << cm.getRepr() << " ";
2592 std::string MEDCouplingUMesh::advancedRepr() const
2594 std::ostringstream ret;
2595 ret << simpleRepr();
2596 ret << "\nCoordinates array : \n___________________\n\n";
2598 _coords->reprWithoutNameStream(ret);
2600 ret << "No array set !\n";
2601 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2602 reprConnectivityOfThisLL(ret);
2606 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2608 std::ostringstream ret;
2609 reprConnectivityOfThisLL(ret);
2614 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2615 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2616 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2619 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2620 * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
2621 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2623 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2625 int mdim=getMeshDimension();
2627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2628 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2630 bool needToCpyCT=true;
2633 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2641 if(!_nodal_connec_index)
2643 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2648 tmp2=_nodal_connec_index;
2651 ret->setConnectivity(tmp1,tmp2,false);
2656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2657 ret->setCoords(coords);
2660 ret->setCoords(_coords);
2665 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2667 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2669 int nbOfCells=getNumberOfCells();
2670 const int *c=_nodal_connec->getConstPointer();
2671 const int *ci=_nodal_connec_index->getConstPointer();
2672 for(int i=0;i<nbOfCells;i++)
2674 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2675 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2676 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2681 stream << "Connectivity not defined !\n";
2684 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2686 const int *ptI=_nodal_connec_index->getConstPointer();
2687 const int *pt=_nodal_connec->getConstPointer();
2688 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2689 return ptI[cellId+1]-ptI[cellId]-1;
2691 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2695 * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2696 * This method avoids to compute explicitely submesh to get its types.
2698 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2700 checkFullyDefined();
2701 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2702 const int *conn=_nodal_connec->getConstPointer();
2703 const int *connIndex=_nodal_connec_index->getConstPointer();
2704 for(const int *w=begin;w!=end;w++)
2705 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2710 * Method reserved for advanced users having prepared their connectivity before.
2711 * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2713 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2715 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2716 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2717 if(isComputingTypes)
2723 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2724 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2726 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_iterator(-1),_mesh_dim(other._mesh_dim),
2727 _nodal_connec(0),_nodal_connec_index(0),
2728 _types(other._types)
2730 if(other._nodal_connec)
2731 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2732 if(other._nodal_connec_index)
2733 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2736 MEDCouplingUMesh::~MEDCouplingUMesh()
2739 _nodal_connec->decrRef();
2740 if(_nodal_connec_index)
2741 _nodal_connec_index->decrRef();
2745 * This method recomputes all cell types of 'this'.
2747 void MEDCouplingUMesh::computeTypes()
2749 if(_nodal_connec && _nodal_connec_index)
2752 const int *conn=_nodal_connec->getConstPointer();
2753 const int *connIndex=_nodal_connec_index->getConstPointer();
2754 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2755 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
2756 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2761 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2763 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2765 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2766 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2770 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2772 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2774 if(!_nodal_connec_index || !_nodal_connec)
2775 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2778 int MEDCouplingUMesh::getNumberOfCells() const
2780 if(_nodal_connec_index)
2782 return _nodal_connec_index->getNumberOfTuples()-1;
2789 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2792 int MEDCouplingUMesh::getMeshDimension() const
2795 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2800 * This method is for test reason. Normally the integer returned is not useable by user.
2802 int MEDCouplingUMesh::getMeshLength() const
2804 return _nodal_connec->getNbOfElems();
2808 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2810 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2812 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2813 tinyInfo.push_back(getMeshDimension());
2814 tinyInfo.push_back(getNumberOfCells());
2816 tinyInfo.push_back(getMeshLength());
2818 tinyInfo.push_back(-1);
2822 * First step of unserialization process.
2824 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2826 return tinyInfo[6]<=0;
2830 * Second step of serialization process.
2831 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2833 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2835 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2837 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2841 * Third and final step of serialization process.
2843 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2845 MEDCouplingPointSet::serialize(a1,a2);
2846 if(getMeshDimension()>-1)
2848 a1=DataArrayInt::New();
2849 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2850 int *ptA1=a1->getPointer();
2851 const int *conn=getNodalConnectivity()->getConstPointer();
2852 const int *index=getNodalConnectivityIndex()->getConstPointer();
2853 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2854 std::copy(conn,conn+getMeshLength(),ptA1);
2861 * Second and final unserialization process.
2862 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2864 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2866 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2867 setMeshDimension(tinyInfo[5]);
2871 const int *recvBuffer=a1->getConstPointer();
2872 DataArrayInt* myConnecIndex=DataArrayInt::New();
2873 myConnecIndex->alloc(tinyInfo[6]+1,1);
2874 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2875 DataArrayInt* myConnec=DataArrayInt::New();
2876 myConnec->alloc(tinyInfo[7],1);
2877 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2878 setConnectivity(myConnec, myConnecIndex) ;
2879 myConnec->decrRef();
2880 myConnecIndex->decrRef();
2885 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2886 * CellIds are given using range specified by a start an end and step.
2888 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2890 checkFullyDefined();
2891 int ncell=getNumberOfCells();
2892 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2893 ret->_mesh_dim=_mesh_dim;
2894 ret->setCoords(_coords);
2895 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2897 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2899 const int *conn=_nodal_connec->getConstPointer();
2900 const int *connIndex=_nodal_connec_index->getConstPointer();
2901 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2903 if(work>=0 && work<ncell)
2905 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2909 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2910 throw INTERP_KERNEL::Exception(oss.str().c_str());
2913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
2914 int *newConnPtr=newConn->getPointer();
2915 std::set<INTERP_KERNEL::NormalizedCellType> types;
2917 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2919 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
2920 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
2922 ret->setConnectivity(newConn,newConnI,false);
2924 ret->copyTinyInfoFrom(this);
2925 std::string name(getName());
2926 std::size_t sz=strlen(PART_OF_NAME);
2927 if(name.length()>=sz)
2928 name=name.substr(0,sz);
2929 if(name!=PART_OF_NAME)
2931 std::ostringstream stream; stream << PART_OF_NAME << getName();
2932 ret->setName(stream.str().c_str());
2935 ret->setName(getName());
2941 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
2942 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2943 * The return newly allocated mesh will share the same coordinates as 'this'.
2945 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
2947 checkFullyDefined();
2948 int ncell=getNumberOfCells();
2949 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2950 ret->_mesh_dim=_mesh_dim;
2951 ret->setCoords(_coords);
2952 std::size_t nbOfElemsRet=std::distance(begin,end);
2953 int *connIndexRet=new int[nbOfElemsRet+1];
2955 const int *conn=_nodal_connec->getConstPointer();
2956 const int *connIndex=_nodal_connec_index->getConstPointer();
2958 for(const int *work=begin;work!=end;work++,newNbring++)
2960 if(*work>=0 && *work<ncell)
2961 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
2964 delete [] connIndexRet;
2965 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
2966 throw INTERP_KERNEL::Exception(oss.str().c_str());
2969 int *connRet=new int[connIndexRet[nbOfElemsRet]];
2970 int *connRetWork=connRet;
2971 std::set<INTERP_KERNEL::NormalizedCellType> types;
2972 for(const int *work=begin;work!=end;work++)
2974 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
2975 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
2977 DataArrayInt *connRetArr=DataArrayInt::New();
2978 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
2979 DataArrayInt *connIndexRetArr=DataArrayInt::New();
2980 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
2981 ret->setConnectivity(connRetArr,connIndexRetArr,false);
2983 connRetArr->decrRef();
2984 connIndexRetArr->decrRef();
2985 ret->copyTinyInfoFrom(this);
2986 std::string name(getName());
2987 std::size_t sz=strlen(PART_OF_NAME);
2988 if(name.length()>=sz)
2989 name=name.substr(0,sz);
2990 if(name!=PART_OF_NAME)
2992 std::ostringstream stream; stream << PART_OF_NAME << getName();
2993 ret->setName(stream.str().c_str());
2996 ret->setName(getName());
3002 * brief returns the volumes of the cells underlying the field \a field
3004 * For 2D geometries, the returned field contains the areas.
3005 * For 3D geometries, the returned field contains the volumes.
3007 * param field field on which cells the volumes are required
3008 * return field containing the volumes, area or length depending the meshdimension.
3010 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3012 std::string name="MeasureOfMesh_";
3014 int nbelem=getNumberOfCells();
3015 MEDCouplingFieldDouble *field=MEDCouplingFieldDouble::New(ON_CELLS);
3016 field->setName(name.c_str());
3017 DataArrayDouble* array=DataArrayDouble::New();
3018 array->alloc(nbelem,1);
3019 double *area_vol=array->getPointer();
3020 field->setArray(array) ;
3022 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3023 if(getMeshDimension()!=-1)
3026 INTERP_KERNEL::NormalizedCellType type;
3027 int dim_space=getSpaceDimension();
3028 const double *coords=getCoords()->getConstPointer();
3029 const int *connec=getNodalConnectivity()->getConstPointer();
3030 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3031 for(int iel=0;iel<nbelem;iel++)
3033 ipt=connec_index[iel];
3034 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3035 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);
3038 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3042 area_vol[0]=std::numeric_limits<double>::max();
3048 * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3049 * This method avoids to build explicitely part of this to perform the work.
3051 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3053 std::string name="PartMeasureOfMesh_";
3055 int nbelem=(int)std::distance(begin,end);
3056 DataArrayDouble* array=DataArrayDouble::New();
3057 array->setName(name.c_str());
3058 array->alloc(nbelem,1);
3059 double *area_vol=array->getPointer();
3060 if(getMeshDimension()!=-1)
3063 INTERP_KERNEL::NormalizedCellType type;
3064 int dim_space=getSpaceDimension();
3065 const double *coords=getCoords()->getConstPointer();
3066 const int *connec=getNodalConnectivity()->getConstPointer();
3067 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3068 for(const int *iel=begin;iel!=end;iel++)
3070 ipt=connec_index[*iel];
3071 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3072 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3075 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3079 area_vol[0]=std::numeric_limits<double>::max();
3085 * This methods returns a field on nodes and no time. This method is usefull to check "P1*" conservative interpolators.
3086 * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3088 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3090 MEDCouplingFieldDouble *tmp=getMeasureField(isAbs);
3091 std::string name="MeasureOnNodeOfMesh_";
3093 int nbNodes=getNumberOfNodes();
3094 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_NODES);
3095 double cst=1./((double)getMeshDimension()+1.);
3096 DataArrayDouble* array=DataArrayDouble::New();
3097 array->alloc(nbNodes,1);
3098 double *valsToFill=array->getPointer();
3099 std::fill(valsToFill,valsToFill+nbNodes,0.);
3100 const double *values=tmp->getArray()->getConstPointer();
3101 DataArrayInt *da=DataArrayInt::New();
3102 DataArrayInt *daInd=DataArrayInt::New();
3103 getReverseNodalConnectivity(da,daInd);
3104 const int *daPtr=da->getConstPointer();
3105 const int *daIPtr=daInd->getConstPointer();
3106 for(int i=0;i<nbNodes;i++)
3107 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3108 valsToFill[i]+=cst*values[*cell];
3112 ret->setArray(array);
3119 * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3120 * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3122 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3124 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3125 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3126 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
3127 DataArrayDouble *array=DataArrayDouble::New();
3128 int nbOfCells=getNumberOfCells();
3129 int nbComp=getMeshDimension()+1;
3130 array->alloc(nbOfCells,nbComp);
3131 double *vals=array->getPointer();
3132 const int *connI=_nodal_connec_index->getConstPointer();
3133 const int *conn=_nodal_connec->getConstPointer();
3134 const double *coords=_coords->getConstPointer();
3135 if(getMeshDimension()==2)
3137 if(getSpaceDimension()==3)
3139 DataArrayDouble *loc=getBarycenterAndOwner();
3140 const double *locPtr=loc->getConstPointer();
3141 for(int i=0;i<nbOfCells;i++,vals+=3)
3143 int offset=connI[i];
3144 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3145 double n=INTERP_KERNEL::norm<3>(vals);
3146 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3152 for(int i=0;i<nbOfCells;i++)
3153 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3156 else//meshdimension==1
3159 for(int i=0;i<nbOfCells;i++)
3161 int offset=connI[i];
3162 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3163 double n=INTERP_KERNEL::norm<2>(tmp);
3164 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3169 ret->setArray(array);
3176 * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3177 * This method avoids to build explicitely part of this to perform the work.
3179 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3181 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3182 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3183 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
3184 DataArrayDouble *array=DataArrayDouble::New();
3185 std::size_t nbelems=std::distance(begin,end);
3186 int nbComp=getMeshDimension()+1;
3187 array->alloc((int)nbelems,nbComp);
3188 double *vals=array->getPointer();
3189 const int *connI=_nodal_connec_index->getConstPointer();
3190 const int *conn=_nodal_connec->getConstPointer();
3191 const double *coords=_coords->getConstPointer();
3192 if(getMeshDimension()==2)
3194 if(getSpaceDimension()==3)
3196 DataArrayDouble *loc=getPartBarycenterAndOwner(begin,end);
3197 const double *locPtr=loc->getConstPointer();
3198 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3200 int offset=connI[*i];
3201 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3202 double n=INTERP_KERNEL::norm<3>(vals);
3203 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3209 for(std::size_t i=0;i<nbelems;i++)
3210 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3213 else//meshdimension==1
3216 for(const int *i=begin;i!=end;i++)
3218 int offset=connI[*i];
3219 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3220 double n=INTERP_KERNEL::norm<2>(tmp);
3221 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3226 ret->setArray(array);
3233 * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3234 * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3236 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3238 if(getMeshDimension()!=1)
3239 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3240 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3241 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3242 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
3243 DataArrayDouble *array=DataArrayDouble::New();
3244 int nbOfCells=getNumberOfCells();
3245 int spaceDim=getSpaceDimension();
3246 array->alloc(nbOfCells,spaceDim);
3247 double *pt=array->getPointer();
3248 const double *coo=getCoords()->getConstPointer();
3249 std::vector<int> conn;
3251 for(int i=0;i<nbOfCells;i++)
3254 getNodeIdsOfCell(i,conn);
3255 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3257 ret->setArray(array);
3264 * This method expects that 'this' is fully defined and has a spaceDim==3 and a meshDim==3. If it is not the case an exception will be thrown.
3265 * This method returns 2 objects :
3266 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3267 * - a newly created dataarray having number of tuples equal to the number of cells in returned mesh that tells for each 2D cell in returned
3268 * mesh the 3D cell id is 'this' it comes from.
3269 * This method works only for linear meshes (non quadratic).
3270 * If plane crosses within 'eps' a face in 'this' shared by more than 1 cell, 2 output faces will be generated. The 2 faces having the same geometry than intersecting
3271 * face. Only 'cellIds' parameter can distinguish the 2.
3272 * @param origin is the origin of the plane. It should be an array of length 3.
3273 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3274 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3275 * also used to state if new points should be created or already existing points are reused. 'eps' is also used to tells if plane overlaps a face, edge or nodes (in absolute).
3277 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3279 checkFullyDefined();
3280 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3283 if(candidates->empty())
3284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3285 std::vector<int> nodes;
3286 std::vector<int> cellIds2D,cellIds1D;
3287 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3288 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3293 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3294 revDesc2=0; revDescIndx2=0;
3295 mDesc2->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds2D);
3296 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3297 revDesc1=0; revDescIndx1=0;
3298 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3300 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3301 for(std::vector<int>::const_iterator it=cellIds1D.begin();it!=cellIds1D.end();it++)
3303 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3304 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3305 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3306 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3307 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3308 std::vector<int> conn,connI,cellIds2;
3310 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3311 if(cellIds2.empty())
3312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3313 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3314 ret->setCoords(mDesc1->getCoords());
3315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
3316 c->alloc((int)conn.size(),1); std::copy(conn.begin(),conn.end(),c->getPointer());
3317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
3318 cI->alloc((int)connI.size(),1); std::copy(connI.begin(),connI.end(),cI->getPointer());
3319 ret->setConnectivity(c,cI,true);
3320 cellIds=candidates->selectByTupleId(&cellIds2[0],&cellIds2[0]+cellIds2.size());
3326 * This method expects that 'this' is fully defined and has a spaceDim==3 and a meshDim==2. If it is not the case an exception will be thrown.
3327 * This method returns 2 objects :
3328 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3329 * - a newly created dataarray having number of tuples equal to the number of cells in returned mesh that tells for each 2D cell in returned
3330 * mesh the 3DSurf cell id is 'this' it comes from.
3331 * This method works only for linear meshes (non quadratic).
3332 * If plane crosses within 'eps' a face in 'this' shared by more than 1 cell, 2 output faces will be generated. The 2 faces having the same geometry than intersecting
3333 * face. Only 'cellIds' parameter can distinguish the 2.
3334 * @param origin is the origin of the plane. It should be an array of length 3.
3335 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3336 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3337 * also used to state if new points should be created or already existing points are reused. 'eps' is also used to tells if plane overlaps a face, edge or nodes (in absolute).
3339 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3341 checkFullyDefined();
3342 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3343 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3345 if(candidates->empty())
3346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3347 std::vector<int> nodes;
3348 std::vector<int> cellIds1D;
3349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3350 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3355 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3356 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3358 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3359 for(std::vector<int>::const_iterator it=cellIds1D.begin();it!=cellIds1D.end();it++)
3361 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3362 int ncellsSub=subMesh->getNumberOfCells();
3363 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3364 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3365 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3366 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3367 std::vector<int> conn,connI,cellIds2; connI.push_back(0);
3368 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3369 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3370 for(int i=0;i<ncellsSub;i++)
3372 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3374 if(cut3DSurf[i].first!=-2)
3376 conn.push_back((int)INTERP_KERNEL::NORM_SEG2); conn.push_back(cut3DSurf[i].first); conn.push_back(cut3DSurf[i].second);
3377 connI.push_back((int)conn.size());
3378 cellIds2.push_back(i);
3382 int cellId3DSurf=cut3DSurf[i].second;
3383 int offset=nodalI[cellId3DSurf]+1;
3384 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3385 for(int j=0;j<nbOfEdges;j++)
3387 conn.push_back((int)INTERP_KERNEL::NORM_SEG2); conn.push_back(nodal[offset+j]); conn.push_back(nodal[offset+(j+1)%nbOfEdges]);
3388 connI.push_back((int)conn.size());
3389 cellIds2.push_back(cellId3DSurf);
3394 if(cellIds2.empty())
3395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3397 ret->setCoords(mDesc1->getCoords());
3398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
3399 c->alloc((int)conn.size(),1); std::copy(conn.begin(),conn.end(),c->getPointer());
3400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
3401 cI->alloc((int)connI.size(),1); std::copy(connI.begin(),connI.end(),cI->getPointer());
3402 ret->setConnectivity(c,cI,true);
3403 cellIds=candidates->selectByTupleId(&cellIds2[0],&cellIds2[0]+cellIds2.size());
3409 * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3410 * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3411 * @param origin is the origin of the plane. It should be an array of length 3.
3412 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3414 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3416 checkFullyDefined();
3417 if(getSpaceDimension()!=3)
3418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3419 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3423 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3424 double angle=acos(vec[2]/normm);
3425 std::vector<int> cellIds;
3429 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3430 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3431 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3433 mw->getBoundingBox(bbox);
3434 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3435 mw->getCellsInBoundingBox(bbox,eps,cellIds);
3439 getBoundingBox(bbox);
3440 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3441 getCellsInBoundingBox(bbox,eps,cellIds);
3443 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
3444 ret->alloc((int)cellIds.size(),1);
3445 std::copy(cellIds.begin(),cellIds.end(),ret->getPointer());
3451 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3452 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3453 * No consideration of coordinate is done by this method.
3454 * 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)
3455 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3457 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3459 if(getMeshDimension()!=1)
3460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3461 int nbCells=getNumberOfCells();
3463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3464 const int *connI=_nodal_connec_index->getConstPointer();
3465 const int *conn=_nodal_connec->getConstPointer();
3466 int ref=conn[connI[0]+2];
3467 for(int i=1;i<nbCells;i++)
3469 if(conn[connI[i]+1]!=ref)
3471 ref=conn[connI[i]+2];
3477 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3478 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3479 * @param pt reference point of the line
3480 * @param v normalized director vector of the line
3481 * @param eps max precision before throwing an exception
3482 * @param res output of size this->getNumberOfCells
3484 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3486 if(getMeshDimension()!=1)
3487 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3488 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3489 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3490 if(getSpaceDimension()!=3)
3491 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3492 MEDCouplingFieldDouble *f=buildDirectionVectorField();
3493 const double *fPtr=f->getArray()->getConstPointer();
3495 for(int i=0;i<getNumberOfCells();i++)
3497 const double *tmp1=fPtr+3*i;
3498 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3499 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3500 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3501 double n1=INTERP_KERNEL::norm<3>(tmp);
3502 n1/=INTERP_KERNEL::norm<3>(tmp1);
3506 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3509 const double *coo=getCoords()->getConstPointer();
3510 for(int i=0;i<getNumberOfNodes();i++)
3512 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3513 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3514 res[i]=std::accumulate(tmp,tmp+3,0.);
3520 * Returns a cell if any that contains the point located on 'pos' with precison eps.
3521 * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3522 * \b Warning this method is good if the caller intends to evaluate only one point. But if more than one point is requested on 'this'
3523 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3525 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3527 std::vector<int> elts;
3528 getCellsContainingPoint(pos,eps,elts);
3531 return elts.front();
3535 * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3536 * \b Warning this method is good if the caller intends to evaluate only one point. But if more than one point is requested on 'this'
3537 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3539 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3541 std::vector<int> eltsIndex;
3542 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3547 namespace ParaMEDMEM
3549 template<const int SPACEDIMM>
3553 static const int MY_SPACEDIM=SPACEDIMM;
3554 static const int MY_MESHDIM=8;
3555 typedef int MyConnType;
3556 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3558 // useless, but for windows compilation ...
3559 const double* getCoordinatesPtr() const { return 0; }
3560 const int* getConnectivityPtr() const { return 0; }
3561 const int* getConnectivityIndexPtr() const { return 0; }
3562 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3566 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3568 INTERP_KERNEL::Edge *ret=0;
3571 case INTERP_KERNEL::NORM_SEG2:
3573 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3576 case INTERP_KERNEL::NORM_SEG3:
3578 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3579 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3580 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3581 bool colinearity=inters.areColinears();
3582 delete e1; delete e2;
3584 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3586 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3587 mapp2[bg[2]].second=false;
3591 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3597 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
3598 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3599 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3601 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3604 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.
3605 const double *coo=mDesc->getCoords()->getConstPointer();
3606 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3607 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3609 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3610 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3611 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3613 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3614 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3616 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3617 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3619 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3620 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3622 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3624 if((*it2).second.second)
3625 mapp[(*it2).second.first]=(*it2).first;
3626 ((*it2).second.first)->decrRef();
3631 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3635 int locId=nodeId-offset2;
3636 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3640 int locId=nodeId-offset1;
3641 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3643 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3646 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3647 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3648 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3650 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3652 int eltId1=abs(*desc1)-1;
3653 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3655 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3656 if(it==mappRev.end())
3658 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3669 template<int SPACEDIM>
3670 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3671 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3673 std::vector<double> bbox;
3674 eltsIndex.resize(nbOfPoints+1);
3677 getBoundingBoxForBBTree(bbox);
3678 int nbOfCells=getNumberOfCells();
3679 const int *conn=_nodal_connec->getConstPointer();
3680 const int *connI=_nodal_connec_index->getConstPointer();
3681 double bb[2*SPACEDIM];
3682 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3683 for(int i=0;i<nbOfPoints;i++)
3685 eltsIndex[i+1]=eltsIndex[i];
3686 for(int j=0;j<SPACEDIM;j++)
3688 bb[2*j]=pos[SPACEDIM*i+j];
3689 bb[2*j+1]=pos[SPACEDIM*i+j];
3691 std::vector<int> candidates;
3692 myTree.getIntersectingElems(bb,candidates);
3693 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3695 int sz=connI[(*iter)+1]-connI[*iter]-1;
3696 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3697 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3698 coords,conn+connI[*iter]+1,sz,eps))
3701 elts.push_back(*iter);
3708 * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3709 * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3710 * in case of multi points searching.
3711 * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3712 * For point j in [0,nbOfPoints), (eltsIndex[j+1]-eltsIndex[j]) cells contain this point. These cells are : [elts.begin()+eltsIndex[j],elts.begin():eltsIndex[j+1]).
3714 * \param pos input parameter that points to an array of size 'getSpaceDim()*nbOfPoints' points stored in full interlace mode : X0,Y0,Z0,X1,Y1,Z1...
3716 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3717 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3719 int spaceDim=getSpaceDimension();
3720 int mDim=getMeshDimension();
3725 const double *coords=_coords->getConstPointer();
3726 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3733 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3735 else if(spaceDim==2)
3739 const double *coords=_coords->getConstPointer();
3740 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3743 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3745 else if(spaceDim==1)
3749 const double *coords=_coords->getConstPointer();
3750 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3753 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3760 * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3761 * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3762 * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3763 * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3765 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3767 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3768 if(getMeshDimension()!=2)
3769 throw INTERP_KERNEL::Exception(msg);
3770 int spaceDim=getSpaceDimension();
3771 if(spaceDim!=2 && spaceDim!=3)
3772 throw INTERP_KERNEL::Exception(msg);
3773 const int *conn=_nodal_connec->getConstPointer();
3774 const int *connI=_nodal_connec_index->getConstPointer();
3775 int nbOfCells=getNumberOfCells();
3776 std::vector<double> cell2DinS2;
3777 for(int i=0;i<nbOfCells;i++)
3779 int offset=connI[i];
3780 int nbOfNodesForCell=connI[i+1]-offset-1;
3781 if(nbOfNodesForCell<=3)
3783 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3784 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3785 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3792 * This method is typically requested to unbutterfly 2D linear cells in \b this.
3794 * 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.
3795 * 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.
3797 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3798 * This convex envelop is computed using Jarvis march algorithm.
3799 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3800 * 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)
3801 * 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.
3803 * @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.
3805 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3807 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
3809 checkFullyDefined();
3810 const double *coords=getCoords()->getConstPointer();
3811 int nbOfCells=getNumberOfCells();
3812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3813 nodalConnecIndexOut->alloc(nbOfCells+1,1);
3814 std::vector<int> nodalConnecOut;
3815 int *workIndexOut=nodalConnecIndexOut->getPointer();
3817 const int *nodalConnecIn=_nodal_connec->getConstPointer();
3818 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3819 std::set<INTERP_KERNEL::NormalizedCellType> types;
3820 std::vector<int> isChanged;
3821 for(int i=0;i<nbOfCells;i++,workIndexOut++)
3823 std::size_t pos=nodalConnecOut.size();
3824 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3825 isChanged.push_back(i);
3826 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut[pos]);
3827 workIndexOut[1]=(int)nodalConnecOut.size();
3829 if(isChanged.empty())
3831 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut2=DataArrayInt::New();
3832 nodalConnecOut2->alloc((int)nodalConnecOut.size(),1);
3833 std::copy(nodalConnecOut.begin(),nodalConnecOut.end(),nodalConnecOut2->getPointer());
3834 setConnectivity(nodalConnecOut2,nodalConnecIndexOut,false);
3836 DataArrayInt *ret=DataArrayInt::New(); ret->alloc((int)isChanged.size(),1);
3837 std::copy(isChanged.begin(),isChanged.end(),ret->getPointer());
3842 * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
3843 * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
3844 * If some extruded cells does not fulfill the MED norm for extruded cells (first face of 3D cell should be oriented to the exterior of the 3D cell).
3845 * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
3847 void MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells(std::vector<int>& cells) throw(INTERP_KERNEL::Exception)
3849 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
3850 if(getMeshDimension()!=3)
3851 throw INTERP_KERNEL::Exception(msg);
3852 int spaceDim=getSpaceDimension();
3854 throw INTERP_KERNEL::Exception(msg);
3856 int nbOfCells=getNumberOfCells();
3857 int *conn=_nodal_connec->getPointer();
3858 const int *connI=_nodal_connec_index->getConstPointer();
3859 const double *coo=getCoords()->getConstPointer();
3860 double vec0[3],vec1[3];
3861 for(int i=0;i<nbOfCells;i++)
3863 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
3864 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
3866 INTERP_KERNEL::AutoPtr<int> tmp=new int[connI[i+1]-connI[i]-1];
3867 int nbOfNodes=cm.fillSonCellNodalConnectivity(0,conn+connI[i]+1,tmp);
3868 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(tmp,nbOfNodes,coo,vec0);
3869 const double *pt0=coo+3*conn[connI[i]+1];
3870 const double *pt1=coo+3*conn[connI[i]+nbOfNodes+1];
3871 vec1[0]=pt0[0]-pt1[0]; vec1[1]=pt0[1]-pt1[1]; vec1[2]=pt0[2]-pt1[2];
3872 double dot=vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2];
3876 std::copy(conn+connI[i]+1,conn+connI[i+1],(int *)tmp);
3877 for(int j=1;j<nbOfNodes;j++)
3879 conn[connI[i]+1+j]=tmp[nbOfNodes-j];
3880 conn[connI[i]+1+j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
3888 * This method is \b NOT const because it can modify 'this'.
3889 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
3890 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
3891 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
3892 * \b 1 for translation and rotation around point of 'mesh1D'.
3893 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
3895 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
3897 checkFullyDefined();
3898 mesh1D->checkFullyDefined();
3899 if(!mesh1D->isContiguous1D())
3900 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
3901 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
3902 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same dimension !");
3903 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3904 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
3905 if(mesh1D->getMeshDimension()!=1)
3906 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
3908 if(isPresenceOfQuadratic())
3910 if(mesh1D->isFullyQuadratic())
3913 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
3916 int oldNbOfNodes=getNumberOfNodes();
3917 DataArrayDouble *newCoords=0;
3922 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
3927 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
3931 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
3933 setCoords(newCoords);
3934 newCoords->decrRef();
3935 MEDCouplingUMesh *ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
3941 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
3942 * If it is not the case an exception will be thrown.
3943 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
3944 * intersection of plane defined by ('origin','vec').
3945 * This method has one in/out parameter : 'cut3DCurve'.
3946 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
3947 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
3948 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
3949 * This method will throw an exception if 'this' contains a non linear segment.
3951 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
3953 checkFullyDefined();
3954 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
3955 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
3956 int ncells=getNumberOfCells();
3957 int nnodes=getNumberOfNodes();
3958 double vec2[3],vec3[3],vec4[3];
3959 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3962 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
3963 const int *conn=_nodal_connec->getConstPointer();
3964 const int *connI=_nodal_connec_index->getConstPointer();
3965 const double *coo=_coords->getConstPointer();
3966 std::vector<double> addCoo;
3967 for(int i=0;i<ncells;i++)
3969 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
3971 if(cut3DCurve[i]==-2)
3973 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
3974 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];
3975 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
3976 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
3977 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
3979 const double *st2=coo+3*st;
3980 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
3981 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]));
3982 if(pos>eps && pos<1-eps)
3984 int nNode=((int)addCoo.size())/3;
3985 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
3986 addCoo.insert(addCoo.end(),vec4,vec4+3);
3987 cut3DCurve[i]=nnodes+nNode;
3993 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
3997 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
3998 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
3999 coo2->alloc(newNbOfNodes,3);
4000 double *tmp=coo2->getPointer();
4001 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4002 std::copy(addCoo.begin(),addCoo.end(),tmp);
4003 DataArrayDouble::SetArrayIn(coo2,_coords);
4008 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4009 * @param mesh1D is the input 1D mesh used for translation computation.
4010 * @return newCoords new coords filled by this method.
4012 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4014 int oldNbOfNodes=getNumberOfNodes();
4015 int nbOf1DCells=mesh1D->getNumberOfCells();
4016 int spaceDim=getSpaceDimension();
4017 DataArrayDouble *ret=DataArrayDouble::New();
4018 std::vector<bool> isQuads;
4019 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4020 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4021 double *retPtr=ret->getPointer();
4022 const double *coords=getCoords()->getConstPointer();
4023 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4025 std::vector<double> c;
4029 for(int i=0;i<nbOf1DCells;i++)
4032 mesh1D->getNodeIdsOfCell(i,v);
4034 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4035 mesh1D->getCoordinatesOfNode(v[0],c);
4036 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4037 for(int j=0;j<oldNbOfNodes;j++)
4038 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4042 mesh1D->getCoordinatesOfNode(v[1],c);
4043 mesh1D->getCoordinatesOfNode(v[0],c);
4044 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4045 for(int j=0;j<oldNbOfNodes;j++)
4046 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4049 ret->copyStringInfoFrom(*getCoords());
4054 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4055 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4056 * @return newCoords new coords filled by this method.
4058 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4060 if(mesh1D->getSpaceDimension()==2)
4061 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4062 if(mesh1D->getSpaceDimension()==3)
4063 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4064 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4068 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4069 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4070 * @return newCoords new coords filled by this method.
4072 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4076 int oldNbOfNodes=getNumberOfNodes();
4077 int nbOf1DCells=mesh1D->getNumberOfCells();
4079 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4080 DataArrayDouble *ret=DataArrayDouble::New();
4081 int nbOfLevsInVec=nbOf1DCells+1;
4082 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4083 double *retPtr=ret->getPointer();
4084 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4085 MEDCouplingUMesh *tmp=MEDCouplingUMesh::New();
4086 DataArrayDouble *tmp2=getCoords()->deepCpy();
4087 tmp->setCoords(tmp2);
4089 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4090 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4091 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4092 for(int i=1;i<nbOfLevsInVec;i++)
4094 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4095 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4096 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4097 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4098 tmp->translate(vec);
4099 double tmp3[2],radius,alpha,alpha0;
4100 const double *p0=i+1<nbOfLevsInVec?begin:third;
4101 const double *p1=i+1<nbOfLevsInVec?end:begin;
4102 const double *p2=i+1<nbOfLevsInVec?third:end;
4103 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4104 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]);
4105 double angle=acos(cosangle/(radius*radius));
4106 tmp->rotate(end,0,angle);
4107 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4114 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4115 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4116 * @return newCoords new coords filled by this method.
4118 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4121 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4122 int oldNbOfNodes=getNumberOfNodes();
4123 int nbOf1DCells=mesh1D->getNumberOfCells();
4125 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4126 DataArrayDouble *ret=DataArrayDouble::New();
4127 int nbOfLevsInVec=nbOf1DCells+1;
4128 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4129 double *retPtr=ret->getPointer();
4130 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4131 MEDCouplingUMesh *tmp=MEDCouplingUMesh::New();
4132 DataArrayDouble *tmp2=getCoords()->deepCpy();
4133 tmp->setCoords(tmp2);
4135 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4136 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4137 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4138 for(int i=1;i<nbOfLevsInVec;i++)
4140 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4141 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4142 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4143 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4144 tmp->translate(vec);
4145 double tmp3[2],radius,alpha,alpha0;
4146 const double *p0=i+1<nbOfLevsInVec?begin:third;
4147 const double *p1=i+1<nbOfLevsInVec?end:begin;
4148 const double *p2=i+1<nbOfLevsInVec?third:end;
4149 double vecPlane[3]={
4150 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4151 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4152 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4154 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4157 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4158 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4159 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4161 double c2=cos(asin(s2));
4163 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4164 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4165 {-vec2[1]*s2, vec2[0]*s2, c2}
4167 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]};
4168 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]};
4169 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]};
4170 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4171 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]);
4172 double angle=acos(cosangle/(radius*radius));
4173 tmp->rotate(end,vecPlane,angle);
4176 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4183 * This method is private because not easy to use for end user. This method is const contrary to
4184 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4185 * the coords sorted slice by slice.
4186 * @param isQuad specifies presence of quadratic cells.
4188 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4190 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4191 int nbOf2DCells=getNumberOfCells();
4192 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4193 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4194 const int *conn=_nodal_connec->getConstPointer();
4195 const int *connI=_nodal_connec_index->getConstPointer();
4196 DataArrayInt *newConn=DataArrayInt::New();
4197 DataArrayInt *newConnI=DataArrayInt::New();
4198 newConnI->alloc(nbOf3DCells+1,1);
4199 int *newConnIPtr=newConnI->getPointer();
4201 std::vector<int> newc;
4202 for(int j=0;j<nbOf2DCells;j++)
4204 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4205 *newConnIPtr++=(int)newc.size();
4207 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4208 int *newConnPtr=newConn->getPointer();
4209 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4210 newConnIPtr=newConnI->getPointer();
4211 for(int iz=0;iz<nbOf1DCells;iz++)
4214 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4215 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4217 int icell=(int)(iter-newc.begin());
4218 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4221 *newConnPtr=(*iter)+iz*deltaPerLev;
4226 *newConnPtr=(*iter);
4229 ret->setConnectivity(newConn,newConnI,true);
4231 newConnI->decrRef();
4232 ret->setCoords(getCoords());
4237 * This method returns if 'this' is constituted by only quadratic cells.
4239 bool MEDCouplingUMesh::isFullyQuadratic() const
4241 checkFullyDefined();
4243 int nbOfCells=getNumberOfCells();
4244 for(int i=0;i<nbOfCells && ret;i++)
4246 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4247 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4248 ret=cm.isQuadratic();
4254 * This method returns if there is at least one quadratic cell.
4256 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4258 checkFullyDefined();
4260 int nbOfCells=getNumberOfCells();
4261 for(int i=0;i<nbOfCells && !ret;i++)
4263 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4264 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4265 ret=cm.isQuadratic();
4271 * This method convert quadratic cells to linear cells if any was found.
4272 * If no such cells exists 'this' remains unchanged.
4274 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4276 checkFullyDefined();
4277 int nbOfCells=getNumberOfCells();
4279 for(int i=0;i<nbOfCells;i++)
4281 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4282 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4283 if(cm.isQuadratic())
4285 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4286 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4287 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4294 newConn->alloc(getMeshLength()-delta,1);
4295 newConnI->alloc(nbOfCells+1,1);
4296 const int *icptr=_nodal_connec->getConstPointer();
4297 const int *iciptr=_nodal_connec_index->getConstPointer();
4298 int *ocptr=newConn->getPointer();
4299 int *ociptr=newConnI->getPointer();
4302 for(int i=0;i<nbOfCells;i++,ociptr++)
4304 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4305 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4306 if(!cm.isQuadratic())
4308 _types.insert(type);
4309 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4310 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4314 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4315 _types.insert(typel);
4316 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4317 int newNbOfNodes=cml.getNumberOfNodes();
4318 *ocptr++=(int)typel;
4319 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4320 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4323 setConnectivity(newConn,newConnI,false);
4327 * This method tessallates 'this' so that the number of cells remains the same.
4328 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4329 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4331 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4332 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4334 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4336 checkFullyDefined();
4337 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4339 double epsa=fabs(eps);
4340 if(epsa<std::numeric_limits<double>::min())
4341 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 !");
4342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4347 revDesc1=0; revDescIndx1=0;
4348 mDesc->tessellate2DCurve(eps);
4349 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4350 setCoords(mDesc->getCoords());
4354 * This method tessallates 'this' so that the number of cells remains the same.
4355 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4356 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4358 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4359 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4361 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4363 checkFullyDefined();
4364 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4366 double epsa=fabs(eps);
4367 if(epsa<std::numeric_limits<double>::min())
4368 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 !");
4369 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4370 int nbCells=getNumberOfCells();
4371 int nbNodes=getNumberOfNodes();
4372 const int *conn=_nodal_connec->getConstPointer();
4373 const int *connI=_nodal_connec_index->getConstPointer();
4374 const double *coords=_coords->getConstPointer();
4375 std::vector<double> addCoo;
4376 std::vector<int> newConn;
4377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4378 newConnI->alloc(nbCells+1,1);
4379 int *newConnIPtr=newConnI->getPointer();
4382 INTERP_KERNEL::Node *tmp2[3];
4383 std::set<INTERP_KERNEL::NormalizedCellType> types;
4384 for(int i=0;i<nbCells;i++,newConnIPtr++)
4386 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4387 if(cm.isQuadratic())
4388 {//assert(connI[i+1]-connI[i]-1==3)
4389 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4390 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4391 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4392 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4393 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4396 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4397 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4399 newConnIPtr[1]=(int)newConn.size();
4403 types.insert(INTERP_KERNEL::NORM_SEG2);
4404 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4405 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4406 newConnIPtr[1]=newConnIPtr[0]+3;
4411 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4412 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4413 newConnIPtr[1]=newConnIPtr[0]+3;
4416 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4419 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4421 newConnArr->alloc((int)newConn.size(),1);
4422 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4423 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4424 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4425 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4426 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4427 std::copy(addCoo.begin(),addCoo.end(),work);
4428 DataArrayDouble::SetArrayIn(newCoords,_coords);
4433 * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4434 * This cut into simplex is performed following the parameter 'policy'. This method so typically increases the number of cells of this.
4435 * This method returns new2old array that specifies a each cell of 'this' after the call what was its id it comes.
4437 * The semantic of 'policy' parameter :
4438 * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4439 * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4441 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4446 return simplexizePol0();
4448 return simplexizePol1();
4450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be 0 or 1 !");
4454 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4456 checkFullyDefined();
4457 if(getMeshDimension()<1)
4458 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4459 int nbCells=getNumberOfCells();
4460 const int *conn=_nodal_connec->getConstPointer();
4461 const int *connI=_nodal_connec_index->getConstPointer();
4462 for(int i=0;i<nbCells;i++)
4464 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4472 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4474 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4476 if(getMeshDimension()!=2)
4477 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4478 int nbOfCells=getNumberOfCells();
4479 DataArrayInt *ret=DataArrayInt::New();
4480 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4481 ret->alloc(nbOfCells+nbOfCutCells,1);
4487 int *retPt=ret->getPointer();
4488 DataArrayInt *newConn=DataArrayInt::New();
4489 DataArrayInt *newConnI=DataArrayInt::New();
4490 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4491 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4492 int *pt=newConn->getPointer();
4493 int *ptI=newConnI->getPointer();
4495 const int *oldc=_nodal_connec->getConstPointer();
4496 const int *ci=_nodal_connec_index->getConstPointer();
4497 for(int i=0;i<nbOfCells;i++,ci++)
4499 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4501 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4502 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4503 pt=std::copy(tmp,tmp+8,pt);
4512 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4513 ptI[1]=ptI[0]+ci[1]-ci[0];
4518 _nodal_connec->decrRef();
4519 _nodal_connec=newConn;
4520 _nodal_connec_index->decrRef();
4521 _nodal_connec_index=newConnI;
4528 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4530 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4532 if(getMeshDimension()!=2)
4533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4534 int nbOfCells=getNumberOfCells();
4535 DataArrayInt *ret=DataArrayInt::New();
4536 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4537 ret->alloc(nbOfCells+nbOfCutCells,1);
4543 int *retPt=ret->getPointer();
4544 DataArrayInt *newConn=DataArrayInt::New();
4545 DataArrayInt *newConnI=DataArrayInt::New();
4546 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4547 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4548 int *pt=newConn->getPointer();
4549 int *ptI=newConnI->getPointer();
4551 const int *oldc=_nodal_connec->getConstPointer();
4552 const int *ci=_nodal_connec_index->getConstPointer();
4553 for(int i=0;i<nbOfCells;i++,ci++)
4555 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4557 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4558 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4559 pt=std::copy(tmp,tmp+8,pt);
4568 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4569 ptI[1]=ptI[0]+ci[1]-ci[0];
4574 _nodal_connec->decrRef();
4575 _nodal_connec=newConn;
4576 _nodal_connec_index->decrRef();
4577 _nodal_connec_index=newConnI;
4584 * This private method is used to subdivide edges of a mesh with meshdim==2. If 'this' has no a meshdim equal to 2 an exception will be thrown.
4585 * This method completly ignore coordinates.
4586 * @param nodeSubdived is the nodal connectivity of subdivision of edges
4587 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
4588 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4589 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4591 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
4593 checkFullyDefined();
4594 if(getMeshDimension()!=2)
4595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
4596 int nbOfCells=getNumberOfCells();
4597 int *connI=_nodal_connec_index->getPointer();
4599 for(int i=0;i<nbOfCells;i++,connI++)
4601 int offset=descIndex[i];
4602 int nbOfEdges=descIndex[i+1]-offset;
4604 bool ddirect=desc[offset+nbOfEdges-1]>0;
4605 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
4606 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
4607 for(int j=0;j<nbOfEdges;j++)
4609 bool direct=desc[offset+j]>0;
4610 int edgeId=std::abs(desc[offset+j])-1;
4611 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
4613 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
4614 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
4615 int ref2=direct?id1:id2;
4618 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4619 newConnLgth+=nbOfSubNodes-1;
4624 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
4625 throw INTERP_KERNEL::Exception(oss.str().c_str());
4630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
4633 newConnLgth++;//+1 is for cell type
4634 connI[1]=newConnLgth;
4637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4638 newConn->alloc(newConnLgth,1);
4639 int *work=newConn->getPointer();
4640 for(int i=0;i<nbOfCells;i++)
4642 *work++=INTERP_KERNEL::NORM_POLYGON;
4643 int offset=descIndex[i];
4644 int nbOfEdges=descIndex[i+1]-offset;
4645 for(int j=0;j<nbOfEdges;j++)
4647 bool direct=desc[offset+j]>0;
4648 int edgeId=std::abs(desc[offset+j])-1;
4650 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
4653 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4654 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
4655 work=std::copy(it,it+nbOfSubNodes-1,work);
4659 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
4662 _types.insert(INTERP_KERNEL::NORM_POLYGON);
4666 * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
4667 * nodal connectivity will be transform to a NORM_TRI3 cell.
4668 * This method works \b only \b on \b linear cells.
4669 * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
4670 * method could be usefull before calling this method in case of presence of several pair of nodes located on same position.
4671 * This method throws an exception if 'this' is not fully defined (connectivity).
4672 * This method throws an exception too if a "too" degenerated cell is detected. For example a NORM_TRI3 with 3 times the same node id.
4674 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
4676 checkFullyDefined();
4677 if(getMeshDimension()<=1)
4678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4679 int nbOfCells=getNumberOfCells();
4682 int initMeshLgth=getMeshLength();
4683 int *conn=_nodal_connec->getPointer();
4684 int *index=_nodal_connec_index->getPointer();
4688 for(int i=0;i<nbOfCells;i++)
4690 lgthOfCurCell=index[i+1]-posOfCurCell;
4691 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4693 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4694 conn+newPos+1,newLgth);
4695 conn[newPos]=newType;
4697 posOfCurCell=index[i+1];
4700 if(newPos!=initMeshLgth)
4701 _nodal_connec->reAlloc(newPos);
4706 * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
4707 * The 'vec' vector has to have a non nul norm.
4708 * If not 'cells' parameter will be appended with cellIds of incorrect cells.
4709 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
4711 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
4713 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4714 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4715 int nbOfCells=getNumberOfCells();
4716 const int *conn=_nodal_connec->getConstPointer();
4717 const int *connI=_nodal_connec_index->getConstPointer();
4718 const double *coordsPtr=_coords->getConstPointer();
4719 for(int i=0;i<nbOfCells;i++)
4721 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4722 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4724 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4725 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4732 * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
4733 * The 'vec' vector has to have a non nul norm.
4734 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
4736 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
4738 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4739 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4740 int nbOfCells=getNumberOfCells();
4741 int *conn=_nodal_connec->getPointer();
4742 const int *connI=_nodal_connec_index->getConstPointer();
4743 const double *coordsPtr=_coords->getConstPointer();
4744 bool isModified=false;
4745 for(int i=0;i<nbOfCells;i++)
4747 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4748 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4750 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4751 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4754 std::vector<int> tmp(connI[i+1]-connI[i]-2);
4755 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
4756 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
4761 _nodal_connec->declareAsNew();
4766 * This method checks that all polyhedrons cells have correctly oriented faces.
4767 * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
4768 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
4770 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
4772 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4773 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4774 int nbOfCells=getNumberOfCells();
4775 const int *conn=_nodal_connec->getConstPointer();
4776 const int *connI=_nodal_connec_index->getConstPointer();
4777 const double *coordsPtr=_coords->getConstPointer();
4778 for(int i=0;i<nbOfCells;i++)
4780 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4781 if(type==INTERP_KERNEL::NORM_POLYHED)
4783 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4790 * This method tries to orient correctly polhedrons cells.
4791 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
4793 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
4795 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4796 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4797 int nbOfCells=getNumberOfCells();
4798 int *conn=_nodal_connec->getPointer();
4799 const int *connI=_nodal_connec_index->getConstPointer();
4800 const double *coordsPtr=_coords->getConstPointer();
4801 bool isModified=false;
4802 for(int i=0;i<nbOfCells;i++)
4804 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4805 if(type==INTERP_KERNEL::NORM_POLYHED)
4806 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4808 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4813 _nodal_connec->declareAsNew();
4818 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
4819 * If it is not the case an exception will be thrown.
4820 * This method is fast because the first cell of 'this' is used to compute the plane.
4821 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
4822 * @param pos output of size at least 3 used to store a point owned of searched plane.
4824 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
4826 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4827 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
4828 const int *conn=_nodal_connec->getConstPointer();
4829 const int *connI=_nodal_connec_index->getConstPointer();
4830 const double *coordsPtr=_coords->getConstPointer();
4831 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
4832 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
4836 * The returned newly created field has to be managed by the caller.
4837 * This method returns a field on cell with no time lying on 'this'. The meshdimension and spacedimension of this are expected to be both in [2,3]. If not an exception will be thrown.
4838 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
4839 * If a cell has an another type an exception will be thrown.
4841 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
4844 int spaceDim=getSpaceDimension();
4845 int meshDim=getMeshDimension();
4846 if(spaceDim!=2 && spaceDim!=3)
4847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
4848 if(meshDim!=2 && meshDim!=3)
4849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
4850 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
4852 int nbOfCells=getNumberOfCells();
4853 DataArrayDouble *arr=DataArrayDouble::New();
4854 arr->alloc(nbOfCells,1);
4855 double *pt=arr->getPointer();
4856 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
4858 const int *conn=_nodal_connec->getConstPointer();
4859 const int *connI=_nodal_connec_index->getConstPointer();
4860 const double *coo=_coords->getConstPointer();
4862 for(int i=0;i<nbOfCells;i++,pt++)
4864 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
4867 case INTERP_KERNEL::NORM_TRI3:
4869 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
4870 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
4873 case INTERP_KERNEL::NORM_QUAD4:
4875 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4876 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
4879 case INTERP_KERNEL::NORM_TETRA4:
4881 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4882 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
4886 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
4888 conn+=connI[i+1]-connI[i];
4890 ret->setName("EdgeRatio");
4896 * The returned newly created field has to be managed by the caller.
4897 * This method returns a field on cell with no time lying on 'this'. The meshdimension and spacedimension of this are expected to be both in [2,3]. If not an exception will be thrown.
4898 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
4899 * If a cell has an another type an exception will be thrown.
4901 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
4904 int spaceDim=getSpaceDimension();
4905 int meshDim=getMeshDimension();
4906 if(spaceDim!=2 && spaceDim!=3)
4907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
4908 if(meshDim!=2 && meshDim!=3)
4909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
4910 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
4912 int nbOfCells=getNumberOfCells();
4913 DataArrayDouble *arr=DataArrayDouble::New();
4914 arr->alloc(nbOfCells,1);
4915 double *pt=arr->getPointer();
4916 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
4918 const int *conn=_nodal_connec->getConstPointer();
4919 const int *connI=_nodal_connec_index->getConstPointer();
4920 const double *coo=_coords->getConstPointer();
4922 for(int i=0;i<nbOfCells;i++,pt++)
4924 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
4927 case INTERP_KERNEL::NORM_TRI3:
4929 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
4930 *pt=INTERP_KERNEL::triAspectRatio(tmp);
4933 case INTERP_KERNEL::NORM_QUAD4:
4935 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4936 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
4939 case INTERP_KERNEL::NORM_TETRA4:
4941 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4942 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
4946 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
4948 conn+=connI[i+1]-connI[i];
4950 ret->setName("AspectRatio");
4956 * The returned newly created field has to be managed by the caller.
4957 * This method returns a field on cell with no time lying on 'this'. The meshdimension must be equal to 2 and the spacedimension must be equal to 3. If not an exception will be thrown.
4958 * This method for the moment only deals with NORM_QUAD4 geometric type.
4959 * If a cell has an another type an exception will be thrown.
4961 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
4964 int spaceDim=getSpaceDimension();
4965 int meshDim=getMeshDimension();
4967 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
4969 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
4970 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
4972 int nbOfCells=getNumberOfCells();
4973 DataArrayDouble *arr=DataArrayDouble::New();
4974 arr->alloc(nbOfCells,1);
4975 double *pt=arr->getPointer();
4976 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
4978 const int *conn=_nodal_connec->getConstPointer();
4979 const int *connI=_nodal_connec_index->getConstPointer();
4980 const double *coo=_coords->getConstPointer();
4982 for(int i=0;i<nbOfCells;i++,pt++)
4984 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
4987 case INTERP_KERNEL::NORM_QUAD4:
4989 FillInCompact3DMode(3,4,conn+1,coo,tmp);
4990 *pt=INTERP_KERNEL::quadWarp(tmp);
4994 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
4996 conn+=connI[i+1]-connI[i];
4998 ret->setName("Warp");
5004 * The returned newly created field has to be managed by the caller.
5005 * This method returns a field on cell with no time lying on 'this'. The meshdimension must be equal to 2 and the spacedimension must be equal to 3. If not an exception will be thrown.
5006 * This method for the moment only deals with NORM_QUAD4 geometric type.
5007 * If a cell has an another type an exception will be thrown.
5009 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5012 int spaceDim=getSpaceDimension();
5013 int meshDim=getMeshDimension();
5015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5017 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5018 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
5020 int nbOfCells=getNumberOfCells();
5021 DataArrayDouble *arr=DataArrayDouble::New();
5022 arr->alloc(nbOfCells,1);
5023 double *pt=arr->getPointer();
5024 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5026 const int *conn=_nodal_connec->getConstPointer();
5027 const int *connI=_nodal_connec_index->getConstPointer();
5028 const double *coo=_coords->getConstPointer();
5030 for(int i=0;i<nbOfCells;i++,pt++)
5032 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5035 case INTERP_KERNEL::NORM_QUAD4:
5037 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5038 *pt=INTERP_KERNEL::quadSkew(tmp);
5042 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5044 conn+=connI[i+1]-connI[i];
5046 ret->setName("Skew");
5052 * This method aggregate the bbox of each cell and put it into bbox parameter.
5053 * @param bbox out parameter of size 2*spacedim*nbOfcells.
5055 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5057 int spaceDim=getSpaceDimension();
5058 int nbOfCells=getNumberOfCells();
5059 bbox.resize(2*nbOfCells*spaceDim);
5060 for(int i=0;i<nbOfCells*spaceDim;i++)
5062 bbox[2*i]=std::numeric_limits<double>::max();
5063 bbox[2*i+1]=-std::numeric_limits<double>::max();
5065 const double *coordsPtr=_coords->getConstPointer();
5066 const int *conn=_nodal_connec->getConstPointer();
5067 const int *connI=_nodal_connec_index->getConstPointer();
5068 for(int i=0;i<nbOfCells;i++)
5070 int offset=connI[i]+1;
5071 int nbOfNodesForCell=connI[i+1]-offset;
5072 for(int j=0;j<nbOfNodesForCell;j++)
5074 int nodeId=conn[offset+j];
5076 for(int k=0;k<spaceDim;k++)
5078 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5079 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5087 namespace ParaMEDMEMImpl
5092 ConnReader(const int *c, int val):_conn(c),_val(val) { }
5093 bool operator() (const int& pos) { return _conn[pos]!=_val; }
5102 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5103 bool operator() (const int& pos) { return _conn[pos]==_val; }
5113 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5114 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5115 * 'this' is composed in cell types.
5116 * The returned array is of size 3*n where n is the number of different types present in 'this'.
5117 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
5118 * This parameter is kept only for compatibility with other methode listed above.
5120 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5122 checkConnectivityFullyDefined();
5123 const int *conn=_nodal_connec->getConstPointer();
5124 const int *connI=_nodal_connec_index->getConstPointer();
5125 const int *work=connI;
5126 int nbOfCells=getNumberOfCells();
5127 std::size_t n=getAllTypes().size();
5128 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5129 std::set<INTERP_KERNEL::NormalizedCellType> types;
5130 for(std::size_t i=0;work!=connI+nbOfCells;i++)
5132 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5133 if(types.find(typ)!=types.end())
5135 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5136 oss << " is not contiguous !";
5137 throw INTERP_KERNEL::Exception(oss.str().c_str());
5141 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5142 ret[3*i+1]=(int)std::distance(work,work2);
5149 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5150 * only for types cell, type node is not managed.
5151 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5152 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5153 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5154 * If 2 or more same geometric type is in 'code' and exception is thrown too.
5156 * This method firstly checks
5157 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5158 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5159 * an exception is thrown too.
5161 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5162 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
5163 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5165 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5168 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5169 std::size_t sz=code.size();
5172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5173 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5175 for(std::size_t i=0;i<n;i++)
5176 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5178 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5180 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5184 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5185 if(idsPerType.empty())
5187 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5188 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5189 if(types.size()==_types.size())
5192 DataArrayInt *ret=DataArrayInt::New();
5194 int *retPtr=ret->getPointer();
5195 const int *connI=_nodal_connec_index->getConstPointer();
5196 const int *conn=_nodal_connec->getConstPointer();
5197 int nbOfCells=getNumberOfCells();
5200 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5202 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5203 int offset=(int)std::distance(connI,i);
5204 if(code[3*kk+2]==-1)
5206 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5207 std::size_t pos2=std::distance(i,j);
5208 for(std::size_t k=0;k<pos2;k++)
5209 *retPtr++=(int)k+offset;
5214 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5215 retPtr,std::bind2nd(std::plus<int>(),offset));
5222 * This method makes the hypothesis that 'this' is sorted by type. If not an exception will be thrown.
5223 * This method is the opposite of MEDCouplingUMesh::checkTypeConsistencyAndContig method. Given a list of cells in 'profile' it returns a list of profiles sorted by geo type.
5224 * This method has 1 input 'profile' and 2 outputs 'code' and 'idsPerType'.
5225 * @throw if 'profile' has not exactly one component. It throws too, if 'profile' contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
5227 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5229 if(profile->getNumberOfComponents()!=1)
5230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5231 checkConnectivityFullyDefined();
5232 const int *conn=_nodal_connec->getConstPointer();
5233 const int *connI=_nodal_connec_index->getConstPointer();
5234 int nbOfCells=getNumberOfCells();
5235 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5236 std::vector<int> typeRangeVals(1);
5237 for(const int *i=connI;i!=connI+nbOfCells;)
5239 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5240 if(std::find(types.begin(),types.end(),curType)!=types.end())
5242 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5244 types.push_back(curType);
5245 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5246 typeRangeVals.push_back((int)std::distance(connI,i));
5249 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5250 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5255 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5256 code.resize(3*nbOfCastsFinal);
5257 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5258 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5259 for(int i=0;i<nbOfCastsFinal;i++)
5261 int castId=castsPresent->getIJ(i,0);
5262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5263 idsInPflPerType2.push_back(tmp3);
5264 code[3*i]=(int)types[castId];
5265 code[3*i+1]=tmp3->getNumberOfTuples();
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5267 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5269 tmp4->copyStringInfoFrom(*profile);
5270 idsPerType2.push_back(tmp4);
5271 code[3*i+2]=(int)idsPerType2.size()-1;
5278 std::size_t sz2=idsInPflPerType2.size();
5279 idsInPflPerType.resize(sz2);
5280 for(std::size_t i=0;i<sz2;i++)
5282 DataArrayInt *locDa=idsInPflPerType2[i];
5284 idsInPflPerType[i]=locDa;
5286 std::size_t sz=idsPerType2.size();
5287 idsPerType.resize(sz);
5288 for(std::size_t i=0;i<sz;i++)
5290 DataArrayInt *locDa=idsPerType2[i];
5292 idsPerType[i]=locDa;
5297 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5298 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5299 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5300 * 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.
5302 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5304 checkFullyDefined();
5305 nM1LevMesh->checkFullyDefined();
5306 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5307 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5308 if(_coords!=nM1LevMesh->getCoords())
5309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5312 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5313 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5314 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5315 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5316 tmp->setConnectivity(tmp0,tmp1);
5317 tmp->renumberCells(ret0->getConstPointer(),false);
5318 revDesc=tmp->getNodalConnectivity();
5319 revDescIndx=tmp->getNodalConnectivityIndex();
5320 DataArrayInt *ret=0;
5321 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5324 ret->getMaxValue(tmp2);
5326 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5327 throw INTERP_KERNEL::Exception(oss.str().c_str());
5332 revDescIndx->incrRef();
5335 meshnM1Old2New=ret0;
5340 * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5341 * It avoids to deal with renum in MEDLoader so it is usefull for MED file R/W with multi types.
5342 * This method returns a newly allocated array old2New.
5343 * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5345 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5347 checkConnectivityFullyDefined();
5348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5349 renumberCells(ret->getConstPointer(),false);
5355 * This methods checks that cells are sorted by their types.
5356 * This method makes asumption (no check) that connectivity is correctly set before calling.
5358 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5360 checkFullyDefined();
5361 const int *conn=_nodal_connec->getConstPointer();
5362 const int *connI=_nodal_connec_index->getConstPointer();
5363 int nbOfCells=getNumberOfCells();
5364 std::set<INTERP_KERNEL::NormalizedCellType> types;
5365 for(const int *i=connI;i!=connI+nbOfCells;)
5367 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5368 if(types.find(curType)!=types.end())
5370 types.insert(curType);
5371 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5377 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5378 * that the order is specified in array defined by [orderBg,orderEnd).
5380 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5382 checkFullyDefined();
5383 const int *conn=_nodal_connec->getConstPointer();
5384 const int *connI=_nodal_connec_index->getConstPointer();
5385 int nbOfCells=getNumberOfCells();
5387 for(const int *i=connI;i!=connI+nbOfCells;)
5389 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5390 int pos=(int)std::distance(orderBg,std::find(orderBg,orderEnd,curType));
5394 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5400 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5401 * 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
5402 * 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'.
5404 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
5406 checkConnectivityFullyDefined();
5407 int nbOfCells=getNumberOfCells();
5408 const int *conn=_nodal_connec->getConstPointer();
5409 const int *connI=_nodal_connec_index->getConstPointer();
5410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
5411 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
5412 tmpa->alloc(nbOfCells,1);
5413 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5414 tmpb->fillWithZero();
5415 int *tmp=tmpa->getPointer();
5416 int *tmp2=tmpb->getPointer();
5417 for(const int *i=connI;i!=connI+nbOfCells;i++)
5419 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5422 int pos=(int)std::distance(orderBg,where);
5424 tmp[std::distance(connI,i)]=pos;
5428 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5429 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5430 oss << " has a type " << cm.getRepr() << " not in input array of type !";
5431 throw INTERP_KERNEL::Exception(oss.str().c_str());
5441 * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in 'this'.
5442 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5443 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5444 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5446 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
5448 DataArrayInt *nbPerType=0;
5449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5450 nbPerType->decrRef();
5451 return tmpa->buildPermArrPerLevel();
5455 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
5456 * The number of cells remains unchanged after the call of this method.
5457 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5458 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5460 * @return the array giving the correspondance old to new.
5462 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5464 checkFullyDefined();
5466 const int *conn=_nodal_connec->getConstPointer();
5467 const int *connI=_nodal_connec_index->getConstPointer();
5468 int nbOfCells=getNumberOfCells();
5469 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5470 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5471 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5473 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5474 types.push_back(curType);
5475 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5477 DataArrayInt *ret=DataArrayInt::New();
5478 ret->alloc(nbOfCells,1);
5479 int *retPtr=ret->getPointer();
5480 std::fill(retPtr,retPtr+nbOfCells,-1);
5482 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5484 for(const int *i=connI;i!=connI+nbOfCells;i++)
5485 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5486 retPtr[std::distance(connI,i)]=newCellId++;
5488 renumberCells(retPtr,false);
5493 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
5494 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5495 * This method makes asumption that connectivity is correctly set before calling.
5497 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5499 checkFullyDefined();
5500 const int *conn=_nodal_connec->getConstPointer();
5501 const int *connI=_nodal_connec_index->getConstPointer();
5502 int nbOfCells=getNumberOfCells();
5503 std::vector<MEDCouplingUMesh *> ret;
5504 for(const int *i=connI;i!=connI+nbOfCells;)
5506 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5507 int beginCellId=(int)std::distance(connI,i);
5508 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5509 int endCellId=(int)std::distance(connI,i);
5510 int sz=endCellId-beginCellId;
5511 int *cells=new int[sz];
5512 for(int j=0;j<sz;j++)
5513 cells[j]=beginCellId+j;
5514 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
5522 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
5523 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
5524 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
5525 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
5526 * are not used here to avoid the build of big permutation array.
5528 * \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
5529 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5530 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
5531 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
5532 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
5533 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
5534 * \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
5535 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5537 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
5538 DataArrayInt *&szOfCellGrpOfSameType,
5539 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
5541 std::vector<const MEDCouplingUMesh *> ms2;
5542 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5545 (*it)->checkConnectivityFullyDefined();
5549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
5550 const DataArrayDouble *refCoo=ms2[0]->getCoords();
5551 int meshDim=ms2[0]->getMeshDimension();
5552 std::vector<const MEDCouplingUMesh *> m1ssm;
5553 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
5555 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
5556 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
5558 std::vector<int> ret1Data;
5559 std::vector<int> ret2Data;
5560 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
5562 if(meshDim!=(*it)->getMeshDimension())
5563 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
5564 if(refCoo!=(*it)->getCoords())
5565 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
5566 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
5567 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
5568 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
5569 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
5571 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
5572 m1ssmSingleAuto.push_back(singleCell);
5573 m1ssmSingle.push_back(singleCell);
5574 ret1Data.push_back((*it2)->getNumberOfCells()); ret2Data.push_back(rk);
5577 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc((int)m1ssmSingle.size(),1); std::copy(ret1Data.begin(),ret1Data.end(),ret1->getPointer());
5578 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=DataArrayInt::New(); ret2->alloc((int)m1ssmSingle.size(),1); std::copy(ret2Data.begin(),ret2Data.end(),ret2->getPointer());
5579 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
5580 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
5581 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
5582 for(std::size_t i=0;i<m1ssm.size();i++)
5583 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
5584 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
5585 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
5586 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
5592 * This method returns a newly created DataArrayInt instance.
5593 * This method retrieves cell ids in [begin,end) that have the type 'type'.
5595 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
5597 checkFullyDefined();
5599 const int *conn=_nodal_connec->getConstPointer();
5600 const int *connIndex=_nodal_connec_index->getConstPointer();
5601 for(const int *w=begin;w!=end;w++)
5602 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
5604 DataArrayInt *ret=DataArrayInt::New();
5605 ret->alloc((int)r.size(),1);
5606 std::copy(r.begin(),r.end(),ret->getPointer());
5611 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
5612 * are in [0:getNumberOfCells())
5614 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
5616 checkFullyDefined();
5617 const int *conn=_nodal_connec->getConstPointer();
5618 const int *connI=_nodal_connec_index->getConstPointer();
5619 int nbOfCells=getNumberOfCells();
5620 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
5621 int *tmp=new int[nbOfCells];
5622 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5625 for(const int *i=connI;i!=connI+nbOfCells;i++)
5626 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5627 tmp[std::distance(connI,i)]=j++;
5629 DataArrayInt *ret=DataArrayInt::New();
5630 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
5631 ret->copyStringInfoFrom(*da);
5632 int *retPtr=ret->getPointer();
5633 const int *daPtr=da->getConstPointer();
5634 int nbOfElems=da->getNbOfElems();
5635 for(int k=0;k<nbOfElems;k++)
5636 retPtr[k]=tmp[daPtr[k]];
5642 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
5643 * cells whose ids is in 'idsPerGeoType' array.
5644 * This method conserves coords and name of mesh.
5646 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
5648 std::vector<int> idsTokeep;
5649 int nbOfCells=getNumberOfCells();
5651 for(int i=0;i<nbOfCells;i++)
5652 if(getTypeOfCell(i)!=type)
5653 idsTokeep.push_back(i);
5656 if(std::find(idsPerGeoTypeBg,idsPerGeoTypeEnd,j)!=idsPerGeoTypeEnd)
5657 idsTokeep.push_back(i);
5660 MEDCouplingPointSet *ret=buildPartOfMySelf(&idsTokeep[0],&idsTokeep[0]+idsTokeep.size(),true);
5661 MEDCouplingUMesh *ret2=dynamic_cast<MEDCouplingUMesh *>(ret);
5667 ret2->copyTinyInfoFrom(this);
5672 * This method returns a vector of size 'this->getNumberOfCells()'.
5673 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
5675 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
5677 int ncell=getNumberOfCells();
5678 std::vector<bool> ret(ncell);
5679 const int *cI=getNodalConnectivityIndex()->getConstPointer();
5680 const int *c=getNodalConnectivity()->getConstPointer();
5681 for(int i=0;i<ncell;i++)
5683 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
5684 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5685 ret[i]=cm.isQuadratic();
5691 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
5693 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
5695 if(other->getType()!=UNSTRUCTURED)
5696 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
5697 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
5698 return MergeUMeshes(this,otherC);
5702 * Returns an array with this->getNumberOfCells() tuples and this->getSpaceDimension() dimension.
5703 * The false barycenter is computed that is to say barycenter of a cell is computed using average on each
5704 * components of coordinates of the cell.
5706 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
5708 DataArrayDouble *ret=DataArrayDouble::New();
5709 int spaceDim=getSpaceDimension();
5710 int nbOfCells=getNumberOfCells();
5711 ret->alloc(nbOfCells,spaceDim);
5712 ret->copyStringInfoFrom(*getCoords());
5713 double *ptToFill=ret->getPointer();
5714 double *tmp=new double[spaceDim];
5715 const int *nodal=_nodal_connec->getConstPointer();
5716 const int *nodalI=_nodal_connec_index->getConstPointer();
5717 const double *coor=_coords->getConstPointer();
5718 for(int i=0;i<nbOfCells;i++)
5720 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
5721 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
5729 * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
5730 * building explicitely it. The input part is defined by an array [begin,end). All ids contained in this array should be less than this->getNumberOfCells().
5731 * No check of that will be done !
5733 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
5735 DataArrayDouble *ret=DataArrayDouble::New();
5736 int spaceDim=getSpaceDimension();
5737 int nbOfTuple=(int)std::distance(begin,end);
5738 ret->alloc(nbOfTuple,spaceDim);
5739 double *ptToFill=ret->getPointer();
5740 double *tmp=new double[spaceDim];
5741 const int *nodal=_nodal_connec->getConstPointer();
5742 const int *nodalI=_nodal_connec_index->getConstPointer();
5743 const double *coor=_coords->getConstPointer();
5744 for(const int *w=begin;w!=end;w++)
5746 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
5747 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
5755 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
5758 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
5761 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
5762 da->checkAllocated();
5763 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
5765 int nbOfTuples=da->getNumberOfTuples();
5766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
5767 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
5768 c->alloc(2*nbOfTuples,1);
5769 cI->alloc(nbOfTuples+1,1);
5770 int *cp=c->getPointer();
5771 int *cip=cI->getPointer();
5773 for(int i=0;i<nbOfTuples;i++)
5775 *cp++=INTERP_KERNEL::NORM_POINT1;
5779 ret->setConnectivity(c,cI,true);
5785 * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
5786 * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
5788 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
5790 std::vector<const MEDCouplingUMesh *> tmp(2);
5791 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
5792 return MergeUMeshes(tmp);
5796 * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
5797 * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
5798 * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
5799 * cells in meshes in 'a' (in the same order too).
5801 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
5803 std::size_t sz=a.size();
5805 return MergeUMeshesLL(a);
5806 for(std::size_t ii=0;ii<sz;ii++)
5809 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
5810 throw INTERP_KERNEL::Exception(oss.str().c_str());
5812 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
5813 std::vector< const MEDCouplingUMesh * > aa(sz);
5815 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
5817 const MEDCouplingUMesh *cur=a[i];
5818 const DataArrayDouble *coo=cur->getCoords();
5820 spaceDim=coo->getNumberOfComponents();
5823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
5824 for(std::size_t i=0;i<sz;i++)
5826 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
5829 return MergeUMeshesLL(aa);
5834 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
5837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
5838 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
5839 int meshDim=(*it)->getMeshDimension();
5840 int nbOfCells=(*it)->getNumberOfCells();
5841 int meshLgth=(*it++)->getMeshLength();
5842 for(;it!=a.end();it++)
5844 if(meshDim!=(*it)->getMeshDimension())
5845 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
5846 nbOfCells+=(*it)->getNumberOfCells();
5847 meshLgth+=(*it)->getMeshLength();
5849 std::vector<const MEDCouplingPointSet *> aps(a.size());
5850 std::copy(a.begin(),a.end(),aps.begin());
5851 DataArrayDouble *pts=MergeNodesArray(aps);
5852 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
5853 ret->setCoords(pts);
5855 DataArrayInt *c=DataArrayInt::New();
5856 c->alloc(meshLgth,1);
5857 int *cPtr=c->getPointer();
5858 DataArrayInt *cI=DataArrayInt::New();
5859 cI->alloc(nbOfCells+1,1);
5860 int *cIPtr=cI->getPointer();
5864 for(it=a.begin();it!=a.end();it++)
5866 int curNbOfCell=(*it)->getNumberOfCells();
5867 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
5868 const int *curC=(*it)->_nodal_connec->getConstPointer();
5869 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
5870 for(int j=0;j<curNbOfCell;j++)
5872 const int *src=curC+curCI[j];
5874 for(;src!=curC+curCI[j+1];src++,cPtr++)
5882 offset+=curCI[curNbOfCell];
5883 offset2+=(*it)->getNumberOfNodes();
5886 ret->setConnectivity(c,cI,true);
5896 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
5897 * 'meshes' must be a non empty vector.
5899 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
5901 std::vector<const MEDCouplingUMesh *> tmp(2);
5902 tmp[0]=mesh1; tmp[1]=mesh2;
5903 return MergeUMeshesOnSameCoords(tmp);
5907 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
5908 * 'meshes' must be a non empty vector.
5910 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
5913 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
5914 for(std::size_t ii=0;ii<meshes.size();ii++)
5917 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
5918 throw INTERP_KERNEL::Exception(oss.str().c_str());
5920 const DataArrayDouble *coords=meshes.front()->getCoords();
5921 int meshDim=meshes.front()->getMeshDimension();
5922 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
5924 int meshIndexLgth=0;
5925 for(;iter!=meshes.end();iter++)
5927 if(coords!=(*iter)->getCoords())
5928 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
5929 if(meshDim!=(*iter)->getMeshDimension())
5930 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
5931 meshLgth+=(*iter)->getMeshLength();
5932 meshIndexLgth+=(*iter)->getNumberOfCells();
5934 DataArrayInt *nodal=DataArrayInt::New();
5935 nodal->alloc(meshLgth,1);
5936 int *nodalPtr=nodal->getPointer();
5937 DataArrayInt *nodalIndex=DataArrayInt::New();
5938 nodalIndex->alloc(meshIndexLgth+1,1);
5939 int *nodalIndexPtr=nodalIndex->getPointer();
5941 for(iter=meshes.begin();iter!=meshes.end();iter++)
5943 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
5944 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
5945 int nbOfCells=(*iter)->getNumberOfCells();
5946 int meshLgth2=(*iter)->getMeshLength();
5947 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
5948 if(iter!=meshes.begin())
5949 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
5951 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
5954 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
5955 ret->setName("merge");
5956 ret->setMeshDimension(meshDim);
5957 ret->setConnectivity(nodal,nodalIndex,true);
5958 ret->setCoords(coords);
5959 nodalIndex->decrRef();
5965 * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
5966 * If a same cell is detected in several meshes in 'meshes', this cell will appear only once in returned mesh (see ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for more details)
5968 * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
5969 * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
5970 * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
5971 * The arrays contained in 'corr' parameter are returned with refcounter set to one.
5972 * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
5973 * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
5974 * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
5976 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
5978 //All checks are delegated to MergeUMeshesOnSameCoords
5979 MEDCouplingUMesh *ret=MergeUMeshesOnSameCoords(meshes);
5980 DataArrayInt *o2n=ret->zipConnectivityTraducer(compType);
5981 corr.resize(meshes.size());
5982 std::size_t nbOfMeshes=meshes.size();
5984 const int *o2nPtr=o2n->getConstPointer();
5985 for(std::size_t i=0;i<nbOfMeshes;i++)
5987 DataArrayInt *tmp=DataArrayInt::New();
5988 int curNbOfCells=meshes[i]->getNumberOfCells();
5989 tmp->alloc(curNbOfCells,1);
5990 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
5991 offset+=curNbOfCells;
5992 tmp->setName(meshes[i]->getName());
6000 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6001 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6002 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6003 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6005 * This method performs nothing if size of \b meshes is in [0,1].
6006 * This method is particulary usefull in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6007 * coordinates DataArrayDouble instance.
6009 * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6011 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6013 std::size_t sz=meshes.size();
6016 std::vector< const DataArrayDouble * > coords(meshes.size());
6017 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6018 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6022 (*it)->checkConnectivityFullyDefined();
6023 const DataArrayDouble *coo=(*it)->getCoords();
6028 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6029 oss << " has no coordinate array defined !";
6030 throw INTERP_KERNEL::Exception(oss.str().c_str());
6035 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6036 oss << " is null !";
6037 throw INTERP_KERNEL::Exception(oss.str().c_str());
6040 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6041 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6042 int offset=(*it)->getNumberOfNodes();
6043 (*it++)->setCoords(res);
6044 for(;it!=meshes.end();it++)
6046 int oldNumberOfNodes=(*it)->getNumberOfNodes();
6047 (*it)->setCoords(res);
6048 (*it)->shiftNodeNumbersInConn(offset);
6049 offset+=oldNumberOfNodes;
6054 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6055 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6056 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6057 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6058 * If \b meshes share the same instance of DataArrayDouble as coordinates and that this instance is null, this method do nothing and no exception will be thrown.
6060 * This method performs nothing if size of \b meshes is empty.
6061 * This method is particulary usefull in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6062 * coordinates DataArrayDouble instance.
6064 * \param [in,out] meshes :vector containing no null instance of MEDCouplingUMesh sharing the same DataArrayDouble instance of coordinates, that in case of success of this method will be modified.
6065 * \param [in] eps is the distance in absolute (that should be positive !), so that 2 or more points within a distance of eps will be merged into a single point.
6067 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6071 std::set<const DataArrayDouble *> s;
6072 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6075 s.insert((*it)->getCoords());
6078 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 !";
6079 throw INTERP_KERNEL::Exception(oss.str().c_str());
6084 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 !";
6085 throw INTERP_KERNEL::Exception(oss.str().c_str());
6087 const DataArrayDouble *coo=*(s.begin());
6091 DataArrayInt *comm,*commI;
6092 coo->findCommonTuples(eps,-1,comm,commI);
6093 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6094 int oldNbOfNodes=coo->getNumberOfTuples();
6096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm,commI,newNbOfNodes);
6097 if(oldNbOfNodes==newNbOfNodes)
6099 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6100 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6102 (*it)->renumberNodesInConn(o2n->getConstPointer());
6103 (*it)->setCoords(newCoords);
6108 * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [connBg,connEnd) and returns its extruded cell by inserting the result at the end of ret.
6109 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6110 * @param isQuad specifies the policy of connectivity.
6111 * @ret in/out parameter in which the result will be append
6113 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6115 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6116 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6117 ret.push_back(cm.getExtrudedType());
6118 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6121 case INTERP_KERNEL::NORM_POINT1:
6123 ret.push_back(connBg[1]);
6124 ret.push_back(connBg[1]+nbOfNodesPerLev);
6127 case INTERP_KERNEL::NORM_SEG2:
6129 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6130 ret.insert(ret.end(),conn,conn+4);
6133 case INTERP_KERNEL::NORM_SEG3:
6135 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6136 ret.insert(ret.end(),conn,conn+8);
6139 case INTERP_KERNEL::NORM_QUAD4:
6141 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6142 ret.insert(ret.end(),conn,conn+8);
6145 case INTERP_KERNEL::NORM_TRI3:
6147 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6148 ret.insert(ret.end(),conn,conn+6);
6151 case INTERP_KERNEL::NORM_TRI6:
6153 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,
6154 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6155 ret.insert(ret.end(),conn,conn+15);
6158 case INTERP_KERNEL::NORM_QUAD8:
6161 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6162 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6163 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6165 ret.insert(ret.end(),conn,conn+20);
6168 case INTERP_KERNEL::NORM_POLYGON:
6170 std::back_insert_iterator< std::vector<int> > ii(ret);
6171 std::copy(connBg+1,connEnd,ii);
6173 std::reverse_iterator<const int *> rConnBg(connEnd);
6174 std::reverse_iterator<const int *> rConnEnd(connBg+1);
6175 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6176 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6177 for(std::size_t i=0;i<nbOfRadFaces;i++)
6180 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6181 std::copy(conn,conn+4,ii);
6186 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6191 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6193 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6195 double v[3]={0.,0.,0.};
6196 std::size_t sz=std::distance(begin,end);
6199 for(std::size_t i=0;i<sz;i++)
6201 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];
6202 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6203 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6205 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6209 * The polyhedron is specfied by its connectivity nodes in [begin,end).
6211 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6213 std::vector<std::pair<int,int> > edges;
6214 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6215 const int *bgFace=begin;
6216 for(std::size_t i=0;i<nbOfFaces;i++)
6218 const int *endFace=std::find(bgFace+1,end,-1);
6219 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6220 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6222 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6223 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6225 edges.push_back(p1);
6229 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6233 * 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)
6234 * 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
6237 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6238 * \param [in] coords the coordinates with nb of components exactly equal to 3
6239 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6240 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6241 * \param [out] the result is put at the end of the vector without any alteration of the data.
6243 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, std::vector<int>& res) throw(INTERP_KERNEL::Exception)
6245 int nbFaces=std::count(begin+1,end,-1)+1;
6246 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6247 double *vPtr=v->getPointer();
6248 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6249 double *pPtr=p->getPointer();
6250 const int *stFaceConn=begin+1;
6251 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6253 const int *endFaceConn=std::find(stFaceConn,end,-1);
6254 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
6255 stFaceConn=endFaceConn+1;
6257 pPtr=p->getPointer(); vPtr=v->getPointer();
6258 DataArrayInt *comm1=0,*commI1=0;
6259 v->findCommonTuples(eps,-1,comm1,commI1);
6260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6261 const int *comm1Ptr=comm1->getConstPointer();
6262 const int *commI1Ptr=commI1->getConstPointer();
6263 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6264 res.push_back((int)INTERP_KERNEL::NORM_POLYHED);
6266 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
6267 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
6268 mm->finishInsertingCells();
6270 for(int i=0;i<nbOfGrps1;i++)
6272 int vecId=comm1Ptr[commI1Ptr[i]];
6273 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6274 DataArrayInt *comm2=0,*commI2=0;
6275 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
6276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
6277 const int *comm2Ptr=comm2->getConstPointer();
6278 const int *commI2Ptr=commI2->getConstPointer();
6279 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
6280 for(int j=0;j<nbOfGrps2;j++)
6282 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
6284 res.insert(res.end(),begin,end);
6289 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
6290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
6291 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6292 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
6293 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
6294 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
6295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
6296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
6297 const int *idsNodePtr=idsNode->getConstPointer();
6298 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];
6299 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
6300 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
6301 if(std::abs(norm)>eps)
6303 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
6304 mm3->rotate(center,vec,angle);
6306 mm3->changeSpaceDimension(2);
6307 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
6308 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
6309 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
6310 int nbOfCells=mm4->getNumberOfCells();
6311 for(int k=0;k<nbOfCells;k++)
6314 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
6315 res.push_back(idsNodePtr[*work]);
6325 * 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
6326 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
6328 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
6329 * \param [in] coords coordinates expected to have 3 components.
6330 * \param [in] begin start of the nodal connectivity of the face.
6331 * \param [in] end end of the nodal connectivity (excluded) of the face.
6332 * \param [out] v the normalized vector of size 3
6333 * \param [out] p the pos of plane
6335 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
6337 std::size_t nbPoints=std::distance(begin,end);
6339 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
6342 bool refFound=false;
6343 for(;j<nbPoints-1 && !refFound;j++)
6345 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
6346 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
6347 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
6348 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
6352 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
6355 for(std::size_t i=j;i<nbPoints-1;i++)
6358 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
6359 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
6360 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
6361 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
6364 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
6365 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];
6366 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
6369 v[0]/=norm; v[1]/=norm; v[2]/=norm;
6370 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
6374 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
6378 * This method tries to obtain a well oriented polyhedron.
6379 * If the algorithm fails, an exception will be thrown.
6381 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
6383 std::vector<std::pair<int,int> > edges;
6384 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6386 std::vector<bool> isPerm(nbOfFaces);
6387 for(std::size_t i=0;i<nbOfFaces;i++)
6389 int *endFace=std::find(bgFace+1,end,-1);
6390 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6391 for(std::size_t l=0;l<nbOfEdgesInFace;l++)
6393 std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]);
6394 edges.push_back(p1);
6396 int *bgFace2=endFace+1;
6397 for(std::size_t k=i+1;k<nbOfFaces;k++)
6399 int *endFace2=std::find(bgFace2+1,end,-1);
6400 std::size_t nbOfEdgesInFace2=std::distance(bgFace2,endFace2);
6401 for(std::size_t j=0;j<nbOfEdgesInFace2;j++)
6403 std::pair<int,int> p2(bgFace2[j],bgFace2[(j+1)%nbOfEdgesInFace2]);
6404 if(std::find(edges.begin(),edges.end(),p2)!=edges.end())
6407 throw INTERP_KERNEL::Exception("Fail to repare polyhedron ! Polyedron looks bad !");
6408 std::vector<int> tmp(nbOfEdgesInFace2-1);
6409 std::copy(bgFace2+1,endFace2,tmp.rbegin());
6410 std::copy(tmp.begin(),tmp.end(),bgFace2+1);
6419 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
6420 {//not lucky ! The first face was not correctly oriented : reorient all faces...
6422 for(std::size_t i=0;i<nbOfFaces;i++)
6424 int *endFace=std::find(bgFace+1,end,-1);
6425 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6426 std::vector<int> tmp(nbOfEdgesInFace-1);
6427 std::copy(bgFace+1,endFace,tmp.rbegin());
6428 std::copy(tmp.begin(),tmp.end(),bgFace+1);
6435 * This method makes the assumption spacedimension == meshdimension == 2.
6436 * This method works only for linear cells.
6438 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
6440 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
6442 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
6443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
6444 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
6446 int nbOfNodesExpected=m->getNumberOfNodes();
6447 if(m->getNumberOfCells()!=nbOfNodesExpected)
6448 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
6449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
6450 const int *n2oPtr=n2o->getConstPointer();
6451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
6452 m->getReverseNodalConnectivity(revNodal,revNodalI);
6453 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
6454 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
6455 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
6456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
6457 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
6458 if(nbOfNodesExpected<1)
6459 { ret->incrRef(); return ret; }
6461 int prevNode=nodalPtr[nodalIPtr[0]+1];
6462 *work++=n2oPtr[prevNode];
6463 for(int i=1;i<nbOfNodesExpected;i++)
6465 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
6467 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
6468 conn.erase(prevNode);
6471 int curNode=*(conn.begin());
6472 *work++=n2oPtr[curNode];
6473 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
6474 shar.erase(prevCell);
6477 prevCell=*(shar.begin());
6481 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
6484 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
6487 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
6489 ret->incrRef(); return ret;
6493 * This method makes the assumption spacedimension == meshdimension == 3.
6494 * This method works only for linear cells.
6496 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
6498 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
6500 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6501 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
6502 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6503 const int *conn=m->getNodalConnectivity()->getConstPointer();
6504 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
6505 int nbOfCells=m->getNumberOfCells();
6506 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
6507 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
6509 { ret->incrRef(); return ret; }
6510 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
6511 for(int i=1;i<nbOfCells;i++)
6514 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
6521 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
6522 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
6524 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
6528 for(int i=0;i<nbOfNodesInCell;i++)
6529 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
6530 else if(spaceDim==2)
6532 for(int i=0;i<nbOfNodesInCell;i++)
6534 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
6539 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
6542 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
6544 int nbOfCells=getNumberOfCells();
6546 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
6547 static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,-1,23,-1,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,-1,-1,-1,25,42,-1,4};
6548 ofs << " <" << getVTKDataSetType() << ">\n";
6549 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
6550 ofs << " <PointData>\n" << pointData << std::endl;
6551 ofs << " </PointData>\n";
6552 ofs << " <CellData>\n" << cellData << std::endl;
6553 ofs << " </CellData>\n";
6554 ofs << " <Points>\n";
6555 if(getSpaceDimension()==3)
6556 _coords->writeVTK(ofs,8,"Points");
6559 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
6560 coo->writeVTK(ofs,8,"Points");
6562 ofs << " </Points>\n";
6563 ofs << " <Cells>\n";
6564 const int *cPtr=_nodal_connec->getConstPointer();
6565 const int *cIPtr=_nodal_connec_index->getConstPointer();
6566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
6567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
6568 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
6569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
6570 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
6571 int szFaceOffsets=0,szConn=0;
6572 for(int i=0;i<nbOfCells;i++,w1++,w2++,*w3++)
6575 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
6578 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
6579 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
6583 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
6584 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
6585 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
6586 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
6587 w4=std::copy(c.begin(),c.end(),w4);
6590 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
6591 types->writeVTK(ofs,8,"UInt8","types");
6592 offsets->writeVTK(ofs,8,"Int32","offsets");
6593 if(szFaceOffsets!=0)
6594 {//presence of Polyhedra
6595 connectivity->reAlloc(szConn);
6596 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
6597 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
6598 w1=faces->getPointer();
6599 for(int i=0;i<nbOfCells;i++)
6600 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
6602 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
6604 const int *w4=cPtr+cIPtr[i]+1,*w5=0;
6605 for(int j=0;j<nbFaces;j++)
6607 w5=std::find(w4,cPtr+cIPtr[i+1],-1);
6608 *w1++=(int)std::distance(w4,w5);
6609 w1=std::copy(w4,w5,w1);
6613 faces->writeVTK(ofs,8,"Int32","faces");
6615 connectivity->writeVTK(ofs,8,"Int32","connectivity");
6616 ofs << " </Cells>\n";
6617 ofs << " </Piece>\n";
6618 ofs << " </" << getVTKDataSetType() << ">\n";
6621 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
6623 return std::string("UnstructuredGrid");
6628 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
6630 m1->checkFullyDefined();
6631 m2->checkFullyDefined();
6632 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
6633 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
6634 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
6635 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
6636 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
6637 std::vector<double> addCoo,addCoordsQuadratic;
6638 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
6639 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
6640 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
6641 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
6642 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
6643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
6644 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
6645 std::vector< std::vector<int> > intersectEdge2;
6646 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
6647 subDiv2.clear(); dd5=0; dd6=0;
6648 std::vector<int> cr,crI;
6649 std::vector<int> cNb1,cNb2;
6650 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
6651 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
6653 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
6654 addCooDa->alloc((int)(addCoo.size())/2,2);
6655 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
6656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
6657 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
6658 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
6659 std::vector<const DataArrayDouble *> coordss(4);
6660 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
6661 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
6662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
6663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
6664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
6665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer()); cellNb1=c1;
6666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer()); cellNb2=c2;
6667 ret->setConnectivity(conn,connI,true);
6668 ret->setCoords(coo);
6669 ret->incrRef(); c1->incrRef(); c2->incrRef();
6675 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
6676 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
6677 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
6678 const std::vector<double>& addCoords,
6679 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
6681 static const int SPACEDIM=2;
6682 std::vector<double> bbox1,bbox2;
6683 const double *coo1=m1->getCoords()->getConstPointer();
6684 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
6685 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
6686 int offset1=m1->getNumberOfNodes();
6687 const double *coo2=m2->getCoords()->getConstPointer();
6688 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
6689 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
6690 int offset2=offset1+m2->getNumberOfNodes();
6691 int offset3=offset2+((int)addCoords.size())/2;
6692 m1->getBoundingBoxForBBTree(bbox1);
6693 m2->getBoundingBoxForBBTree(bbox2);
6694 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
6695 int ncell1=m1->getNumberOfCells();
6697 for(int i=0;i<ncell1;i++)
6699 std::vector<int> candidates2;
6700 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
6701 std::map<INTERP_KERNEL::Node *,int> mapp;
6702 std::map<int,INTERP_KERNEL::Node *> mappRev;
6703 INTERP_KERNEL::QuadraticPolygon pol1;
6704 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
6705 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6706 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
6707 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
6708 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
6709 std::vector<int> crTmp,crITmp;
6710 crITmp.push_back(crI.back());
6711 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++)
6713 INTERP_KERNEL::QuadraticPolygon pol2;
6714 pol1.initLocations();
6715 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
6716 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
6717 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
6718 pol2.buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
6719 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
6720 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
6721 pol1.buildPartitionsAbs(pol2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
6725 cr.insert(cr.end(),crTmp.begin(),crTmp.end());
6726 crI.insert(crI.end(),crITmp.begin()+1,crITmp.end());
6728 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
6729 (*it).second->decrRef();
6734 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
6737 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
6738 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
6739 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
6740 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
6741 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
6743 static const int SPACEDIM=2;
6744 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
6745 desc2=DataArrayInt::New();
6746 descIndx2=DataArrayInt::New();
6747 revDesc2=DataArrayInt::New();
6748 revDescIndx2=DataArrayInt::New();
6749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
6750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
6751 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
6752 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
6753 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
6754 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
6755 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
6756 std::vector<double> bbox1,bbox2;
6757 m1Desc->getBoundingBoxForBBTree(bbox1);
6758 m2Desc->getBoundingBoxForBBTree(bbox2);
6759 int ncell1=m1Desc->getNumberOfCells();
6760 int ncell2=m2Desc->getNumberOfCells();
6761 intersectEdge1.resize(ncell1);
6762 colinear2.resize(ncell2);
6763 subDiv2.resize(ncell2);
6764 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
6765 std::vector<int> candidates1(1);
6766 int offset1=m1->getNumberOfNodes();
6767 int offset2=offset1+m2->getNumberOfNodes();
6768 for(int i=0;i<ncell1;i++)
6770 std::vector<int> candidates2;
6771 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
6772 if(!candidates2.empty())
6774 std::map<INTERP_KERNEL::Node *,int> map1,map2;
6775 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
6777 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
6778 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
6783 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
6785 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
6786 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
6790 * This method performs the 2nd step of Partition of 2D mesh.
6791 * This method has 4 inputs :
6792 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
6793 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
6794 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
6795 * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
6796 * @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. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
6797 * @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.
6798 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
6800 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
6802 int offset1=m1->getNumberOfNodes();
6803 int ncell=m2->getNumberOfCells();
6804 const int *c=m2->getNodalConnectivity()->getConstPointer();
6805 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
6806 const double *coo=m2->getCoords()->getConstPointer();
6807 const double *cooBis=m1->getCoords()->getConstPointer();
6808 int offset2=offset1+m2->getNumberOfNodes();
6809 intersectEdge.resize(ncell);
6810 for(int i=0;i<ncell;i++,cI++)
6812 const std::vector<int>& divs=subDiv[i];
6813 int nnode=cI[1]-cI[0]-1;
6814 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
6815 std::map<INTERP_KERNEL::Node *, int> mapp22;
6816 for(int j=0;j<nnode;j++)
6818 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
6819 int nnid=c[(*cI)+j+1];
6820 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
6821 mapp22[nn]=nnid+offset1;
6823 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
6824 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
6825 ((*it).second.first)->decrRef();
6826 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
6827 std::map<INTERP_KERNEL::Node *,int> mapp3;
6828 for(std::size_t j=0;j<divs.size();j++)
6831 INTERP_KERNEL::Node *tmp=0;
6833 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
6835 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
6837 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
6841 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
6842 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
6849 * 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).
6850 * 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
6851 * with a plane. The result will be put in 'cut3DSuf' out parameter.
6852 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
6853 * @param nodesOnPlane, returns all the nodes that are on the plane.
6854 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
6855 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
6856 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
6857 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
6858 * @param desc is the descending connectivity 3DSurf->3DCurve
6859 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
6860 * @param cut3DSuf input/output param.
6862 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
6863 const int *nodal3DCurve, const int *nodalIndx3DCurve,
6864 const int *desc, const int *descIndx,
6865 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
6867 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
6868 int nbOf3DSurfCell=(int)cut3DSurf.size();
6869 for(int i=0;i<nbOf3DSurfCell;i++)
6871 std::vector<int> res;
6872 int offset=descIndx[i];
6873 int nbOfSeg=descIndx[i+1]-offset;
6874 for(int j=0;j<nbOfSeg;j++)
6876 int edgeId=desc[offset+j];
6877 int status=cut3DCurve[edgeId];
6881 res.push_back(status);
6884 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
6885 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
6893 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
6899 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
6900 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
6903 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
6907 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
6912 {// case when plane is on a multi colinear edge of a polyhedron
6913 if((int)res.size()==2*nbOfSeg)
6915 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
6918 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
6925 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
6926 * 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).
6927 * 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
6928 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
6929 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
6930 * @param desc is the descending connectivity 3D->3DSurf
6931 * @param descIndx is the descending connectivity index 3D->3DSurf
6933 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
6934 const int *desc, const int *descIndx,
6935 std::vector<int>& nodalRes, std::vector<int>& nodalResIndx, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
6937 checkFullyDefined();
6938 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
6940 const int *nodal3D=_nodal_connec->getConstPointer();
6941 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
6942 int nbOfCells=getNumberOfCells();
6943 for(int i=0;i<nbOfCells;i++)
6945 std::map<int, std::set<int> > m;
6946 int offset=descIndx[i];
6947 int nbOfFaces=descIndx[i+1]-offset;
6950 for(int j=0;j<nbOfFaces;j++)
6952 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
6953 if(p.first!=-1 && p.second!=-1)
6957 start=p.first; end=p.second;
6958 m[p.first].insert(p.second);
6959 m[p.second].insert(p.first);
6963 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
6964 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
6965 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6966 INTERP_KERNEL::NormalizedCellType cmsId;
6967 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
6968 start=tmp[0]; end=tmp[nbOfNodesSon-1];
6969 for(unsigned k=0;k<nbOfNodesSon;k++)
6971 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
6972 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
6979 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
6983 std::map<int, std::set<int> >::const_iterator it=m.find(start);
6984 const std::set<int>& s=(*it).second;
6985 std::set<int> s2; s2.insert(prev);
6987 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
6990 int val=*s3.begin();
6991 conn.push_back(start);
6998 conn.push_back(end);
7001 nodalRes.insert(nodalRes.end(),conn.begin(),conn.end());
7002 nodalResIndx.push_back((int)nodalRes.size());
7003 cellIds.push_back(i);
7009 * 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
7010 * 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
7011 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7012 * 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
7013 * 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.
7015 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7017 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, std::vector<int>& nodalConnecOut) throw(INTERP_KERNEL::Exception)
7019 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7022 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7023 if(cm.getDimension()==2)
7025 const int *node=nodalConnBg+1;
7026 int startNode=*node++;
7027 double refX=coords[2*startNode];
7028 for(;node!=nodalConnEnd;node++)
7030 if(coords[2*(*node)]<refX)
7033 refX=coords[2*startNode];
7036 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7040 double angle0=-M_PI/2;
7046 while(nextNode!=startNode)
7050 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7052 if(*node!=tmpOut.back() && *node!=prevNode)
7054 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7055 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7060 res=angle0-angleM+2.*M_PI;
7069 if(nextNode!=startNode)
7071 angle0=angleNext-M_PI;
7074 prevNode=tmpOut.back();
7075 tmpOut.push_back(nextNode);
7078 std::vector<int> tmp3(2*(sz-1));
7079 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7080 std::copy(nodalConnBg+1,nodalConnEnd,it);
7081 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7083 nodalConnecOut.insert(nodalConnecOut.end(),nodalConnBg,nodalConnEnd);
7086 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7088 nodalConnecOut.insert(nodalConnecOut.end(),nodalConnBg,nodalConnEnd);
7093 nodalConnecOut.push_back((int)INTERP_KERNEL::NORM_POLYGON);
7094 nodalConnecOut.insert(nodalConnecOut.end(),tmpOut.begin(),tmpOut.end());
7100 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7104 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7105 * 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.
7107 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7108 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7109 * \param [in,out] arr array in which the remove operation will be done.
7110 * \param [in,out] arrIndx array in the remove operation will modify
7111 * \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])
7112 * \return true if \b arr and \b arrIndx have been modified, false if not.
7114 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7116 if(!arrIndx || !arr)
7117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7118 if(offsetForRemoval<0)
7119 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7120 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7121 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7122 int *arrIPtr=arrIndx->getPointer();
7125 const int *arrPtr=arr->getConstPointer();
7126 std::vector<int> arrOut;
7127 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7129 if(*arrIPtr-previousArrI>offsetForRemoval)
7131 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7133 if(s.find(*work)==s.end())
7134 arrOut.push_back(*work);
7137 previousArrI=*arrIPtr;
7138 *arrIPtr=(int)arrOut.size();
7140 if(arr->getNumberOfTuples()==(int)arrOut.size())
7142 arr->alloc((int)arrOut.size(),1);
7143 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7148 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7149 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7150 * The selection of extraction is done standardly in new2old format.
7151 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
7153 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7154 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7155 * \param [in] arrIn arr origin array from which the extraction will be done.
7156 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7157 * \param [out] arrOut the resulting array
7158 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7160 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7161 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7163 if(!arrIn || !arrIndxIn)
7164 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7165 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7166 const int *arrInPtr=arrIn->getConstPointer();
7167 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7168 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7169 int maxSizeOfArr=arrIn->getNumberOfTuples();
7170 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7172 arrIo->alloc((int)(sz+1),1);
7173 const int *idsIt=idsOfSelectBg;
7174 int *work=arrIo->getPointer();
7177 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7179 if(*idsIt>=0 && *idsIt<nbOfGrps)
7180 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7183 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7184 throw INTERP_KERNEL::Exception(oss.str().c_str());
7190 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7191 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7192 throw INTERP_KERNEL::Exception(oss.str().c_str());
7195 arro->alloc(lgth,1);
7196 work=arro->getPointer();
7197 idsIt=idsOfSelectBg;
7198 for(std::size_t i=0;i<sz;i++,idsIt++)
7200 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7201 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7204 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7205 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7206 throw INTERP_KERNEL::Exception(oss.str().c_str());
7216 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7217 * 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
7218 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7219 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7221 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7222 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7223 * \param [in] arrIn arr origin array from which the extraction will be done.
7224 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7225 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7226 * \param [in] srcArrIndex index array of \b srcArr
7227 * \param [out] arrOut the resulting array
7228 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7230 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7232 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7233 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7234 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7236 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7237 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7240 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7241 std::vector<bool> v(nbOfTuples,true);
7243 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7244 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7245 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7247 if(*it>=0 && *it<nbOfTuples)
7250 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7254 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7255 throw INTERP_KERNEL::Exception(oss.str().c_str());
7258 srcArrIndexPtr=srcArrIndex->getConstPointer();
7259 arrIo->alloc(nbOfTuples+1,1);
7260 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7261 const int *arrInPtr=arrIn->getConstPointer();
7262 const int *srcArrPtr=srcArr->getConstPointer();
7263 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7264 int *arroPtr=arro->getPointer();
7265 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7269 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7270 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7274 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7275 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7276 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7279 arrOut=arro; arro->incrRef();
7280 arrIndexOut=arrIo; arrIo->incrRef();
7284 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7285 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7287 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7288 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7289 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7290 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7291 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7292 * \param [in] srcArrIndex index array of \b srcArr
7294 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7296 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7297 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7299 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7300 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7301 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7302 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7303 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7304 int *arrInOutPtr=arrInOut->getPointer();
7305 const int *srcArrPtr=srcArr->getConstPointer();
7306 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7308 if(*it>=0 && *it<nbOfTuples)
7310 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7311 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7314 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] !";
7315 throw INTERP_KERNEL::Exception(oss.str().c_str());
7320 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7321 throw INTERP_KERNEL::Exception(oss.str().c_str());
7327 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7328 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7329 * 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]].
7330 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7331 * A negative value in \b arrIn means that it is ignored.
7332 * This method is usefull 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.
7334 * \param [in] arrIn arr origin array from which the extraction will be done.
7335 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7336 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7338 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
7340 if(!arrIn || !arrIndxIn)
7341 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7342 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7345 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
7348 const int *arrInPtr=arrIn->getConstPointer();
7349 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7350 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7351 arro->alloc(nbOfTuples,1);
7352 arro->fillWithValue(-1);
7353 int *arroPtr=arro->getPointer();
7354 std::set<int> s; s.insert(0);
7358 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7360 for(const int *work=arrInPtr+arrIndxPtr[*it];work!=arrInPtr+arrIndxPtr[*it+1];work++)
7362 if(*work>=0 && arroPtr[*work]<0)
7371 return arro->getIdsEqual(1);
7375 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7376 * 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
7377 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7378 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7380 * \param [in] start begin of set of ids of the input extraction (included)
7381 * \param [in] end end of set of ids of the input extraction (excluded)
7382 * \param [in] step step of the set of ids in range mode.
7383 * \param [in] arrIn arr origin array from which the extraction will be done.
7384 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7385 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7386 * \param [in] srcArrIndex index array of \b srcArr
7387 * \param [out] arrOut the resulting array
7388 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7390 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
7392 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7393 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7394 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7396 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7397 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
7398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7400 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7402 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7403 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7404 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
7406 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7408 if(it>=0 && it<nbOfTuples)
7409 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7412 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7413 throw INTERP_KERNEL::Exception(oss.str().c_str());
7416 srcArrIndexPtr=srcArrIndex->getConstPointer();
7417 arrIo->alloc(nbOfTuples+1,1);
7418 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7419 const int *arrInPtr=arrIn->getConstPointer();
7420 const int *srcArrPtr=srcArr->getConstPointer();
7421 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7422 int *arroPtr=arro->getPointer();
7423 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7425 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
7428 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7429 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7433 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7434 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7437 arrOut=arro; arro->incrRef();
7438 arrIndexOut=arrIo; arrIo->incrRef();
7442 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7443 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7445 * \param [in] start begin of set of ids of the input extraction (included)
7446 * \param [in] end end of set of ids of the input extraction (excluded)
7447 * \param [in] step step of the set of ids in range mode.
7448 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7449 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7450 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7451 * \param [in] srcArrIndex index array of \b srcArr
7453 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7455 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7456 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7458 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7459 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
7460 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7461 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7462 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7463 int *arrInOutPtr=arrInOut->getPointer();
7464 const int *srcArrPtr=srcArr->getConstPointer();
7465 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
7467 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7469 if(it>=0 && it<nbOfTuples)
7471 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
7472 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
7475 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7476 throw INTERP_KERNEL::Exception(oss.str().c_str());
7481 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7482 throw INTERP_KERNEL::Exception(oss.str().c_str());
7488 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
7489 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
7490 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
7491 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
7492 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
7494 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
7496 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
7498 checkFullyDefined();
7499 int mdim=getMeshDimension();
7500 int spaceDim=getSpaceDimension();
7502 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
7503 int nbCells=getNumberOfCells();
7504 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
7505 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
7506 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
7507 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
7508 ret->setCoords(getCoords());
7509 ret->allocateCells((int)partition.size());
7511 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
7513 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
7514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
7518 cell=tmp->buildUnionOf2DMesh();
7521 cell=tmp->buildUnionOf3DMesh();
7524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
7527 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
7530 ret->finishInsertingCells();
7531 ret->incrRef(); return ret;
7535 * This method partitions \b this into contiguous zone.
7536 * This method only needs a well defined connectivity. Coordinates are not considered here.
7537 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
7539 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
7541 int nbOfCellsCur=getNumberOfCells();
7542 DataArrayInt *neigh=0,*neighI=0;
7543 computeNeighborsOfCells(neigh,neighI);
7544 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
7545 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
7546 std::vector<DataArrayInt *> ret;
7547 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
7548 while(nbOfCellsCur>0)
7550 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
7551 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
7552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
7553 ret2.push_back(tmp2); ret.push_back(tmp2);
7554 nbOfCellsCur=tmp3->getNumberOfTuples();
7557 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
7558 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
7561 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
7562 neighAuto->transformWithIndArr(renum->begin(),renum->end());
7565 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
7571 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
7572 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
7574 * \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.
7575 * \return a newly allocated DataArrayInt to be managed by the caller.
7576 * \throw In case of \a code has not the right format (typically of size 3*n)
7578 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
7580 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
7581 std::size_t nb=code.size()/3;
7582 if(code.size()%3!=0)
7583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
7584 ret->alloc((int)nb,2);
7585 int *retPtr=ret->getPointer();
7586 for(std::size_t i=0;i<nb;i++,retPtr+=2)
7588 retPtr[0]=code[3*i+2];
7589 retPtr[1]=code[3*i+2]+code[3*i+1];
7595 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
7596 _own_cell(true),_cell_id(-1),_nb_cell(0)
7601 _nb_cell=mesh->getNumberOfCells();
7605 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
7613 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
7614 _own_cell(false),_cell_id(bg-1),
7621 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
7624 if(_cell_id<_nb_cell)
7633 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
7639 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
7641 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
7644 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
7650 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
7658 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
7664 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
7669 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
7674 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
7676 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
7679 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
7684 _nb_cell=mesh->getNumberOfCells();
7688 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
7695 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
7697 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
7698 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
7699 if(_cell_id<_nb_cell)
7701 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
7702 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
7703 int startId=_cell_id;
7704 _cell_id+=nbOfElems;
7705 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
7711 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
7715 _conn=mesh->getNodalConnectivity()->getPointer();
7716 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
7720 void MEDCouplingUMeshCell::next()
7722 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
7727 _conn_lgth=_conn_indx[1]-_conn_indx[0];
7730 std::string MEDCouplingUMeshCell::repr() const
7732 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
7734 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
7736 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
7740 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
7743 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
7745 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
7746 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
7748 return INTERP_KERNEL::NORM_ERROR;
7751 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
7754 if(_conn_lgth!=NOTICABLE_FIRST_VAL)