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
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
29 #include "SplitterTetra.hxx"
30 #include "DirectedBoundingBox.hxx"
31 #include "InterpKernelMeshQuality.hxx"
32 #include "InterpKernelCellSimplify.hxx"
33 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
34 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
35 #include "InterpKernelAutoPtr.hxx"
36 #include "InterpKernelGeo2DNode.hxx"
37 #include "InterpKernelGeo2DEdgeLin.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
48 using namespace ParaMEDMEM;
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 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
81 ret+=_nodal_connec->getHeapMemorySize();
82 if(_nodal_connec_index)
83 ret+=_nodal_connec_index->getHeapMemorySize();
84 return MEDCouplingPointSet::getHeapMemorySize()+ret;
87 void MEDCouplingUMesh::updateTime() const
89 MEDCouplingPointSet::updateTime();
92 updateTimeWith(*_nodal_connec);
94 if(_nodal_connec_index)
96 updateTimeWith(*_nodal_connec_index);
100 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
105 * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity.
106 * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be
107 * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check
108 * that all is in order in 'this'.
110 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
113 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
115 MEDCouplingPointSet::checkCoherency();
116 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
118 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
120 std::ostringstream message;
121 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
122 throw INTERP_KERNEL::Exception(message.str().c_str());
127 if(_nodal_connec->getNumberOfComponents()!=1)
128 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
129 if(_nodal_connec->getInfoOnComponent(0)!="")
130 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
132 if(_nodal_connec_index)
134 if(_nodal_connec_index->getNumberOfComponents()!=1)
135 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
136 if(_nodal_connec_index->getInfoOnComponent(0)!="")
137 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
142 * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does.
143 * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids.
144 * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2.
146 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
151 int meshDim=getMeshDimension();
152 int nbOfNodes=getNumberOfNodes();
153 int nbOfCells=getNumberOfCells();
154 const int *ptr=_nodal_connec->getConstPointer();
155 const int *ptrI=_nodal_connec_index->getConstPointer();
156 for(int i=0;i<nbOfCells;i++)
158 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
159 if((int)cm.getDimension()!=meshDim)
161 std::ostringstream oss;
162 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
163 throw INTERP_KERNEL::Exception(oss.str().c_str());
165 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
167 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
169 std::ostringstream oss;
170 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
171 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
172 throw INTERP_KERNEL::Exception(oss.str().c_str());
174 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
179 if(nodeId>=nbOfNodes)
181 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
182 throw INTERP_KERNEL::Exception(oss.str().c_str());
187 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
188 throw INTERP_KERNEL::Exception(oss.str().c_str());
192 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
194 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
195 throw INTERP_KERNEL::Exception(oss.str().c_str());
202 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
204 checkCoherency1(eps);
207 void MEDCouplingUMesh::setMeshDimension(int meshDim)
209 if(meshDim<-1 || meshDim>3)
210 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
215 void MEDCouplingUMesh::allocateCells(int nbOfCells)
217 if(_nodal_connec_index)
219 _nodal_connec_index->decrRef();
223 _nodal_connec->decrRef();
225 _nodal_connec_index=DataArrayInt::New();
226 _nodal_connec_index->reserve(nbOfCells+1);
227 _nodal_connec_index->pushBackSilent(0);
228 _nodal_connec=DataArrayInt::New();
229 _nodal_connec->reserve(2*nbOfCells);
235 * Appends a cell in connectivity array.
236 * @param type type of cell to add.
237 * @param size number of nodes constituting this cell.
238 * @param nodalConnOfCell the connectivity of the cell to add.
240 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
242 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
243 if(_nodal_connec_index==0)
244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
245 if((int)cm.getDimension()==_mesh_dim)
248 if(size!=(int)cm.getNumberOfNodes())
250 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
251 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 int idx=_nodal_connec_index->back();
256 _nodal_connec_index->pushBackSilent(val);
257 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
262 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
263 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
264 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
270 * Method to be called to cloture the insertion of cells using this->insertNextCell.
272 void MEDCouplingUMesh::finishInsertingCells()
274 _nodal_connec->pack();
275 _nodal_connec_index->pack();
276 _nodal_connec->declareAsNew();
277 _nodal_connec_index->declareAsNew();
282 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
283 * Useful for python users.
285 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
287 return new MEDCouplingUMeshCellIterator(this);
291 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
292 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
293 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
294 * Useful for python users.
296 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
298 if(!checkConsecutiveCellTypes())
299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
300 return new MEDCouplingUMeshCellByTypeEntry(this);
303 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
309 * This method is a method that compares 'this' and 'other'.
310 * This method compares \b all attributes, even names and component names.
312 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
316 std::ostringstream oss; oss.precision(15);
317 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
320 reason="mesh given in input is not castable in MEDCouplingUMesh !";
323 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
325 if(_mesh_dim!=otherC->_mesh_dim)
327 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
331 if(_types!=otherC->_types)
333 oss << "umesh geometric type mismatch :\nThis geometric types are :";
334 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
335 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
336 oss << "\nOther geometric types are :";
337 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
338 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
342 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
343 if(_nodal_connec==0 || otherC->_nodal_connec==0)
345 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
348 if(_nodal_connec!=otherC->_nodal_connec)
349 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
351 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
354 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
355 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
357 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
360 if(_nodal_connec_index!=otherC->_nodal_connec_index)
361 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
363 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
369 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
371 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
374 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
376 if(_mesh_dim!=otherC->_mesh_dim)
378 if(_types!=otherC->_types)
380 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
381 if(_nodal_connec==0 || otherC->_nodal_connec==0)
383 if(_nodal_connec!=otherC->_nodal_connec)
384 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
386 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
387 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
389 if(_nodal_connec_index!=otherC->_nodal_connec_index)
390 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
396 * 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
397 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
399 * In case of success cellCor and nodeCor are informed both.
400 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
401 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
402 * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
404 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
405 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
407 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
409 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
410 MEDCouplingMesh::checkFastEquivalWith(other,prec);
411 if(_types!=otherC->_types)
412 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
413 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
416 int oldNbOfNodes=getNumberOfNodes();
417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
420 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
421 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
422 if(pt!=da->getConstPointer()+da->getNbOfElems())
423 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
424 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
427 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
430 da=m->zipConnectivityTraducer(cellCompPol);
431 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
432 pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
433 if(pt!=da->getConstPointer()+da->getNbOfElems())
434 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
436 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
437 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
441 * 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
442 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
443 * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
444 * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception !
446 * In case of success cellCor are informed both.
447 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
448 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
450 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
451 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
453 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
455 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
456 MEDCouplingMesh::checkFastEquivalWith(other,prec);
457 if(_types!=otherC->_types)
458 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
459 if(_coords!=otherC->_coords)
460 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
461 std::vector<const MEDCouplingUMesh *> ms(2);
464 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
466 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
467 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
468 if(pt!=da->getConstPointer()+da->getNbOfElems())
470 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
473 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
477 * This method checks fastly that 'this' and 'other' are equal.
479 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
481 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
483 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
484 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
485 int nbOfCells=getNumberOfCells();
489 status&=areCellsFrom2MeshEqual(otherC,0,prec);
490 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
491 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
493 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
497 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
498 * For speed reasons no check of this will be done.
500 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
503 int nbOfNodes=getNumberOfNodes();
504 int *revNodalIndxPtr=new int[nbOfNodes+1];
505 revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
506 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
507 const int *conn=_nodal_connec->getConstPointer();
508 const int *connIndex=_nodal_connec_index->getConstPointer();
509 int nbOfCells=getNumberOfCells();
510 int nbOfEltsInRevNodal=0;
511 for(int eltId=0;eltId<nbOfCells;eltId++)
513 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
514 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
515 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
516 if(*iter>=0)//for polyhedrons
518 nbOfEltsInRevNodal++;
519 revNodalIndxPtr[(*iter)+1]++;
522 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
523 int *revNodalPtr=new int[nbOfEltsInRevNodal];
524 revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
525 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
526 for(int eltId=0;eltId<nbOfCells;eltId++)
528 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
529 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
530 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
531 if(*iter>=0)//for polyhedrons
532 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
538 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
543 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
549 if(cm.getOrientationStatus(nb,conn1,conn2))
556 class MinusOneSonsGenerator
559 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
560 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
561 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
562 static const int DELTA=1;
564 const INTERP_KERNEL::CellModel& _cm;
567 class MinusOneSonsGeneratorBiQuadratic
570 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
571 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
572 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
573 static const int DELTA=1;
575 const INTERP_KERNEL::CellModel& _cm;
578 class MinusTwoSonsGenerator
581 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
582 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
583 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
584 static const int DELTA=2;
586 const INTERP_KERNEL::CellModel& _cm;
592 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
593 * For speed reasons no check of this will be done.
594 * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
595 * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
596 * The algorithm to compute this p-1 mesh is the following :
597 * For each cell in 'this' it splits into p-1 elements.
598 * If this p-1 element does not already exists it is appended to the returned mesh
599 * If this p-1 element already exists, it is not appended.
600 * This method returns or 4 arrays plus the returned mesh.
601 * '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.
602 * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
604 * 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.
605 * 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])
607 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
608 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
610 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
612 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
616 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
617 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
618 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
619 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
620 * \sa MEDCouplingUMesh::buildDescendingConnectivity
622 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
625 if(getMeshDimension()!=3)
626 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
627 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
631 * WARNING this method do the assumption that connectivity lies on the coordinates set.
632 * For speed reasons no check of this will be done.
633 * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
634 * 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,
635 * 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
636 * an array in relative "FORTRAN" mode.
638 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
639 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
641 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
643 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
647 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
648 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
649 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
650 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
652 * \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
653 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
654 * \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.
656 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
664 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
668 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
669 * 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,
670 * excluding a set of meshdim-1 cells in input descending connectivity.
671 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
672 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
673 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
675 * \param [in] desc descending connectivity array.
676 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
677 * \param [in] revDesc reverse descending connectivity array.
678 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
679 * \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
680 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
681 * \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.
683 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
684 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
686 if(!desc || !descIndx || !revDesc || !revDescIndx)
687 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
688 const int *descPtr=desc->getConstPointer();
689 const int *descIPtr=descIndx->getConstPointer();
690 const int *revDescPtr=revDesc->getConstPointer();
691 const int *revDescIPtr=revDescIndx->getConstPointer();
693 int nbCells=descIndx->getNumberOfTuples()-1;
694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
695 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
696 int *out1Ptr=out1->getPointer();
698 out0->reserve(desc->getNumberOfTuples());
699 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
701 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
703 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
705 out0->insertAtTheEnd(s.begin(),s.end());
707 *out1Ptr=out0->getNumberOfTuples();
709 neighbors=out0.retn();
710 neighborsIndx=out1.retn();
716 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
717 * For speed reasons no check of this will be done.
719 template<class SonsGenerator>
720 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
722 if(!desc || !descIndx || !revDesc || !revDescIndx)
723 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
724 checkConnectivityFullyDefined();
725 int nbOfCells=getNumberOfCells();
726 int nbOfNodes=getNumberOfNodes();
727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
728 int *revNodalIndxPtr=revNodalIndx->getPointer();
729 const int *conn=_nodal_connec->getConstPointer();
730 const int *connIndex=_nodal_connec_index->getConstPointer();
731 std::string name="Mesh constituent of "; name+=getName();
732 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
733 ret->setCoords(getCoords());
734 ret->allocateCells(2*nbOfCells);
735 descIndx->alloc(nbOfCells+1,1);
736 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
737 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
738 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
740 int pos=connIndex[eltId];
741 int posP1=connIndex[eltId+1];
742 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
743 SonsGenerator sg(cm);
744 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
745 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
746 for(unsigned i=0;i<nbOfSons;i++)
748 INTERP_KERNEL::NormalizedCellType cmsId;
749 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
750 for(unsigned k=0;k<nbOfNodesSon;k++)
752 revNodalIndxPtr[tmp[k]+1]++;
753 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
754 revDesc2->pushBackSilent(eltId);
756 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
758 int nbOfCellsM1=ret->getNumberOfCells();
759 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
761 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
762 int *revNodalPtr=revNodal->getPointer();
763 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
764 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
765 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
767 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
768 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
769 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
770 if(*iter>=0)//for polyhedrons
771 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
774 DataArrayInt *commonCells=0,*commonCellsI=0;
775 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
777 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
778 int newNbOfCellsM1=-1;
779 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
780 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
781 std::vector<bool> isImpacted(nbOfCellsM1,false);
782 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
783 for(int work2=work[0];work2!=work[1];work2++)
784 isImpacted[commonCellsPtr[work2]]=true;
785 const int *o2nM1Ptr=o2nM1->getConstPointer();
786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
787 const int *n2oM1Ptr=n2oM1->getConstPointer();
788 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
789 ret2->copyTinyInfoFrom(this);
790 desc->alloc(descIndx->back(),1);
791 int *descPtr=desc->getPointer();
792 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
793 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
796 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
799 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
801 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
802 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
805 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
808 revDesc->reserve(newNbOfCellsM1);
809 revDescIndx->alloc(newNbOfCellsM1+1,1);
810 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
811 const int *revDesc2Ptr=revDesc2->getConstPointer();
812 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
814 int oldCellIdM1=n2oM1Ptr[i];
815 if(!isImpacted[oldCellIdM1])
817 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
818 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
822 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
823 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
824 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
832 struct MEDCouplingAccVisit
834 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
835 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
836 int _new_nb_of_nodes;
843 * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
844 * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
845 * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
846 * If mesh dimension is not in [2,3] an exception is thrown.
847 * Of course pay attention that the resulting mesh is slower than previous one.
848 * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
849 * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
850 * If mesh==3, after throw the mesh is \b unconsistent !
851 * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
853 * \warning This method modifies can modify significantly the geometric type order in \a this.
854 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
856 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
859 int dim=getMeshDimension();
861 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
862 int nbOfCells=getNumberOfCells();
865 const int *connIndex=_nodal_connec_index->getConstPointer();
866 int *conn=_nodal_connec->getPointer();
867 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
869 if(*iter>=0 && *iter<nbOfCells)
871 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
873 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
875 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
879 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
880 oss << " in range [0," << nbOfCells << ") !";
881 throw INTERP_KERNEL::Exception(oss.str().c_str());
887 int *connIndex=_nodal_connec_index->getPointer();
888 int connIndexLgth=_nodal_connec_index->getNbOfElems();
889 const int *connOld=_nodal_connec->getConstPointer();
890 int connOldLgth=_nodal_connec->getNbOfElems();
891 std::vector<int> connNew(connOld,connOld+connOldLgth);
892 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
894 if(*iter>=0 && *iter<nbOfCells)
896 int pos=connIndex[*iter];
897 int posP1=connIndex[(*iter)+1];
898 int lgthOld=posP1-pos-1;
899 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
900 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
901 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
902 int *tmp=new int[nbOfFaces*lgthOld];
904 for(int j=0;j<(int)nbOfFaces;j++)
906 INTERP_KERNEL::NormalizedCellType type;
907 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
911 std::size_t newLgth=std::distance(tmp,work)-1;
912 std::size_t delta=newLgth-lgthOld;
913 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
914 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
915 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
920 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
921 oss << " in range [0," << nbOfCells << ") !";
922 throw INTERP_KERNEL::Exception(oss.str().c_str());
925 _nodal_connec->alloc((int)connNew.size(),1);
926 int *newConnPtr=_nodal_connec->getPointer();
927 std::copy(connNew.begin(),connNew.end(),newConnPtr);
933 * This method converts all cells into poly type if possible.
934 * This method is purely for userfriendliness.
935 * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
937 void MEDCouplingUMesh::convertAllToPoly()
939 int nbOfCells=getNumberOfCells();
940 std::vector<int> cellIds(nbOfCells);
941 for(int i=0;i<nbOfCells;i++)
943 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
947 * 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.
948 * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
949 * 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
950 * each 2 faces hidden in the single face of polyhedron).
951 * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
952 * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
953 * 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'
955 * This method is useful only for users that wants to build extruded unstructured mesh.
956 * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
957 * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
959 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
962 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
963 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
964 int nbOfCells=getNumberOfCells();
965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
966 newCi->alloc(nbOfCells+1,1);
967 int *newci=newCi->getPointer();
968 const int *ci=_nodal_connec_index->getConstPointer();
969 const int *c=_nodal_connec->getConstPointer();
971 for(int i=0;i<nbOfCells;i++)
973 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
974 if(type==INTERP_KERNEL::NORM_POLYHED)
976 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
978 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
979 throw INTERP_KERNEL::Exception(oss.str().c_str());
981 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
984 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 !";
985 throw INTERP_KERNEL::Exception(oss.str().c_str());
988 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)
991 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
994 newC->alloc(newci[nbOfCells],1);
995 int *newc=newC->getPointer();
996 for(int i=0;i<nbOfCells;i++)
998 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
999 if(type==INTERP_KERNEL::NORM_POLYHED)
1001 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1002 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1004 for(std::size_t j=0;j<n1;j++)
1006 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1008 newc[n1+5*j+1]=c[ci[i]+1+j];
1009 newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
1010 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1011 newc[n1+5*j+4]=c[ci[i]+1+j+n1];
1016 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1018 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1019 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1023 * This method is the opposite of ParaMEDMEM::MEDCouplingUMesh::convertToPolyTypes method.
1024 * The aim is to take all polygons or polyhedrons cell and to try to traduce them into classical cells.
1026 * \return If true at least one cell has been unpolyzed.
1027 \n If false has been returned the nodal connectivity of \a this has **not** been altered and \a this has remains unchanged.
1029 * \warning This method modifies can modify significantly the geometric type order in \a this.
1030 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1032 bool MEDCouplingUMesh::unPolyze()
1034 checkFullyDefined();
1035 int mdim=getMeshDimension();
1037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1040 int nbOfCells=getNumberOfCells();
1043 int initMeshLgth=getMeshLength();
1044 int *conn=_nodal_connec->getPointer();
1045 int *index=_nodal_connec_index->getPointer();
1050 for(int i=0;i<nbOfCells;i++)
1052 lgthOfCurCell=index[i+1]-posOfCurCell;
1053 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1054 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1055 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1059 switch(cm.getDimension())
1063 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1064 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1065 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1070 int nbOfFaces,lgthOfPolyhConn;
1071 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1072 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1077 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1081 ret=ret || (newType!=type);
1082 conn[newPos]=newType;
1084 posOfCurCell=index[i+1];
1089 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1090 newPos+=lgthOfCurCell;
1091 posOfCurCell+=lgthOfCurCell;
1095 if(newPos!=initMeshLgth)
1096 _nodal_connec->reAlloc(newPos);
1103 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1104 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1105 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1107 * \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
1110 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1112 checkFullyDefined();
1113 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1115 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1116 coords->recenterForMaxPrecision(eps);
1118 int nbOfCells=getNumberOfCells();
1119 const int *conn=_nodal_connec->getConstPointer();
1120 const int *index=_nodal_connec_index->getConstPointer();
1121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1122 connINew->alloc(nbOfCells+1,1);
1123 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1126 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1128 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1130 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1134 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1135 *connINewPtr=connNew->getNumberOfTuples();
1138 setConnectivity(connNew,connINew,false);
1142 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1143 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1144 * the format of returned DataArrayInt instance.
1146 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1147 * \sa MEDCouplingUMesh::getNodeIdsInUse
1149 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1151 checkConnectivityFullyDefined();
1152 int nbOfCells=getNumberOfCells();
1153 const int *connIndex=_nodal_connec_index->getConstPointer();
1154 const int *conn=_nodal_connec->getConstPointer();
1155 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1156 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1157 std::vector<bool> retS(maxElt,false);
1158 for(int i=0;i<nbOfCells;i++)
1159 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1163 for(int i=0;i<maxElt;i++)
1166 DataArrayInt *ret=DataArrayInt::New();
1168 int *retPtr=ret->getPointer();
1169 for(int i=0;i<maxElt;i++)
1176 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1177 * \sa MEDCouplingUMesh::getNodeIdsInUse
1179 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1181 int nbOfNodes=(int)nodeIdsInUse.size();
1182 int nbOfCells=getNumberOfCells();
1183 const int *connIndex=_nodal_connec_index->getConstPointer();
1184 const int *conn=_nodal_connec->getConstPointer();
1185 for(int i=0;i<nbOfCells;i++)
1186 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1189 if(conn[j]<nbOfNodes)
1190 nodeIdsInUse[conn[j]]=true;
1193 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1194 throw INTERP_KERNEL::Exception(oss.str().c_str());
1200 * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
1201 * The returned array is newly created and should be dealt by the caller.
1202 * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
1203 * The size of returned array is the number of nodes of 'this'.
1204 * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
1205 * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
1206 * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
1207 * \throw if a cell contains in its nodal connectivity a node id >= nb of nodes an exception will be thrown.
1208 * \sa MEDCouplingUMesh::computeNodeIdsAlg
1210 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1213 int nbOfNodes=getNumberOfNodes();
1214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1215 ret->alloc(nbOfNodes,1);
1216 int *traducer=ret->getPointer();
1217 std::fill(traducer,traducer+nbOfNodes,-1);
1218 int nbOfCells=getNumberOfCells();
1219 const int *connIndex=_nodal_connec_index->getConstPointer();
1220 const int *conn=_nodal_connec->getConstPointer();
1221 for(int i=0;i<nbOfCells;i++)
1222 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1225 if(conn[j]<nbOfNodes)
1226 traducer[conn[j]]=1;
1229 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1230 throw INTERP_KERNEL::Exception(oss.str().c_str());
1233 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1234 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1239 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1240 * For each cell in \b this the number of nodes constituting cell is computed.
1241 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1242 * For polyhedrons, the face separation (-1) are excluded from the couting.
1244 * \return a newly allocated array
1246 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1248 checkConnectivityFullyDefined();
1249 int nbOfCells=getNumberOfCells();
1250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1251 ret->alloc(nbOfCells,1);
1252 int *retPtr=ret->getPointer();
1253 const int *conn=getNodalConnectivity()->getConstPointer();
1254 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1255 for(int i=0;i<nbOfCells;i++,retPtr++)
1257 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1258 *retPtr=connI[i+1]-connI[i]-1;
1260 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1266 * 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.
1267 * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
1268 * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
1269 * -1 values in returned array means that the corresponding old node is no more used.
1271 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1273 int newNbOfNodes=-1;
1274 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1275 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1280 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1281 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1283 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1288 return AreCellsEqual0(conn,connI,cell1,cell2);
1290 return AreCellsEqual1(conn,connI,cell1,cell2);
1292 return AreCellsEqual2(conn,connI,cell1,cell2);
1294 return AreCellsEqual3(conn,connI,cell1,cell2);
1296 return AreCellsEqual7(conn,connI,cell1,cell2);
1298 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2 or 3.");
1302 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1304 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1306 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1307 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1312 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1314 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1316 int sz=connI[cell1+1]-connI[cell1];
1317 if(sz==connI[cell2+1]-connI[cell2])
1319 if(conn[connI[cell1]]==conn[connI[cell2]])
1321 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1322 unsigned dim=cm.getDimension();
1328 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1329 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1330 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1331 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1332 return work!=tmp+sz1?1:0;
1335 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1345 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1347 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1349 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1351 if(conn[connI[cell1]]==conn[connI[cell2]])
1353 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1354 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1362 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1364 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1366 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1368 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1369 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1376 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1378 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1380 int sz=connI[cell1+1]-connI[cell1];
1381 if(sz==connI[cell2+1]-connI[cell2])
1383 if(conn[connI[cell1]]==conn[connI[cell2]])
1385 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1386 unsigned dim=cm.getDimension();
1392 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1393 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1394 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1395 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1400 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1401 std::reverse_iterator<int *> it2((int *)tmp);
1402 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1408 return work!=tmp+sz1?1:0;
1411 {//case of SEG2 and SEG3
1412 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1414 if(!cm.isQuadratic())
1416 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1417 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1418 if(std::equal(it1,it2,conn+connI[cell2]+1))
1424 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])
1431 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1439 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1440 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1442 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1444 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1446 std::vector<int> c1,c2;
1447 getNodeIdsOfCell(cellId,c1);
1448 other->getNodeIdsOfCell(cellId,c2);
1449 std::size_t sz=c1.size();
1452 for(std::size_t i=0;i<sz;i++)
1454 std::vector<double> n1,n2;
1455 getCoordinatesOfNode(c1[0],n1);
1456 other->getCoordinatesOfNode(c2[0],n2);
1457 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1458 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1459 if(*std::max_element(n1.begin(),n1.end())>prec)
1466 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1467 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1468 * and result remains unchanged.
1469 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1470 * If in 'candidates' pool -1 value is considered as an empty value.
1471 * WARNING this method returns only ONE set of result !
1473 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1475 if(candidates.size()<1)
1478 std::vector<int>::const_iterator iter=candidates.begin();
1479 int start=(*iter++);
1480 for(;iter!=candidates.end();iter++)
1482 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1487 result->pushBackSilent(start);
1491 result->pushBackSilent(*iter);
1493 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1500 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1501 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1503 * \param [in] compType input specifying the technique used to compare cells each other.
1504 * - 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.
1505 * - 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)
1506 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1507 * - 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
1508 * can be used for users not sensitive to orientation of cell
1509 * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1510 * \param [out] commonCells
1511 * \param [out] commonCellsI
1512 * \return the correspondance array old to new in a newly allocated array.
1515 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1517 checkConnectivityFullyDefined();
1518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1519 getReverseNodalConnectivity(revNodal,revNodalI);
1520 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1523 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1524 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1526 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1527 int nbOfCells=nodalI->getNumberOfTuples()-1;
1528 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1529 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1530 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1531 std::vector<bool> isFetched(nbOfCells,false);
1534 for(int i=0;i<nbOfCells;i++)
1538 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1539 std::vector<int> v,v2;
1540 if(connOfNode!=connPtr+connIPtr[i+1])
1542 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1543 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1546 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1550 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1551 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1552 v2.resize(std::distance(v2.begin(),it));
1556 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1558 int pos=commonCellsI->back();
1559 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1560 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1561 isFetched[*it]=true;
1569 for(int i=startCellId;i<nbOfCells;i++)
1573 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1574 std::vector<int> v,v2;
1575 if(connOfNode!=connPtr+connIPtr[i+1])
1577 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1580 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1584 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1585 v2.resize(std::distance(v2.begin(),it));
1589 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1591 int pos=commonCellsI->back();
1592 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1593 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1594 isFetched[*it]=true;
1600 commonCellsArr=commonCells.retn();
1601 commonCellsIArr=commonCellsI.retn();
1605 * This method could potentially modify \a this. This method merges cells if there are cells equal in \a this. The comparison is specified by \a compType.
1606 * This method keeps the coordiantes of \a this.
1608 * \param [in] compType input specifying the technique used to compare cells each other.
1609 * - 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.
1610 * - 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)
1611 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1612 * - 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
1613 * can be used for users not sensitive to orientation of cell
1614 * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned
1615 * \return the correspondance array old to new in a newly allocated array.
1617 * \warning This method modifies can modify significantly the geometric type order in \a this.
1618 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1620 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1622 DataArrayInt *commonCells=0,*commonCellsI=0;
1623 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1625 int newNbOfCells=-1;
1626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1627 commonCellsI->end(),newNbOfCells);
1628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1629 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1630 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1635 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1636 * 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.
1637 * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
1638 * The main difference is that this method is not expected to throw exception.
1639 * This method has two outputs :
1641 * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
1642 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1643 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1645 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1647 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1648 int nbOfCells=getNumberOfCells();
1649 static const int possibleCompType[]={0,1,2};
1650 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1652 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1653 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1655 throw INTERP_KERNEL::Exception(oss.str().c_str());
1657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1658 arr=o2n->substr(nbOfCells);
1659 arr->setName(other->getName());
1661 if(other->getNumberOfCells()==0)
1663 return arr->getMaxValue(tmp)<nbOfCells;
1667 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1668 * This method tries to determine if \b other is fully included in \b this.
1669 * The main difference is that this method is not expected to throw exception.
1670 * This method has two outputs :
1672 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1673 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1675 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1677 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1678 DataArrayInt *commonCells=0,*commonCellsI=0;
1679 int thisNbCells=getNumberOfCells();
1680 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1682 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1683 int otherNbCells=other->getNumberOfCells();
1684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1685 arr2->alloc(otherNbCells,1);
1686 arr2->fillWithZero();
1687 int *arr2Ptr=arr2->getPointer();
1688 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1689 for(int i=0;i<nbOfCommon;i++)
1691 int start=commonCellsPtr[commonCellsIPtr[i]];
1692 if(start<thisNbCells)
1694 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1696 int sig=commonCellsPtr[j]>0?1:-1;
1697 int val=std::abs(commonCellsPtr[j])-1;
1698 if(val>=thisNbCells)
1699 arr2Ptr[val-thisNbCells]=sig*(start+1);
1703 arr2->setName(other->getName());
1704 if(arr2->presenceOfValue(0))
1711 * @param areNodesMerged if at least two nodes have been merged.
1712 * @return old to new node correspondance.
1714 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1716 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1718 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1723 * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
1725 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1727 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1729 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1734 * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
1735 * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
1736 * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
1737 * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
1739 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
1741 const DataArrayDouble *coords=other.getCoords();
1743 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
1745 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1746 int otherNbOfNodes=other.getNumberOfNodes();
1747 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1749 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1750 setCoords(newCoords);
1751 bool areNodesMerged;
1753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1756 setCoords(oldCoords);
1757 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1759 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1760 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1761 if(pt!=da->getConstPointer()+da->getNbOfElems())
1763 setCoords(oldCoords);
1764 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1766 setCoords(oldCoords);
1767 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1772 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1773 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1774 * cellIds is not given explicitely but by a range python like.
1776 * \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.
1777 * \return a newly allocated
1779 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1780 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1782 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1784 if(getMeshDimension()!=-1)
1786 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
1793 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1795 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1797 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1799 return const_cast<MEDCouplingUMesh *>(this);
1804 * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
1805 * @param begin begin of array containing the cell ids to keep.
1806 * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
1807 * @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.
1809 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1810 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1812 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1814 if(getMeshDimension()!=-1)
1816 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
1824 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1826 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1828 return const_cast<MEDCouplingUMesh *>(this);
1833 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1835 * 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.
1836 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1837 * The number of cells of \b this will remain the same with this method.
1839 * \param [in] begin begin of cell ids (included) of cells in this to assign
1840 * \param [in] end end of cell ids (excluded) of cells in this to assign
1841 * \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).
1842 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1844 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1846 checkConnectivityFullyDefined();
1847 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1848 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1850 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1852 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1853 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1854 throw INTERP_KERNEL::Exception(oss.str().c_str());
1856 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1857 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1859 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1860 throw INTERP_KERNEL::Exception(oss.str().c_str());
1862 int nbOfCells=getNumberOfCells();
1863 bool easyAssign=true;
1864 const int *connI=_nodal_connec_index->getConstPointer();
1865 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1866 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1868 if(*it>=0 && *it<nbOfCells)
1870 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1874 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1875 throw INTERP_KERNEL::Exception(oss.str().c_str());
1880 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1885 DataArrayInt *arrOut=0,*arrIOut=0;
1886 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1889 setConnectivity(arrOut,arrIOut,true);
1893 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1895 checkConnectivityFullyDefined();
1896 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1897 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1899 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1901 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1902 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1903 throw INTERP_KERNEL::Exception(oss.str().c_str());
1905 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1906 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1908 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1909 throw INTERP_KERNEL::Exception(oss.str().c_str());
1911 int nbOfCells=getNumberOfCells();
1912 bool easyAssign=true;
1913 const int *connI=_nodal_connec_index->getConstPointer();
1914 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1916 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1918 if(it>=0 && it<nbOfCells)
1920 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1924 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1925 throw INTERP_KERNEL::Exception(oss.str().c_str());
1930 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1935 DataArrayInt *arrOut=0,*arrIOut=0;
1936 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1939 setConnectivity(arrOut,arrIOut,true);
1943 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1945 DataArrayInt *cellIdsKept=0;
1946 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
1947 cellIdsKept->setName(getName());
1952 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1953 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
1954 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1955 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1957 * \param [in] begin input start of array of node ids.
1958 * \param [in] end input end of array of node ids.
1959 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
1960 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
1962 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
1964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
1965 checkConnectivityFullyDefined();
1967 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
1968 std::vector<bool> fastFinder(sz,false);
1969 for(const int *work=begin;work!=end;work++)
1970 if(*work>=0 && *work<sz)
1971 fastFinder[*work]=true;
1972 int nbOfCells=getNumberOfCells();
1973 const int *conn=getNodalConnectivity()->getConstPointer();
1974 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
1975 for(int i=0;i<nbOfCells;i++)
1977 int ref=0,nbOfHit=0;
1978 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
1982 if(fastFinder[*work2])
1985 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
1986 cellIdsKept->pushBackSilent(i);
1988 cellIdsKeptArr=cellIdsKept.retn();
1992 * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
1994 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1996 DataArrayInt *cellIdsKept=0;
1997 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1998 cellIdsKept->setName(getName());
2003 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2004 * The return newly allocated mesh will share the same coordinates as 'this'.
2005 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2006 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2008 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2010 DataArrayInt *cellIdsKept=0;
2011 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2013 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2017 * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
2018 * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
2019 * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
2020 * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
2022 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2025 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2026 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2027 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2028 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2032 * This method returns a mesh with meshDim=this->getMeshDimension()-1.
2033 * This returned mesh contains cells that are linked with one and only one cell of this.
2034 * @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.
2035 * @return mesh with ref counter equal to 1.
2037 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2039 DataArrayInt *desc=DataArrayInt::New();
2040 DataArrayInt *descIndx=DataArrayInt::New();
2041 DataArrayInt *revDesc=DataArrayInt::New();
2042 DataArrayInt *revDescIndx=DataArrayInt::New();
2044 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2047 descIndx->decrRef();
2048 int nbOfCells=meshDM1->getNumberOfCells();
2049 const int *revDescIndxC=revDescIndx->getConstPointer();
2050 std::vector<int> boundaryCells;
2051 for(int i=0;i<nbOfCells;i++)
2052 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2053 boundaryCells.push_back(i);
2054 revDescIndx->decrRef();
2055 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2060 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2061 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2062 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2064 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2066 checkFullyDefined();
2067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2072 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2073 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2077 const int *revDescPtr=revDesc->getConstPointer();
2078 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2079 int nbOfCells=getNumberOfCells();
2080 std::vector<bool> ret1(nbOfCells,false);
2082 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2083 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2084 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2086 DataArrayInt *ret2=DataArrayInt::New();
2088 int *ret2Ptr=ret2->getPointer();
2090 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2093 ret2->setName("BoundaryCells");
2098 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2099 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2100 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2101 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2103 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2104 * This method method returns cells ids set s = s1 + s2 where :
2106 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2107 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2109 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2110 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2112 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2113 * \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
2114 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2116 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2118 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2119 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2120 checkConnectivityFullyDefined();
2121 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2122 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2123 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2126 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2128 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2129 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2130 DataArrayInt *idsOtherInConsti=0;
2131 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2136 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2137 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2139 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2140 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2141 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2143 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2144 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2145 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2146 neighThisPartAuto=0;
2147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2148 const int li[2]={0,1};
2149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2150 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2151 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2154 cellIdsRk0=s0arr.retn();
2155 cellIdsRk1=s_renum1.retn();
2159 * 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
2160 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2162 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2164 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2167 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2171 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2172 revDesc=0; desc=0; descIndx=0;
2173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2175 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2179 * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2180 * The returned nodes ids are those lying on the boundary of \b this.
2182 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2184 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2185 return skin->computeFetchedNodeIds();
2188 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2191 return const_cast<MEDCouplingUMesh *>(this);
2195 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2196 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2197 * This value is asked because often known by the caller of this method.
2198 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2200 * @param newNodeNumbers array specifying the new numbering in old2New convention.
2201 * @param newNbOfNodes the new number of nodes.
2203 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2205 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2206 renumberNodesInConn(newNodeNumbers);
2210 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2211 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2212 * This value is asked because often known by the caller of this method.
2213 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2214 * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2216 * @param newNodeNumbers array specifying the new numbering.
2217 * @param newNbOfNodes the new number of nodes.
2220 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2222 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2223 renumberNodesInConn(newNodeNumbers);
2227 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2228 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2229 * 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.
2230 * 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.
2231 * 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.
2233 * \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
2234 * parameter is altered during the call.
2235 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2236 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2237 * \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.
2239 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2241 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2242 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2244 checkFullyDefined();
2245 otherDimM1OnSameCoords.checkFullyDefined();
2246 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2247 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2248 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2249 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2250 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2251 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2254 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2255 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2256 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2259 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2261 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2263 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2264 DataArrayInt *idsTmp=0;
2265 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2269 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2270 DataArrayInt *tmp0=0,*tmp1=0;
2271 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2276 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2277 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2279 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2280 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2281 nodeIdsToDuplicate=s3.retn();
2285 * This method operates a modification of the connectivity and coords in \b this.
2286 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2287 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2288 * 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
2289 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2290 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2292 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2294 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2295 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2297 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2299 int nbOfNodes=getNumberOfNodes();
2300 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2301 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2305 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2306 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2307 * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2308 * @param [in] newNodeNumbers in old2New convention
2310 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2312 checkConnectivityFullyDefined();
2313 int *conn=getNodalConnectivity()->getPointer();
2314 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2315 int nbOfCells=getNumberOfCells();
2316 for(int i=0;i<nbOfCells;i++)
2317 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2319 int& node=conn[iconn];
2320 if(node>=0)//avoid polyhedron separator
2322 node=newNodeNumbersO2N[node];
2325 _nodal_connec->declareAsNew();
2330 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2331 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2332 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2334 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2336 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2338 checkConnectivityFullyDefined();
2339 int *conn=getNodalConnectivity()->getPointer();
2340 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2341 int nbOfCells=getNumberOfCells();
2342 for(int i=0;i<nbOfCells;i++)
2343 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2345 int& node=conn[iconn];
2346 if(node>=0)//avoid polyhedron separator
2351 _nodal_connec->declareAsNew();
2356 * This method operates a modification of the connectivity in \b this.
2357 * 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.
2358 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2359 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2360 * 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
2361 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2362 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2364 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2365 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2367 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2368 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2369 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2371 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2373 checkConnectivityFullyDefined();
2374 std::map<int,int> m;
2376 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2378 int *conn=getNodalConnectivity()->getPointer();
2379 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2380 int nbOfCells=getNumberOfCells();
2381 for(int i=0;i<nbOfCells;i++)
2382 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2384 int& node=conn[iconn];
2385 if(node>=0)//avoid polyhedron separator
2387 std::map<int,int>::iterator it=m.find(node);
2396 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2398 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2399 * After the call of this method the number of cells remains the same as before.
2401 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2402 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2403 * be strictly in [0;this->getNumberOfCells()).
2405 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2406 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2407 * should be contained in[0;this->getNumberOfCells()).
2409 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2411 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2413 checkConnectivityFullyDefined();
2414 int nbCells=getNumberOfCells();
2415 const int *array=old2NewBg;
2417 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2419 const int *conn=_nodal_connec->getConstPointer();
2420 const int *connI=_nodal_connec_index->getConstPointer();
2421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2422 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2423 newConn->copyStringInfoFrom(*_nodal_connec);
2424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2425 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2426 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2428 int *newC=newConn->getPointer();
2429 int *newCI=newConnI->getPointer();
2432 for(int i=0;i<nbCells;i++)
2434 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2435 int nbOfElts=connI[pos+1]-connI[pos];
2436 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2441 setConnectivity(newConn,newConnI);
2443 delete [] const_cast<int *>(array);
2447 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2448 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2449 * added in 'elems' parameter.
2451 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2454 if(getMeshDimension()==-1)
2456 elems->pushBackSilent(0);
2457 return elems.retn();
2459 int dim=getSpaceDimension();
2460 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2461 const int* conn = getNodalConnectivity()->getConstPointer();
2462 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2463 const double* coords = getCoords()->getConstPointer();
2464 int nbOfCells=getNumberOfCells();
2465 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2467 for (int i=0; i<dim; i++)
2469 elem_bb[i*2]=std::numeric_limits<double>::max();
2470 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2473 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2475 int node= conn[inode];
2476 if(node>=0)//avoid polyhedron separator
2478 for (int idim=0; idim<dim; idim++)
2480 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2482 elem_bb[idim*2] = coords[node*dim+idim] ;
2484 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2486 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2491 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2492 elems->pushBackSilent(ielem);
2494 return elems.retn();
2498 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2499 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2500 * added in 'elems' parameter.
2502 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2504 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2505 if(getMeshDimension()==-1)
2507 elems->pushBackSilent(0);
2508 return elems.retn();
2510 int dim=getSpaceDimension();
2511 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2512 const int* conn = getNodalConnectivity()->getConstPointer();
2513 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2514 const double* coords = getCoords()->getConstPointer();
2515 int nbOfCells=getNumberOfCells();
2516 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2518 for (int i=0; i<dim; i++)
2520 elem_bb[i*2]=std::numeric_limits<double>::max();
2521 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2524 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2526 int node= conn[inode];
2527 if(node>=0)//avoid polyhedron separator
2529 for (int idim=0; idim<dim; idim++)
2531 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2533 elem_bb[idim*2] = coords[node*dim+idim] ;
2535 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2537 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2542 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2543 elems->pushBackSilent(ielem);
2545 return elems.retn();
2549 * Returns the cell type of cell with id 'cellId'.
2551 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2553 const int *ptI=_nodal_connec_index->getConstPointer();
2554 const int *pt=_nodal_connec->getConstPointer();
2555 if(cellId>=0 && cellId<_nodal_connec_index->getNbOfElems()-1)
2556 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2559 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2560 throw INTERP_KERNEL::Exception(oss.str().c_str());
2565 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2566 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2567 * The coordinates array is not considered here.
2569 * \param [in] type the geometric type
2570 * \return cell ids in this having geometric type \a type.
2572 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2577 checkConnectivityFullyDefined();
2578 int nbCells=getNumberOfCells();
2579 int mdim=getMeshDimension();
2580 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2581 if(mdim!=(int)cm.getDimension())
2582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2583 const int *ptI=_nodal_connec_index->getConstPointer();
2584 const int *pt=_nodal_connec->getConstPointer();
2585 for(int i=0;i<nbCells;i++)
2587 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2588 ret->pushBackSilent(i);
2594 * Returns nb of cells having the geometric type 'type'.
2596 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2598 const int *ptI=_nodal_connec_index->getConstPointer();
2599 const int *pt=_nodal_connec->getConstPointer();
2600 int nbOfCells=getNumberOfCells();
2602 for(int i=0;i<nbOfCells;i++)
2603 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2609 * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2610 * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2611 * That is to say -1 separator is omitted in returned conn.
2613 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2615 const int *ptI=_nodal_connec_index->getConstPointer();
2616 const int *pt=_nodal_connec->getConstPointer();
2617 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2622 std::string MEDCouplingUMesh::simpleRepr() const
2624 static const char msg0[]="No coordinates specified !";
2625 std::ostringstream ret;
2626 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2627 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2629 double tt=getTime(tmpp1,tmpp2);
2630 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2631 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2632 ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2635 const int spaceDim=getSpaceDimension();
2636 ret << spaceDim << "\nInfo attached on space dimension : ";
2637 for(int i=0;i<spaceDim;i++)
2638 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2642 ret << msg0 << "\n";
2643 ret << "Number of nodes : ";
2645 ret << getNumberOfNodes() << "\n";
2647 ret << msg0 << "\n";
2648 ret << "Number of cells : ";
2649 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2650 ret << getNumberOfCells() << "\n";
2652 ret << "No connectivity specified !" << "\n";
2653 ret << "Cell types present : ";
2654 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2656 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2657 ret << cm.getRepr() << " ";
2663 std::string MEDCouplingUMesh::advancedRepr() const
2665 std::ostringstream ret;
2666 ret << simpleRepr();
2667 ret << "\nCoordinates array : \n___________________\n\n";
2669 _coords->reprWithoutNameStream(ret);
2671 ret << "No array set !\n";
2672 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2673 reprConnectivityOfThisLL(ret);
2678 * This method returns a C++ code that is a dump of \a this.
2679 * This method will throw if this is not fully defined.
2681 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2683 static const char coordsName[]="coords";
2684 static const char connName[]="conn";
2685 static const char connIName[]="connI";
2686 checkFullyDefined();
2687 std::ostringstream ret; ret << "// coordinates" << std::endl;
2688 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2689 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2690 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2691 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2692 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2693 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2694 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2698 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2700 std::ostringstream ret;
2701 reprConnectivityOfThisLL(ret);
2706 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2707 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2708 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2711 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2712 * 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
2713 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2715 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2717 int mdim=getMeshDimension();
2719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2720 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2722 bool needToCpyCT=true;
2725 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2733 if(!_nodal_connec_index)
2735 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2740 tmp2=_nodal_connec_index;
2743 ret->setConnectivity(tmp1,tmp2,false);
2748 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2749 ret->setCoords(coords);
2752 ret->setCoords(_coords);
2756 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2758 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2760 int nbOfCells=getNumberOfCells();
2761 const int *c=_nodal_connec->getConstPointer();
2762 const int *ci=_nodal_connec_index->getConstPointer();
2763 for(int i=0;i<nbOfCells;i++)
2765 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2766 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2767 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2772 stream << "Connectivity not defined !\n";
2775 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2777 const int *ptI=_nodal_connec_index->getConstPointer();
2778 const int *pt=_nodal_connec->getConstPointer();
2779 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2780 return ptI[cellId+1]-ptI[cellId]-1;
2782 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2786 * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2787 * This method avoids to compute explicitely submesh to get its types.
2789 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2791 checkFullyDefined();
2792 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2793 const int *conn=_nodal_connec->getConstPointer();
2794 const int *connIndex=_nodal_connec_index->getConstPointer();
2795 for(const int *w=begin;w!=end;w++)
2796 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2801 * Method reserved for advanced users having prepared their connectivity before.
2802 * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2804 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2806 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2807 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2808 if(isComputingTypes)
2814 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2815 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2817 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2818 _nodal_connec(0),_nodal_connec_index(0),
2819 _types(other._types)
2821 if(other._nodal_connec)
2822 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2823 if(other._nodal_connec_index)
2824 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2827 MEDCouplingUMesh::~MEDCouplingUMesh()
2830 _nodal_connec->decrRef();
2831 if(_nodal_connec_index)
2832 _nodal_connec_index->decrRef();
2836 * This method recomputes all cell types of 'this'.
2838 void MEDCouplingUMesh::computeTypes()
2840 if(_nodal_connec && _nodal_connec_index)
2843 const int *conn=_nodal_connec->getConstPointer();
2844 const int *connIndex=_nodal_connec_index->getConstPointer();
2845 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2847 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2848 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2853 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2855 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2857 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2858 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2862 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2864 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2866 if(!_nodal_connec_index || !_nodal_connec)
2867 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2870 int MEDCouplingUMesh::getNumberOfCells() const
2872 if(_nodal_connec_index)
2873 return _nodal_connec_index->getNumberOfTuples()-1;
2878 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2881 int MEDCouplingUMesh::getMeshDimension() const
2884 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2889 * This method is for test reason. Normally the integer returned is not useable by user.
2891 int MEDCouplingUMesh::getMeshLength() const
2893 return _nodal_connec->getNbOfElems();
2897 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2899 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2901 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2902 tinyInfo.push_back(getMeshDimension());
2903 tinyInfo.push_back(getNumberOfCells());
2905 tinyInfo.push_back(getMeshLength());
2907 tinyInfo.push_back(-1);
2911 * First step of unserialization process.
2913 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2915 return tinyInfo[6]<=0;
2919 * Second step of serialization process.
2920 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2922 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2924 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2926 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2930 * Third and final step of serialization process.
2932 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2934 MEDCouplingPointSet::serialize(a1,a2);
2935 if(getMeshDimension()>-1)
2937 a1=DataArrayInt::New();
2938 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2939 int *ptA1=a1->getPointer();
2940 const int *conn=getNodalConnectivity()->getConstPointer();
2941 const int *index=getNodalConnectivityIndex()->getConstPointer();
2942 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2943 std::copy(conn,conn+getMeshLength(),ptA1);
2950 * Second and final unserialization process.
2951 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2953 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2955 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2956 setMeshDimension(tinyInfo[5]);
2960 const int *recvBuffer=a1->getConstPointer();
2961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
2962 myConnecIndex->alloc(tinyInfo[6]+1,1);
2963 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
2965 myConnec->alloc(tinyInfo[7],1);
2966 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2967 setConnectivity(myConnec, myConnecIndex);
2972 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2973 * CellIds are given using range specified by a start an end and step.
2975 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2977 checkFullyDefined();
2978 int ncell=getNumberOfCells();
2979 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2980 ret->_mesh_dim=_mesh_dim;
2981 ret->setCoords(_coords);
2982 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2984 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2986 const int *conn=_nodal_connec->getConstPointer();
2987 const int *connIndex=_nodal_connec_index->getConstPointer();
2988 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2990 if(work>=0 && work<ncell)
2992 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2996 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2997 throw INTERP_KERNEL::Exception(oss.str().c_str());
3000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3001 int *newConnPtr=newConn->getPointer();
3002 std::set<INTERP_KERNEL::NormalizedCellType> types;
3004 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3006 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3007 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3009 ret->setConnectivity(newConn,newConnI,false);
3011 ret->copyTinyInfoFrom(this);
3016 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3017 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3018 * The return newly allocated mesh will share the same coordinates as 'this'.
3020 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3022 checkFullyDefined();
3023 int ncell=getNumberOfCells();
3024 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3025 ret->_mesh_dim=_mesh_dim;
3026 ret->setCoords(_coords);
3027 std::size_t nbOfElemsRet=std::distance(begin,end);
3028 int *connIndexRet=new int[nbOfElemsRet+1];
3030 const int *conn=_nodal_connec->getConstPointer();
3031 const int *connIndex=_nodal_connec_index->getConstPointer();
3033 for(const int *work=begin;work!=end;work++,newNbring++)
3035 if(*work>=0 && *work<ncell)
3036 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3039 delete [] connIndexRet;
3040 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3041 throw INTERP_KERNEL::Exception(oss.str().c_str());
3044 int *connRet=new int[connIndexRet[nbOfElemsRet]];
3045 int *connRetWork=connRet;
3046 std::set<INTERP_KERNEL::NormalizedCellType> types;
3047 for(const int *work=begin;work!=end;work++)
3049 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3050 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3053 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3055 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3056 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3058 ret->copyTinyInfoFrom(this);
3063 * brief returns the volumes of the cells underlying the field \a field
3065 * For 2D geometries, the returned field contains the areas.
3066 * For 3D geometries, the returned field contains the volumes.
3068 * param field field on which cells the volumes are required
3069 * return field containing the volumes, area or length depending the meshdimension.
3071 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3073 std::string name="MeasureOfMesh_";
3075 int nbelem=getNumberOfCells();
3076 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3077 field->setName(name.c_str());
3078 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3079 array->alloc(nbelem,1);
3080 double *area_vol=array->getPointer();
3081 field->setArray(array) ; array=0;
3082 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3083 field->synchronizeTimeWithMesh();
3084 if(getMeshDimension()!=-1)
3087 INTERP_KERNEL::NormalizedCellType type;
3088 int dim_space=getSpaceDimension();
3089 const double *coords=getCoords()->getConstPointer();
3090 const int *connec=getNodalConnectivity()->getConstPointer();
3091 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3092 for(int iel=0;iel<nbelem;iel++)
3094 ipt=connec_index[iel];
3095 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3096 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);
3099 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3103 area_vol[0]=std::numeric_limits<double>::max();
3105 return field.retn();
3109 * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3110 * This method avoids to build explicitely part of this to perform the work.
3112 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3114 std::string name="PartMeasureOfMesh_";
3116 int nbelem=(int)std::distance(begin,end);
3117 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3118 array->setName(name.c_str());
3119 array->alloc(nbelem,1);
3120 double *area_vol=array->getPointer();
3121 if(getMeshDimension()!=-1)
3124 INTERP_KERNEL::NormalizedCellType type;
3125 int dim_space=getSpaceDimension();
3126 const double *coords=getCoords()->getConstPointer();
3127 const int *connec=getNodalConnectivity()->getConstPointer();
3128 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3129 for(const int *iel=begin;iel!=end;iel++)
3131 ipt=connec_index[*iel];
3132 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3133 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3136 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3140 area_vol[0]=std::numeric_limits<double>::max();
3142 return array.retn();
3146 * This methods returns a field on nodes and no time. This method is useful to check "P1*" conservative interpolators.
3147 * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3149 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3151 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3152 std::string name="MeasureOnNodeOfMesh_";
3154 int nbNodes=getNumberOfNodes();
3155 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3156 double cst=1./((double)getMeshDimension()+1.);
3157 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3158 array->alloc(nbNodes,1);
3159 double *valsToFill=array->getPointer();
3160 std::fill(valsToFill,valsToFill+nbNodes,0.);
3161 const double *values=tmp->getArray()->getConstPointer();
3162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3164 getReverseNodalConnectivity(da,daInd);
3165 const int *daPtr=da->getConstPointer();
3166 const int *daIPtr=daInd->getConstPointer();
3167 for(int i=0;i<nbNodes;i++)
3168 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3169 valsToFill[i]+=cst*values[*cell];
3171 ret->setArray(array);
3176 * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3177 * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3179 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() 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 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3184 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3185 int nbOfCells=getNumberOfCells();
3186 int nbComp=getMeshDimension()+1;
3187 array->alloc(nbOfCells,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 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3197 const double *locPtr=loc->getConstPointer();
3198 for(int i=0;i<nbOfCells;i++,vals+=3)
3200 int offset=connI[i];
3201 INTERP_KERNEL::crossprod<3>(locPtr+3*i,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));
3208 for(int i=0;i<nbOfCells;i++)
3209 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3212 else//meshdimension==1
3215 for(int i=0;i<nbOfCells;i++)
3217 int offset=connI[i];
3218 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3219 double n=INTERP_KERNEL::norm<2>(tmp);
3220 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3225 ret->setArray(array);
3227 ret->synchronizeTimeWithSupport();
3232 * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3233 * This method avoids to build explicitely part of this to perform the work.
3235 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3237 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3238 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3239 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3240 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3241 std::size_t nbelems=std::distance(begin,end);
3242 int nbComp=getMeshDimension()+1;
3243 array->alloc((int)nbelems,nbComp);
3244 double *vals=array->getPointer();
3245 const int *connI=_nodal_connec_index->getConstPointer();
3246 const int *conn=_nodal_connec->getConstPointer();
3247 const double *coords=_coords->getConstPointer();
3248 if(getMeshDimension()==2)
3250 if(getSpaceDimension()==3)
3252 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3253 const double *locPtr=loc->getConstPointer();
3254 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3256 int offset=connI[*i];
3257 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3258 double n=INTERP_KERNEL::norm<3>(vals);
3259 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3264 for(std::size_t i=0;i<nbelems;i++)
3265 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3268 else//meshdimension==1
3271 for(const int *i=begin;i!=end;i++)
3273 int offset=connI[*i];
3274 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3275 double n=INTERP_KERNEL::norm<2>(tmp);
3276 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3281 ret->setArray(array);
3283 ret->synchronizeTimeWithSupport();
3288 * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3289 * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3291 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3293 if(getMeshDimension()!=1)
3294 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3295 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3296 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3298 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3299 int nbOfCells=getNumberOfCells();
3300 int spaceDim=getSpaceDimension();
3301 array->alloc(nbOfCells,spaceDim);
3302 double *pt=array->getPointer();
3303 const double *coo=getCoords()->getConstPointer();
3304 std::vector<int> conn;
3306 for(int i=0;i<nbOfCells;i++)
3309 getNodeIdsOfCell(i,conn);
3310 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3312 ret->setArray(array);
3314 ret->synchronizeTimeWithSupport();
3319 * 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.
3320 * This method returns 2 objects :
3321 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3322 * - 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
3323 * mesh the 3D cell id is 'this' it comes from.
3324 * This method works only for linear meshes (non quadratic).
3325 * 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
3326 * face. Only 'cellIds' parameter can distinguish the 2.
3327 * @param origin is the origin of the plane. It should be an array of length 3.
3328 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3329 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3330 * 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).
3332 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3334 checkFullyDefined();
3335 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3336 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3338 if(candidates->empty())
3339 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3340 std::vector<int> nodes;
3341 DataArrayInt *cellIds1D=0;
3342 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3343 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3348 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3349 revDesc2=0; revDescIndx2=0;
3350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3351 revDesc1=0; revDescIndx1=0;
3352 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3355 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3356 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3358 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3359 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3360 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3361 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3362 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3364 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3365 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3366 if(cellIds2->empty())
3367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3368 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3369 ret->setCoords(mDesc1->getCoords());
3370 ret->setConnectivity(conn,connI,true);
3371 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3376 * 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.
3377 * This method returns 2 objects :
3378 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3379 * - 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
3380 * mesh the 3DSurf cell id is 'this' it comes from.
3381 * This method works only for linear meshes (non quadratic).
3382 * 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
3383 * face. Only 'cellIds' parameter can distinguish the 2.
3384 * @param origin is the origin of the plane. It should be an array of length 3.
3385 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3386 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3387 * 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).
3389 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3391 checkFullyDefined();
3392 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3393 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3395 if(candidates->empty())
3396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3397 std::vector<int> nodes;
3398 DataArrayInt *cellIds1D=0;
3399 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3400 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3401 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3405 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3406 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3409 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3410 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3412 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3413 int ncellsSub=subMesh->getNumberOfCells();
3414 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3415 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3416 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3417 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3420 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3421 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3422 for(int i=0;i<ncellsSub;i++)
3424 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3426 if(cut3DSurf[i].first!=-2)
3428 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3429 connI->pushBackSilent(conn->getNumberOfTuples());
3430 cellIds2->pushBackSilent(i);
3434 int cellId3DSurf=cut3DSurf[i].second;
3435 int offset=nodalI[cellId3DSurf]+1;
3436 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3437 for(int j=0;j<nbOfEdges;j++)
3439 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3440 connI->pushBackSilent(conn->getNumberOfTuples());
3441 cellIds2->pushBackSilent(cellId3DSurf);
3446 if(cellIds2->empty())
3447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3449 ret->setCoords(mDesc1->getCoords());
3450 ret->setConnectivity(conn,connI,true);
3451 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3456 * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3457 * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3458 * @param origin is the origin of the plane. It should be an array of length 3.
3459 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3461 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3463 checkFullyDefined();
3464 if(getSpaceDimension()!=3)
3465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3466 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3470 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3471 double angle=acos(vec[2]/normm);
3472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3476 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3477 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3478 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3480 mw->getBoundingBox(bbox);
3481 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3482 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3486 getBoundingBox(bbox);
3487 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3488 cellIds=getCellsInBoundingBox(bbox,eps);
3490 return cellIds.retn();
3494 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3495 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3496 * No consideration of coordinate is done by this method.
3497 * 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)
3498 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3500 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3502 if(getMeshDimension()!=1)
3503 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3504 int nbCells=getNumberOfCells();
3506 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3507 const int *connI=_nodal_connec_index->getConstPointer();
3508 const int *conn=_nodal_connec->getConstPointer();
3509 int ref=conn[connI[0]+2];
3510 for(int i=1;i<nbCells;i++)
3512 if(conn[connI[i]+1]!=ref)
3514 ref=conn[connI[i]+2];
3520 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3521 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3522 * @param pt reference point of the line
3523 * @param v normalized director vector of the line
3524 * @param eps max precision before throwing an exception
3525 * @param res output of size this->getNumberOfCells
3527 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3529 if(getMeshDimension()!=1)
3530 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3531 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3532 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3533 if(getSpaceDimension()!=3)
3534 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3535 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3536 const double *fPtr=f->getArray()->getConstPointer();
3538 for(int i=0;i<getNumberOfCells();i++)
3540 const double *tmp1=fPtr+3*i;
3541 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3542 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3543 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3544 double n1=INTERP_KERNEL::norm<3>(tmp);
3545 n1/=INTERP_KERNEL::norm<3>(tmp1);
3547 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3549 const double *coo=getCoords()->getConstPointer();
3550 for(int i=0;i<getNumberOfNodes();i++)
3552 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3553 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3554 res[i]=std::accumulate(tmp,tmp+3,0.);
3559 * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance.
3560 * \a this is expected to be a mesh so that its space dimension is equal to its
3561 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3562 * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3564 * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found
3565 * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked
3566 * to the node that minimizes distance with the input point then -1 is returned in cellId.
3568 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3569 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3571 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3572 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3573 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3574 * \return the positive value of the distance.
3575 * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
3577 * \sa DataArrayDouble::distanceToTuple
3579 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
3581 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3582 if(meshDim!=spaceDim-1)
3583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3584 if(meshDim!=2 && meshDim!=1)
3585 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3586 checkFullyDefined();
3587 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3588 { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
3590 double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
3592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
3593 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
3598 distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
3603 distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
3607 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3615 * \param [in] pt the start pointer (included) of the coordinates of the point
3616 * \param [in] cellIds
3617 * \param [in,out] ret0 the min distance between \a this and the external input point
3618 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3619 * \sa MEDCouplingUMesh::distanceToPoint
3621 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3623 const double *coords=_coords->getConstPointer();
3625 if(cellIds->empty())
3627 const int *ptr=_nodal_connec->getConstPointer();
3628 const int *ptrI=_nodal_connec_index->getConstPointer();
3629 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3631 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3633 case INTERP_KERNEL::NORM_TRI3:
3635 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
3637 { ret0=tmp; cellId=*zeCell; }
3640 case INTERP_KERNEL::NORM_QUAD4:
3641 case INTERP_KERNEL::NORM_POLYGON:
3643 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
3645 { ret0=tmp; cellId=*zeCell; }
3649 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3655 * \param [in] pt the start pointer (included) of the coordinates of the point
3656 * \param [in] cellIds
3657 * \param [in,out] ret0 the min distance between \a this and the external input point
3658 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3659 * \sa MEDCouplingUMesh::distanceToPoint
3661 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3663 const double *coords=_coords->getConstPointer();
3664 if(cellIds->empty())
3665 { cellId=-1; return; }
3666 const int *ptr=_nodal_connec->getConstPointer();
3667 const int *ptrI=_nodal_connec_index->getConstPointer();
3668 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3670 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3672 case INTERP_KERNEL::NORM_SEG2:
3674 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
3675 if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
3677 { ret0=tmp; cellId=*zeCell; }
3681 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3687 * Returns a cell if any that contains the point located on 'pos' with precison eps.
3688 * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3689 * \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'
3690 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3692 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3694 std::vector<int> elts;
3695 getCellsContainingPoint(pos,eps,elts);
3698 return elts.front();
3702 * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3703 * \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'
3704 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3706 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3708 std::vector<int> eltsIndex;
3709 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3714 namespace ParaMEDMEM
3716 template<const int SPACEDIMM>
3720 static const int MY_SPACEDIM=SPACEDIMM;
3721 static const int MY_MESHDIM=8;
3722 typedef int MyConnType;
3723 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3725 // useless, but for windows compilation ...
3726 const double* getCoordinatesPtr() const { return 0; }
3727 const int* getConnectivityPtr() const { return 0; }
3728 const int* getConnectivityIndexPtr() const { return 0; }
3729 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3733 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3735 INTERP_KERNEL::Edge *ret=0;
3738 case INTERP_KERNEL::NORM_SEG2:
3740 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3743 case INTERP_KERNEL::NORM_SEG3:
3745 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3746 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3747 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3748 bool colinearity=inters.areColinears();
3749 delete e1; delete e2;
3751 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3753 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3754 mapp2[bg[2]].second=false;
3758 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3764 * 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'.
3765 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3766 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3768 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3771 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.
3772 const double *coo=mDesc->getCoords()->getConstPointer();
3773 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3774 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3776 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3777 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3778 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3780 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3781 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3783 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3784 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3786 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3787 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3789 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3791 if((*it2).second.second)
3792 mapp[(*it2).second.first]=(*it2).first;
3793 ((*it2).second.first)->decrRef();
3798 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3802 int locId=nodeId-offset2;
3803 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3807 int locId=nodeId-offset1;
3808 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3810 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3813 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3814 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3815 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3817 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3819 int eltId1=abs(*desc1)-1;
3820 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3822 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3823 if(it==mappRev.end())
3825 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3836 template<int SPACEDIM>
3837 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3838 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3840 std::vector<double> bbox;
3841 eltsIndex.resize(nbOfPoints+1);
3844 getBoundingBoxForBBTree(bbox);
3845 int nbOfCells=getNumberOfCells();
3846 const int *conn=_nodal_connec->getConstPointer();
3847 const int *connI=_nodal_connec_index->getConstPointer();
3848 double bb[2*SPACEDIM];
3849 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3850 for(int i=0;i<nbOfPoints;i++)
3852 eltsIndex[i+1]=eltsIndex[i];
3853 for(int j=0;j<SPACEDIM;j++)
3855 bb[2*j]=pos[SPACEDIM*i+j];
3856 bb[2*j+1]=pos[SPACEDIM*i+j];
3858 std::vector<int> candidates;
3859 myTree.getIntersectingElems(bb,candidates);
3860 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3862 int sz=connI[(*iter)+1]-connI[*iter]-1;
3863 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3864 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3865 coords,conn+connI[*iter]+1,sz,eps))
3868 elts.push_back(*iter);
3875 * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3876 * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3877 * in case of multi points searching.
3878 * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3879 * 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]).
3881 * \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...
3883 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3884 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3886 int spaceDim=getSpaceDimension();
3887 int mDim=getMeshDimension();
3892 const double *coords=_coords->getConstPointer();
3893 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3900 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3902 else if(spaceDim==2)
3906 const double *coords=_coords->getConstPointer();
3907 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3910 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3912 else if(spaceDim==1)
3916 const double *coords=_coords->getConstPointer();
3917 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3920 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3927 * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3928 * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3929 * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3930 * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3932 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3934 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3935 if(getMeshDimension()!=2)
3936 throw INTERP_KERNEL::Exception(msg);
3937 int spaceDim=getSpaceDimension();
3938 if(spaceDim!=2 && spaceDim!=3)
3939 throw INTERP_KERNEL::Exception(msg);
3940 const int *conn=_nodal_connec->getConstPointer();
3941 const int *connI=_nodal_connec_index->getConstPointer();
3942 int nbOfCells=getNumberOfCells();
3943 std::vector<double> cell2DinS2;
3944 for(int i=0;i<nbOfCells;i++)
3946 int offset=connI[i];
3947 int nbOfNodesForCell=connI[i+1]-offset-1;
3948 if(nbOfNodesForCell<=3)
3950 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3951 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3952 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3959 * This method is typically requested to unbutterfly 2D linear cells in \b this.
3961 * 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.
3962 * 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.
3964 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3965 * This convex envelop is computed using Jarvis march algorithm.
3966 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3967 * 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)
3968 * 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.
3970 * @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.
3972 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3974 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3975 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
3976 checkFullyDefined();
3977 const double *coords=getCoords()->getConstPointer();
3978 int nbOfCells=getNumberOfCells();
3979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3980 nodalConnecIndexOut->alloc(nbOfCells+1,1);
3981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
3982 int *workIndexOut=nodalConnecIndexOut->getPointer();
3984 const int *nodalConnecIn=_nodal_connec->getConstPointer();
3985 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3986 std::set<INTERP_KERNEL::NormalizedCellType> types;
3987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
3988 isChanged->alloc(0,1);
3989 for(int i=0;i<nbOfCells;i++,workIndexOut++)
3991 int pos=nodalConnecOut->getNumberOfTuples();
3992 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3993 isChanged->pushBackSilent(i);
3994 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
3995 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
3997 if(isChanged->empty())
3999 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4001 return isChanged.retn();
4005 * This method is \b NOT const because it can modify 'this'.
4006 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4007 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4008 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4009 * \b 1 for translation and rotation around point of 'mesh1D'.
4010 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
4012 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4014 checkFullyDefined();
4015 mesh1D->checkFullyDefined();
4016 if(!mesh1D->isContiguous1D())
4017 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4018 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4019 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4020 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4021 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4022 if(mesh1D->getMeshDimension()!=1)
4023 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4025 if(isPresenceOfQuadratic())
4027 if(mesh1D->isFullyQuadratic())
4030 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4033 int oldNbOfNodes=getNumberOfNodes();
4034 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4039 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4044 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4048 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4050 setCoords(newCoords);
4051 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4057 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4058 * If it is not the case an exception will be thrown.
4059 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4060 * intersection of plane defined by ('origin','vec').
4061 * This method has one in/out parameter : 'cut3DCurve'.
4062 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4063 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4064 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4065 * This method will throw an exception if 'this' contains a non linear segment.
4067 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4069 checkFullyDefined();
4070 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4071 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4072 int ncells=getNumberOfCells();
4073 int nnodes=getNumberOfNodes();
4074 double vec2[3],vec3[3],vec4[3];
4075 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4077 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4078 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4079 const int *conn=_nodal_connec->getConstPointer();
4080 const int *connI=_nodal_connec_index->getConstPointer();
4081 const double *coo=_coords->getConstPointer();
4082 std::vector<double> addCoo;
4083 for(int i=0;i<ncells;i++)
4085 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4087 if(cut3DCurve[i]==-2)
4089 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4090 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];
4091 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4092 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4093 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4095 const double *st2=coo+3*st;
4096 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4097 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]));
4098 if(pos>eps && pos<1-eps)
4100 int nNode=((int)addCoo.size())/3;
4101 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4102 addCoo.insert(addCoo.end(),vec4,vec4+3);
4103 cut3DCurve[i]=nnodes+nNode;
4109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4113 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4114 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4115 coo2->alloc(newNbOfNodes,3);
4116 double *tmp=coo2->getPointer();
4117 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4118 std::copy(addCoo.begin(),addCoo.end(),tmp);
4119 DataArrayDouble::SetArrayIn(coo2,_coords);
4124 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4125 * @param mesh1D is the input 1D mesh used for translation computation.
4126 * @return newCoords new coords filled by this method.
4128 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4130 int oldNbOfNodes=getNumberOfNodes();
4131 int nbOf1DCells=mesh1D->getNumberOfCells();
4132 int spaceDim=getSpaceDimension();
4133 DataArrayDouble *ret=DataArrayDouble::New();
4134 std::vector<bool> isQuads;
4135 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4136 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4137 double *retPtr=ret->getPointer();
4138 const double *coords=getCoords()->getConstPointer();
4139 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4141 std::vector<double> c;
4145 for(int i=0;i<nbOf1DCells;i++)
4148 mesh1D->getNodeIdsOfCell(i,v);
4150 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4151 mesh1D->getCoordinatesOfNode(v[0],c);
4152 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4153 for(int j=0;j<oldNbOfNodes;j++)
4154 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4158 mesh1D->getCoordinatesOfNode(v[1],c);
4159 mesh1D->getCoordinatesOfNode(v[0],c);
4160 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4161 for(int j=0;j<oldNbOfNodes;j++)
4162 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4165 ret->copyStringInfoFrom(*getCoords());
4170 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4171 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4172 * @return newCoords new coords filled by this method.
4174 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4176 if(mesh1D->getSpaceDimension()==2)
4177 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4178 if(mesh1D->getSpaceDimension()==3)
4179 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4180 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4184 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4185 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4186 * @return newCoords new coords filled by this method.
4188 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4191 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4192 int oldNbOfNodes=getNumberOfNodes();
4193 int nbOf1DCells=mesh1D->getNumberOfCells();
4195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4196 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4197 int nbOfLevsInVec=nbOf1DCells+1;
4198 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4199 double *retPtr=ret->getPointer();
4200 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4201 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4202 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4203 tmp->setCoords(tmp2);
4204 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4205 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4206 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4207 for(int i=1;i<nbOfLevsInVec;i++)
4209 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4210 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4211 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4212 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4213 tmp->translate(vec);
4214 double tmp3[2],radius,alpha,alpha0;
4215 const double *p0=i+1<nbOfLevsInVec?begin:third;
4216 const double *p1=i+1<nbOfLevsInVec?end:begin;
4217 const double *p2=i+1<nbOfLevsInVec?third:end;
4218 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4219 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]);
4220 double angle=acos(cosangle/(radius*radius));
4221 tmp->rotate(end,0,angle);
4222 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4228 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4229 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4230 * @return newCoords new coords filled by this method.
4232 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4235 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4236 int oldNbOfNodes=getNumberOfNodes();
4237 int nbOf1DCells=mesh1D->getNumberOfCells();
4239 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4240 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4241 int nbOfLevsInVec=nbOf1DCells+1;
4242 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4243 double *retPtr=ret->getPointer();
4244 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4245 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4246 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4247 tmp->setCoords(tmp2);
4248 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4249 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4250 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4251 for(int i=1;i<nbOfLevsInVec;i++)
4253 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4254 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4255 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4256 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4257 tmp->translate(vec);
4258 double tmp3[2],radius,alpha,alpha0;
4259 const double *p0=i+1<nbOfLevsInVec?begin:third;
4260 const double *p1=i+1<nbOfLevsInVec?end:begin;
4261 const double *p2=i+1<nbOfLevsInVec?third:end;
4262 double vecPlane[3]={
4263 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4264 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4265 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4267 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4270 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4271 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4272 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4274 double c2=cos(asin(s2));
4276 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4277 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4278 {-vec2[1]*s2, vec2[0]*s2, c2}
4280 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]};
4281 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]};
4282 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]};
4283 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4284 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]);
4285 double angle=acos(cosangle/(radius*radius));
4286 tmp->rotate(end,vecPlane,angle);
4289 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4295 * This method is private because not easy to use for end user. This method is const contrary to
4296 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4297 * the coords sorted slice by slice.
4298 * @param isQuad specifies presence of quadratic cells.
4300 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4302 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4303 int nbOf2DCells=getNumberOfCells();
4304 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4305 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4306 const int *conn=_nodal_connec->getConstPointer();
4307 const int *connI=_nodal_connec_index->getConstPointer();
4308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4310 newConnI->alloc(nbOf3DCells+1,1);
4311 int *newConnIPtr=newConnI->getPointer();
4313 std::vector<int> newc;
4314 for(int j=0;j<nbOf2DCells;j++)
4316 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4317 *newConnIPtr++=(int)newc.size();
4319 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4320 int *newConnPtr=newConn->getPointer();
4321 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4322 newConnIPtr=newConnI->getPointer();
4323 for(int iz=0;iz<nbOf1DCells;iz++)
4326 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4327 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4329 int icell=(int)(iter-newc.begin());
4330 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4333 *newConnPtr=(*iter)+iz*deltaPerLev;
4338 *newConnPtr=(*iter);
4341 ret->setConnectivity(newConn,newConnI,true);
4342 ret->setCoords(getCoords());
4347 * This method returns if 'this' is constituted by only quadratic cells.
4349 bool MEDCouplingUMesh::isFullyQuadratic() const
4351 checkFullyDefined();
4353 int nbOfCells=getNumberOfCells();
4354 for(int i=0;i<nbOfCells && ret;i++)
4356 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4357 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4358 ret=cm.isQuadratic();
4364 * This method returns if there is at least one quadratic cell.
4366 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4368 checkFullyDefined();
4370 int nbOfCells=getNumberOfCells();
4371 for(int i=0;i<nbOfCells && !ret;i++)
4373 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4374 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4375 ret=cm.isQuadratic();
4381 * This method convert quadratic cells to linear cells if any was found.
4382 * If no such cells exists 'this' remains unchanged.
4384 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4386 checkFullyDefined();
4387 int nbOfCells=getNumberOfCells();
4389 for(int i=0;i<nbOfCells;i++)
4391 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4392 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4393 if(cm.isQuadratic())
4395 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4396 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4397 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4404 newConn->alloc(getMeshLength()-delta,1);
4405 newConnI->alloc(nbOfCells+1,1);
4406 const int *icptr=_nodal_connec->getConstPointer();
4407 const int *iciptr=_nodal_connec_index->getConstPointer();
4408 int *ocptr=newConn->getPointer();
4409 int *ociptr=newConnI->getPointer();
4412 for(int i=0;i<nbOfCells;i++,ociptr++)
4414 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4415 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4416 if(!cm.isQuadratic())
4418 _types.insert(type);
4419 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4420 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4424 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4425 _types.insert(typel);
4426 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4427 int newNbOfNodes=cml.getNumberOfNodes();
4428 *ocptr++=(int)typel;
4429 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4430 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4433 setConnectivity(newConn,newConnI,false);
4437 * This method converts all linear cell in \a this to quadratic one.
4438 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4439 * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
4440 * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
4441 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4442 * end of the existing coordinates.
4444 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4445 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4446 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4448 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4450 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4452 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4454 DataArrayInt *conn=0,*connI=0;
4455 DataArrayDouble *coords=0;
4456 std::set<INTERP_KERNEL::NormalizedCellType> types;
4457 checkFullyDefined();
4458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4459 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4460 int meshDim=getMeshDimension();
4461 switch(conversionType)
4467 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4468 connSafe=conn; connISafe=connI; coordsSafe=coords;
4471 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4472 connSafe=conn; connISafe=connI; coordsSafe=coords;
4475 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4476 connSafe=conn; connISafe=connI; coordsSafe=coords;
4479 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4487 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4488 connSafe=conn; connISafe=connI; coordsSafe=coords;
4491 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4492 connSafe=conn; connISafe=connI; coordsSafe=coords;
4495 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4496 connSafe=conn; connISafe=connI; coordsSafe=coords;
4499 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4504 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4506 setConnectivity(connSafe,connISafe,false);
4508 setCoords(coordsSafe);
4513 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4514 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4515 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4517 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4519 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4520 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4521 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4522 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4523 int nbOfCells=getNumberOfCells();
4524 int nbOfNodes=getNumberOfNodes();
4525 const int *cPtr=_nodal_connec->getConstPointer();
4526 const int *icPtr=_nodal_connec_index->getConstPointer();
4527 int lastVal=0,offset=nbOfNodes;
4528 for(int i=0;i<nbOfCells;i++,icPtr++)
4530 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4531 if(type==INTERP_KERNEL::NORM_SEG2)
4533 types.insert(INTERP_KERNEL::NORM_SEG3);
4534 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4535 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4536 newConn->pushBackSilent(offset++);
4538 newConnI->pushBackSilent(lastVal);
4539 ret->pushBackSilent(i);
4544 lastVal+=(icPtr[1]-icPtr[0]);
4545 newConnI->pushBackSilent(lastVal);
4546 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4549 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4550 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4554 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4556 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4560 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4561 DataArrayInt *conn1D=0,*conn1DI=0;
4562 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4563 DataArrayDouble *coordsTmp=0;
4564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4565 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4567 const int *c1DPtr=conn1D->begin();
4568 const int *c1DIPtr=conn1DI->begin();
4569 int nbOfCells=getNumberOfCells();
4570 const int *cPtr=_nodal_connec->getConstPointer();
4571 const int *icPtr=_nodal_connec_index->getConstPointer();
4573 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4575 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4576 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4577 if(!cm.isQuadratic())
4579 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4580 types.insert(typ2); newConn->pushBackSilent(typ2);
4581 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4582 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4583 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4584 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4585 newConnI->pushBackSilent(lastVal);
4586 ret->pushBackSilent(i);
4591 lastVal+=(icPtr[1]-icPtr[0]);
4592 newConnI->pushBackSilent(lastVal);
4593 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4596 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4601 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4602 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4603 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4605 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4608 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4609 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4610 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4613 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4616 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4618 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4619 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4620 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4622 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4623 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4624 DataArrayInt *conn1D=0,*conn1DI=0;
4625 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4626 DataArrayDouble *coordsTmp=0;
4627 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4628 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4630 const int *c1DPtr=conn1D->begin();
4631 const int *c1DIPtr=conn1DI->begin();
4632 int nbOfCells=getNumberOfCells();
4633 const int *cPtr=_nodal_connec->getConstPointer();
4634 const int *icPtr=_nodal_connec_index->getConstPointer();
4635 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4636 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4638 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4639 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4640 if(!cm.isQuadratic())
4642 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4643 types.insert(typ2); newConn->pushBackSilent(typ2);
4644 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4645 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4646 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4647 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4648 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4649 newConnI->pushBackSilent(lastVal);
4650 ret->pushBackSilent(i);
4655 lastVal+=(icPtr[1]-icPtr[0]);
4656 newConnI->pushBackSilent(lastVal);
4657 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4660 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4661 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4666 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4667 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4668 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4670 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4672 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4673 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4674 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4677 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4680 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
4681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
4682 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
4684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
4688 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4689 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
4690 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
4691 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
4692 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
4693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
4694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4695 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
4697 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
4698 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
4699 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
4700 int nbOfCells=getNumberOfCells();
4701 const int *cPtr=_nodal_connec->getConstPointer();
4702 const int *icPtr=_nodal_connec_index->getConstPointer();
4703 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4704 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
4706 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4707 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4708 if(!cm.isQuadratic())
4710 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4711 if(typ2==INTERP_KERNEL::NORM_ERROR)
4713 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
4714 throw INTERP_KERNEL::Exception(oss.str().c_str());
4716 types.insert(typ2); newConn->pushBackSilent(typ2);
4717 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4718 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4719 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4720 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
4722 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
4723 int tmpPos=newConn->getNumberOfTuples();
4724 newConn->pushBackSilent(nodeId2);
4725 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
4727 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4728 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
4729 newConnI->pushBackSilent(lastVal);
4730 ret->pushBackSilent(i);
4735 lastVal+=(icPtr[1]-icPtr[0]);
4736 newConnI->pushBackSilent(lastVal);
4737 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4740 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
4741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
4742 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
4743 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4744 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
4745 int *c=newConn->getPointer();
4746 const int *cI(newConnI->begin());
4747 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
4748 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
4749 offset=coordsTmp2Safe->getNumberOfTuples();
4750 for(const int *elt=ret->begin();elt!=ret->end();elt++)
4751 c[cI[(*elt)+1]-1]+=offset;
4752 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
4757 * This method tessallates 'this' so that the number of cells remains the same.
4758 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4759 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4761 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4762 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4764 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4766 checkFullyDefined();
4767 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4768 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4769 double epsa=fabs(eps);
4770 if(epsa<std::numeric_limits<double>::min())
4771 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 !");
4772 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4776 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4777 revDesc1=0; revDescIndx1=0;
4778 mDesc->tessellate2DCurve(eps);
4779 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4780 setCoords(mDesc->getCoords());
4784 * This method tessallates 'this' so that the number of cells remains the same.
4785 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4786 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4788 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4789 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4791 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4793 checkFullyDefined();
4794 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4796 double epsa=fabs(eps);
4797 if(epsa<std::numeric_limits<double>::min())
4798 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 !");
4799 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4800 int nbCells=getNumberOfCells();
4801 int nbNodes=getNumberOfNodes();
4802 const int *conn=_nodal_connec->getConstPointer();
4803 const int *connI=_nodal_connec_index->getConstPointer();
4804 const double *coords=_coords->getConstPointer();
4805 std::vector<double> addCoo;
4806 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
4807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
4808 newConnI->alloc(nbCells+1,1);
4809 int *newConnIPtr=newConnI->getPointer();
4812 INTERP_KERNEL::Node *tmp2[3];
4813 std::set<INTERP_KERNEL::NormalizedCellType> types;
4814 for(int i=0;i<nbCells;i++,newConnIPtr++)
4816 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4817 if(cm.isQuadratic())
4818 {//assert(connI[i+1]-connI[i]-1==3)
4819 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4820 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4821 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4822 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4823 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4826 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4827 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4829 newConnIPtr[1]=(int)newConn.size();
4833 types.insert(INTERP_KERNEL::NORM_SEG2);
4834 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4835 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4836 newConnIPtr[1]=newConnIPtr[0]+3;
4841 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4842 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4843 newConnIPtr[1]=newConnIPtr[0]+3;
4846 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4849 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4851 newConnArr->alloc((int)newConn.size(),1);
4852 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4853 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4854 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4855 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4856 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4857 std::copy(addCoo.begin(),addCoo.end(),work);
4858 DataArrayDouble::SetArrayIn(newCoords,_coords);
4863 * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4864 * This cut into simplex is performed following the parameter \a policy. This method so typically increases the number of cells of \a this.
4865 * This method \b keeps the number of nodes \b unchanged. That's why the splitting policy in 3D INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4866 * This method returns new2old newly allocated array that specifies a each cell of \a this after the call what was its id it comes.
4868 * The semantic of \a policy parameter :
4869 * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4870 * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4871 * - PLANAR_FACE_5 only HEXA8. All HEXA8 are split into 5 TETRA4
4872 * - PLANAR_FACE_6 only HEXA8. All HEXA8 are split into 6 TETRA4
4874 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4879 return simplexizePol0();
4881 return simplexizePol1();
4882 case (int) INTERP_KERNEL::PLANAR_FACE_5:
4883 return simplexizePlanarFace5();
4884 case (int) INTERP_KERNEL::PLANAR_FACE_6:
4885 return simplexizePlanarFace6();
4887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n - 0 or 1 (only available for meshdim=2) \n - PLANAR_FACE_5, PLANAR_FACE_6 (only for meshdim=3)");
4891 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4893 checkFullyDefined();
4894 if(getMeshDimension()<1)
4895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4896 int nbCells=getNumberOfCells();
4897 const int *conn=_nodal_connec->getConstPointer();
4898 const int *connI=_nodal_connec_index->getConstPointer();
4899 for(int i=0;i<nbCells;i++)
4901 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4909 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4911 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4913 checkConnectivityFullyDefined();
4914 if(getMeshDimension()!=2)
4915 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4916 int nbOfCells=getNumberOfCells();
4917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4918 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4919 ret->alloc(nbOfCells+nbOfCutCells,1);
4920 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4921 int *retPt=ret->getPointer();
4922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4923 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4924 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4925 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4926 int *pt=newConn->getPointer();
4927 int *ptI=newConnI->getPointer();
4929 const int *oldc=_nodal_connec->getConstPointer();
4930 const int *ci=_nodal_connec_index->getConstPointer();
4931 for(int i=0;i<nbOfCells;i++,ci++)
4933 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4935 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4936 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4937 pt=std::copy(tmp,tmp+8,pt);
4946 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4947 ptI[1]=ptI[0]+ci[1]-ci[0];
4952 _nodal_connec->decrRef();
4953 _nodal_connec=newConn.retn();
4954 _nodal_connec_index->decrRef();
4955 _nodal_connec_index=newConnI.retn();
4962 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4964 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4966 checkConnectivityFullyDefined();
4967 if(getMeshDimension()!=2)
4968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4969 int nbOfCells=getNumberOfCells();
4970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4971 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4972 ret->alloc(nbOfCells+nbOfCutCells,1);
4973 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4974 int *retPt=ret->getPointer();
4975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4977 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4978 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4979 int *pt=newConn->getPointer();
4980 int *ptI=newConnI->getPointer();
4982 const int *oldc=_nodal_connec->getConstPointer();
4983 const int *ci=_nodal_connec_index->getConstPointer();
4984 for(int i=0;i<nbOfCells;i++,ci++)
4986 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4988 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4989 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4990 pt=std::copy(tmp,tmp+8,pt);
4999 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5000 ptI[1]=ptI[0]+ci[1]-ci[0];
5005 _nodal_connec->decrRef();
5006 _nodal_connec=newConn.retn();
5007 _nodal_connec_index->decrRef();
5008 _nodal_connec_index=newConnI.retn();
5015 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5017 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5019 checkConnectivityFullyDefined();
5020 if(getMeshDimension()!=3)
5021 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5022 int nbOfCells=getNumberOfCells();
5023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5024 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5025 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5026 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5027 int *retPt=ret->getPointer();
5028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5029 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5030 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5031 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5032 int *pt=newConn->getPointer();
5033 int *ptI=newConnI->getPointer();
5035 const int *oldc=_nodal_connec->getConstPointer();
5036 const int *ci=_nodal_connec_index->getConstPointer();
5037 for(int i=0;i<nbOfCells;i++,ci++)
5039 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5041 for(int j=0;j<5;j++,pt+=5,ptI++)
5043 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5044 pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5051 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5052 ptI[1]=ptI[0]+ci[1]-ci[0];
5057 _nodal_connec->decrRef();
5058 _nodal_connec=newConn.retn();
5059 _nodal_connec_index->decrRef();
5060 _nodal_connec_index=newConnI.retn();
5067 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5069 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5071 checkConnectivityFullyDefined();
5072 if(getMeshDimension()!=3)
5073 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5074 int nbOfCells=getNumberOfCells();
5075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5076 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5077 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5078 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5079 int *retPt=ret->getPointer();
5080 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5082 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5083 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5084 int *pt=newConn->getPointer();
5085 int *ptI=newConnI->getPointer();
5087 const int *oldc=_nodal_connec->getConstPointer();
5088 const int *ci=_nodal_connec_index->getConstPointer();
5089 for(int i=0;i<nbOfCells;i++,ci++)
5091 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5093 for(int j=0;j<6;j++,pt+=5,ptI++)
5095 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5096 pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5103 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5104 ptI[1]=ptI[0]+ci[1]-ci[0];
5109 _nodal_connec->decrRef();
5110 _nodal_connec=newConn.retn();
5111 _nodal_connec_index->decrRef();
5112 _nodal_connec_index=newConnI.retn();
5119 * 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.
5120 * This method completly ignore coordinates.
5121 * @param nodeSubdived is the nodal connectivity of subdivision of edges
5122 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5123 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5124 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5126 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5128 checkFullyDefined();
5129 if(getMeshDimension()!=2)
5130 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5131 int nbOfCells=getNumberOfCells();
5132 int *connI=_nodal_connec_index->getPointer();
5134 for(int i=0;i<nbOfCells;i++,connI++)
5136 int offset=descIndex[i];
5137 int nbOfEdges=descIndex[i+1]-offset;
5139 bool ddirect=desc[offset+nbOfEdges-1]>0;
5140 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5141 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5142 for(int j=0;j<nbOfEdges;j++)
5144 bool direct=desc[offset+j]>0;
5145 int edgeId=std::abs(desc[offset+j])-1;
5146 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5148 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5149 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5150 int ref2=direct?id1:id2;
5153 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5154 newConnLgth+=nbOfSubNodes-1;
5159 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5160 throw INTERP_KERNEL::Exception(oss.str().c_str());
5165 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5168 newConnLgth++;//+1 is for cell type
5169 connI[1]=newConnLgth;
5172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5173 newConn->alloc(newConnLgth,1);
5174 int *work=newConn->getPointer();
5175 for(int i=0;i<nbOfCells;i++)
5177 *work++=INTERP_KERNEL::NORM_POLYGON;
5178 int offset=descIndex[i];
5179 int nbOfEdges=descIndex[i+1]-offset;
5180 for(int j=0;j<nbOfEdges;j++)
5182 bool direct=desc[offset+j]>0;
5183 int edgeId=std::abs(desc[offset+j])-1;
5185 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5188 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5189 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5190 work=std::copy(it,it+nbOfSubNodes-1,work);
5194 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5197 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5201 * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
5202 * nodal connectivity will be transform to a NORM_TRI3 cell.
5203 * This method works \b only \b on \b linear cells.
5204 * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
5205 * method could be useful before calling this method in case of presence of several pair of nodes located on same position.
5206 * This method throws an exception if 'this' is not fully defined (connectivity).
5207 * 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.
5209 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5211 checkFullyDefined();
5212 if(getMeshDimension()<=1)
5213 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5214 int nbOfCells=getNumberOfCells();
5217 int initMeshLgth=getMeshLength();
5218 int *conn=_nodal_connec->getPointer();
5219 int *index=_nodal_connec_index->getPointer();
5223 for(int i=0;i<nbOfCells;i++)
5225 lgthOfCurCell=index[i+1]-posOfCurCell;
5226 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5228 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5229 conn+newPos+1,newLgth);
5230 conn[newPos]=newType;
5232 posOfCurCell=index[i+1];
5235 if(newPos!=initMeshLgth)
5236 _nodal_connec->reAlloc(newPos);
5241 * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5242 * The 'vec' vector has to have a non nul norm.
5243 * If not 'cells' parameter will be appended with cellIds of incorrect cells.
5244 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5246 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5248 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5249 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5250 int nbOfCells=getNumberOfCells();
5251 const int *conn=_nodal_connec->getConstPointer();
5252 const int *connI=_nodal_connec_index->getConstPointer();
5253 const double *coordsPtr=_coords->getConstPointer();
5254 for(int i=0;i<nbOfCells;i++)
5256 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5257 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5259 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5260 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5267 * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5268 * The 'vec' vector has to have a non nul norm.
5269 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5271 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5273 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5274 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5275 int nbOfCells=getNumberOfCells();
5276 int *conn=_nodal_connec->getPointer();
5277 const int *connI=_nodal_connec_index->getConstPointer();
5278 const double *coordsPtr=_coords->getConstPointer();
5279 bool isModified=false;
5280 for(int i=0;i<nbOfCells;i++)
5282 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5283 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5285 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5286 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5289 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5290 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5291 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5296 _nodal_connec->declareAsNew();
5301 * This method checks that all polyhedrons cells have correctly oriented faces.
5302 * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
5303 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
5305 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5307 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5308 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5309 int nbOfCells=getNumberOfCells();
5310 const int *conn=_nodal_connec->getConstPointer();
5311 const int *connI=_nodal_connec_index->getConstPointer();
5312 const double *coordsPtr=_coords->getConstPointer();
5313 for(int i=0;i<nbOfCells;i++)
5315 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5316 if(type==INTERP_KERNEL::NORM_POLYHED)
5318 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5325 * This method tries to orient correctly polhedrons cells.
5327 * \throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
5328 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5330 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5332 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5333 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5334 int nbOfCells=getNumberOfCells();
5335 int *conn=_nodal_connec->getPointer();
5336 const int *connI=_nodal_connec_index->getConstPointer();
5337 const double *coordsPtr=_coords->getConstPointer();
5338 for(int i=0;i<nbOfCells;i++)
5340 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5341 if(type==INTERP_KERNEL::NORM_POLYHED)
5345 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5346 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5348 catch(INTERP_KERNEL::Exception& e)
5350 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5351 throw INTERP_KERNEL::Exception(oss.str().c_str());
5359 * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
5360 * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
5361 * 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).
5362 * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
5364 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5365 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5367 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5369 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5370 if(getMeshDimension()!=3)
5371 throw INTERP_KERNEL::Exception(msg);
5372 int spaceDim=getSpaceDimension();
5374 throw INTERP_KERNEL::Exception(msg);
5376 int nbOfCells=getNumberOfCells();
5377 int *conn=_nodal_connec->getPointer();
5378 const int *connI=_nodal_connec_index->getConstPointer();
5379 const double *coo=getCoords()->getConstPointer();
5380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5381 for(int i=0;i<nbOfCells;i++)
5383 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5384 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5386 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5388 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5389 cells->pushBackSilent(i);
5393 return cells.retn();
5397 * This method is a faster method to correct orientation of all 3D cells in \a this.
5398 * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
5399 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5401 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5402 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5404 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5406 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5407 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5408 int nbOfCells=getNumberOfCells();
5409 int *conn=_nodal_connec->getPointer();
5410 const int *connI=_nodal_connec_index->getConstPointer();
5411 const double *coordsPtr=_coords->getConstPointer();
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5413 for(int i=0;i<nbOfCells;i++)
5415 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5418 case INTERP_KERNEL::NORM_TETRA4:
5420 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5422 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5423 ret->pushBackSilent(i);
5427 case INTERP_KERNEL::NORM_PYRA5:
5429 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5431 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5432 ret->pushBackSilent(i);
5436 case INTERP_KERNEL::NORM_PENTA6:
5437 case INTERP_KERNEL::NORM_HEXA8:
5438 case INTERP_KERNEL::NORM_HEXGP12:
5440 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5442 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5443 ret->pushBackSilent(i);
5447 case INTERP_KERNEL::NORM_POLYHED:
5449 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5451 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5452 ret->pushBackSilent(i);
5457 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
5465 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5466 * If it is not the case an exception will be thrown.
5467 * This method is fast because the first cell of 'this' is used to compute the plane.
5468 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5469 * @param pos output of size at least 3 used to store a point owned of searched plane.
5471 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5473 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5474 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5475 const int *conn=_nodal_connec->getConstPointer();
5476 const int *connI=_nodal_connec_index->getConstPointer();
5477 const double *coordsPtr=_coords->getConstPointer();
5478 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5479 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5483 * The returned newly created field has to be managed by the caller.
5484 * 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.
5485 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5486 * If a cell has an another type an exception will be thrown.
5488 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5491 int spaceDim=getSpaceDimension();
5492 int meshDim=getMeshDimension();
5493 if(spaceDim!=2 && spaceDim!=3)
5494 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5495 if(meshDim!=2 && meshDim!=3)
5496 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5497 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5499 int nbOfCells=getNumberOfCells();
5500 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5501 arr->alloc(nbOfCells,1);
5502 double *pt=arr->getPointer();
5503 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5504 const int *conn=_nodal_connec->getConstPointer();
5505 const int *connI=_nodal_connec_index->getConstPointer();
5506 const double *coo=_coords->getConstPointer();
5508 for(int i=0;i<nbOfCells;i++,pt++)
5510 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5513 case INTERP_KERNEL::NORM_TRI3:
5515 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5516 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5519 case INTERP_KERNEL::NORM_QUAD4:
5521 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5522 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5525 case INTERP_KERNEL::NORM_TETRA4:
5527 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5528 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5532 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5534 conn+=connI[i+1]-connI[i];
5536 ret->setName("EdgeRatio");
5537 ret->synchronizeTimeWithSupport();
5542 * The returned newly created field has to be managed by the caller.
5543 * 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.
5544 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5545 * If a cell has an another type an exception will be thrown.
5547 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5550 int spaceDim=getSpaceDimension();
5551 int meshDim=getMeshDimension();
5552 if(spaceDim!=2 && spaceDim!=3)
5553 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5554 if(meshDim!=2 && meshDim!=3)
5555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5556 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5558 int nbOfCells=getNumberOfCells();
5559 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5560 arr->alloc(nbOfCells,1);
5561 double *pt=arr->getPointer();
5562 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5563 const int *conn=_nodal_connec->getConstPointer();
5564 const int *connI=_nodal_connec_index->getConstPointer();
5565 const double *coo=_coords->getConstPointer();
5567 for(int i=0;i<nbOfCells;i++,pt++)
5569 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5572 case INTERP_KERNEL::NORM_TRI3:
5574 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5575 *pt=INTERP_KERNEL::triAspectRatio(tmp);
5578 case INTERP_KERNEL::NORM_QUAD4:
5580 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5581 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5584 case INTERP_KERNEL::NORM_TETRA4:
5586 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5587 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5591 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5593 conn+=connI[i+1]-connI[i];
5595 ret->setName("AspectRatio");
5596 ret->synchronizeTimeWithSupport();
5601 * The returned newly created field has to be managed by the caller.
5602 * 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.
5603 * This method for the moment only deals with NORM_QUAD4 geometric type.
5604 * If a cell has an another type an exception will be thrown.
5606 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
5609 int spaceDim=getSpaceDimension();
5610 int meshDim=getMeshDimension();
5612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5614 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5615 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5617 int nbOfCells=getNumberOfCells();
5618 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5619 arr->alloc(nbOfCells,1);
5620 double *pt=arr->getPointer();
5621 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5622 const int *conn=_nodal_connec->getConstPointer();
5623 const int *connI=_nodal_connec_index->getConstPointer();
5624 const double *coo=_coords->getConstPointer();
5626 for(int i=0;i<nbOfCells;i++,pt++)
5628 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5631 case INTERP_KERNEL::NORM_QUAD4:
5633 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5634 *pt=INTERP_KERNEL::quadWarp(tmp);
5638 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5640 conn+=connI[i+1]-connI[i];
5642 ret->setName("Warp");
5643 ret->synchronizeTimeWithSupport();
5648 * The returned newly created field has to be managed by the caller.
5649 * 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.
5650 * This method for the moment only deals with NORM_QUAD4 geometric type.
5651 * If a cell has an another type an exception will be thrown.
5653 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5656 int spaceDim=getSpaceDimension();
5657 int meshDim=getMeshDimension();
5659 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5664 int nbOfCells=getNumberOfCells();
5665 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5666 arr->alloc(nbOfCells,1);
5667 double *pt=arr->getPointer();
5668 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5669 const int *conn=_nodal_connec->getConstPointer();
5670 const int *connI=_nodal_connec_index->getConstPointer();
5671 const double *coo=_coords->getConstPointer();
5673 for(int i=0;i<nbOfCells;i++,pt++)
5675 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5678 case INTERP_KERNEL::NORM_QUAD4:
5680 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5681 *pt=INTERP_KERNEL::quadSkew(tmp);
5685 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5687 conn+=connI[i+1]-connI[i];
5689 ret->setName("Skew");
5690 ret->synchronizeTimeWithSupport();
5695 * This method aggregate the bbox of each cell and put it into bbox parameter.
5696 * @param bbox out parameter of size 2*spacedim*nbOfcells.
5698 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5700 int spaceDim=getSpaceDimension();
5701 int nbOfCells=getNumberOfCells();
5702 bbox.resize(2*nbOfCells*spaceDim);
5703 for(int i=0;i<nbOfCells*spaceDim;i++)
5705 bbox[2*i]=std::numeric_limits<double>::max();
5706 bbox[2*i+1]=-std::numeric_limits<double>::max();
5708 const double *coordsPtr=_coords->getConstPointer();
5709 const int *conn=_nodal_connec->getConstPointer();
5710 const int *connI=_nodal_connec_index->getConstPointer();
5711 for(int i=0;i<nbOfCells;i++)
5713 int offset=connI[i]+1;
5714 int nbOfNodesForCell=connI[i+1]-offset;
5715 for(int j=0;j<nbOfNodesForCell;j++)
5717 int nodeId=conn[offset+j];
5719 for(int k=0;k<spaceDim;k++)
5721 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5722 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5730 namespace ParaMEDMEMImpl
5735 ConnReader(const int *c, int val):_conn(c),_val(val) { }
5736 bool operator() (const int& pos) { return _conn[pos]!=_val; }
5745 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5746 bool operator() (const int& pos) { return _conn[pos]==_val; }
5756 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5757 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5758 * 'this' is composed in cell types.
5759 * The returned array is of size 3*n where n is the number of different types present in 'this'.
5760 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
5761 * This parameter is kept only for compatibility with other methode listed above.
5763 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5765 checkConnectivityFullyDefined();
5766 const int *conn=_nodal_connec->getConstPointer();
5767 const int *connI=_nodal_connec_index->getConstPointer();
5768 const int *work=connI;
5769 int nbOfCells=getNumberOfCells();
5770 std::size_t n=getAllTypes().size();
5771 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5772 std::set<INTERP_KERNEL::NormalizedCellType> types;
5773 for(std::size_t i=0;work!=connI+nbOfCells;i++)
5775 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5776 if(types.find(typ)!=types.end())
5778 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5779 oss << " is not contiguous !";
5780 throw INTERP_KERNEL::Exception(oss.str().c_str());
5784 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5785 ret[3*i+1]=(int)std::distance(work,work2);
5792 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5793 * only for types cell, type node is not managed.
5794 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5795 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5796 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5797 * If 2 or more same geometric type is in 'code' and exception is thrown too.
5799 * This method firstly checks
5800 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5801 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5802 * an exception is thrown too.
5804 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5805 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
5806 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5808 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5811 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5812 std::size_t sz=code.size();
5815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5816 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5818 for(std::size_t i=0;i<n;i++)
5819 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5821 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5823 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5828 if(idsPerType.empty())
5830 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5831 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5832 if(types.size()==_types.size())
5835 DataArrayInt *ret=DataArrayInt::New();
5837 int *retPtr=ret->getPointer();
5838 const int *connI=_nodal_connec_index->getConstPointer();
5839 const int *conn=_nodal_connec->getConstPointer();
5840 int nbOfCells=getNumberOfCells();
5843 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5845 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5846 int offset=(int)std::distance(connI,i);
5847 if(code[3*kk+2]==-1)
5849 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5850 std::size_t pos2=std::distance(i,j);
5851 for(std::size_t k=0;k<pos2;k++)
5852 *retPtr++=(int)k+offset;
5857 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5858 retPtr,std::bind2nd(std::plus<int>(),offset));
5865 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
5866 * This method is the opposite of MEDCouplingUMesh::checkTypeConsistencyAndContig method. Given a list of cells in \a profile it returns a list of sub-profiles sorted by geo type.
5867 * The result is put in the array \a idsPerType. In the returned parameter \a code, foreach i \a code[3*i+2] refers (if different from -1) to a location into the \a idsPerType.
5868 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
5870 * @param [out] code is a vector of size 3*n where n is the number of different geometric type in \a this \b reduced to the profile \a profile. \a code has exactly the same semantic than in MEDCouplingUMesh::checkTypeConsistencyAndContig method.
5871 * @param [out] idsInPflPerType is a vector of size of different geometric type in the subpart defined by \a profile of \a this ( equal to \a code.size()/3). For each i,
5872 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5873 * @param [out] idsPerType is a vector of size of different sub profiles needed to be defined to represent the profile \a profile for a given geometric type.
5874 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5875 * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
5877 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5879 if(profile->getNumberOfComponents()!=1)
5880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5881 checkConnectivityFullyDefined();
5882 const int *conn=_nodal_connec->getConstPointer();
5883 const int *connI=_nodal_connec_index->getConstPointer();
5884 int nbOfCells=getNumberOfCells();
5885 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5886 std::vector<int> typeRangeVals(1);
5887 for(const int *i=connI;i!=connI+nbOfCells;)
5889 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5890 if(std::find(types.begin(),types.end(),curType)!=types.end())
5892 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5894 types.push_back(curType);
5895 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5896 typeRangeVals.push_back((int)std::distance(connI,i));
5899 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5900 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5905 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5906 code.resize(3*nbOfCastsFinal);
5907 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5908 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5909 for(int i=0;i<nbOfCastsFinal;i++)
5911 int castId=castsPresent->getIJ(i,0);
5912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5913 idsInPflPerType2.push_back(tmp3);
5914 code[3*i]=(int)types[castId];
5915 code[3*i+1]=tmp3->getNumberOfTuples();
5916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5917 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5919 tmp4->copyStringInfoFrom(*profile);
5920 idsPerType2.push_back(tmp4);
5921 code[3*i+2]=(int)idsPerType2.size()-1;
5928 std::size_t sz2=idsInPflPerType2.size();
5929 idsInPflPerType.resize(sz2);
5930 for(std::size_t i=0;i<sz2;i++)
5932 DataArrayInt *locDa=idsInPflPerType2[i];
5934 idsInPflPerType[i]=locDa;
5936 std::size_t sz=idsPerType2.size();
5937 idsPerType.resize(sz);
5938 for(std::size_t i=0;i<sz;i++)
5940 DataArrayInt *locDa=idsPerType2[i];
5942 idsPerType[i]=locDa;
5947 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5948 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5949 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5950 * 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.
5952 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5954 checkFullyDefined();
5955 nM1LevMesh->checkFullyDefined();
5956 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5957 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5958 if(_coords!=nM1LevMesh->getCoords())
5959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5964 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5965 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5966 tmp->setConnectivity(tmp0,tmp1);
5967 tmp->renumberCells(ret0->getConstPointer(),false);
5968 revDesc=tmp->getNodalConnectivity();
5969 revDescIndx=tmp->getNodalConnectivityIndex();
5970 DataArrayInt *ret=0;
5971 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5974 ret->getMaxValue(tmp2);
5976 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5977 throw INTERP_KERNEL::Exception(oss.str().c_str());
5982 revDescIndx->incrRef();
5985 meshnM1Old2New=ret0;
5990 * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5991 * It avoids to deal with renum in MEDLoader so it is useful for MED file R/W with multi types.
5992 * This method returns a newly allocated array old2New.
5993 * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5995 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5997 checkConnectivityFullyDefined();
5998 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5999 renumberCells(ret->getConstPointer(),false);
6004 * This methods checks that cells are sorted by their types.
6005 * This method makes asumption (no check) that connectivity is correctly set before calling.
6007 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6009 checkFullyDefined();
6010 const int *conn=_nodal_connec->getConstPointer();
6011 const int *connI=_nodal_connec_index->getConstPointer();
6012 int nbOfCells=getNumberOfCells();
6013 std::set<INTERP_KERNEL::NormalizedCellType> types;
6014 for(const int *i=connI;i!=connI+nbOfCells;)
6016 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6017 if(types.find(curType)!=types.end())
6019 types.insert(curType);
6020 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6026 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6027 * The geometric type order is specified by MED file.
6029 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6031 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6033 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6037 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6038 * that the order is specified in array defined by [orderBg,orderEnd).
6039 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6040 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6042 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6044 checkFullyDefined();
6045 const int *conn=_nodal_connec->getConstPointer();
6046 const int *connI=_nodal_connec_index->getConstPointer();
6047 int nbOfCells=getNumberOfCells();
6051 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6052 for(const int *i=connI;i!=connI+nbOfCells;)
6054 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6055 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6056 if(isTypeExists!=orderEnd)
6058 int pos=(int)std::distance(orderBg,isTypeExists);
6062 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6066 if(sg.find(curType)==sg.end())
6068 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6079 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6080 * 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
6081 * 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'.
6083 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6085 checkConnectivityFullyDefined();
6086 int nbOfCells=getNumberOfCells();
6087 const int *conn=_nodal_connec->getConstPointer();
6088 const int *connI=_nodal_connec_index->getConstPointer();
6089 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6091 tmpa->alloc(nbOfCells,1);
6092 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6093 tmpb->fillWithZero();
6094 int *tmp=tmpa->getPointer();
6095 int *tmp2=tmpb->getPointer();
6096 for(const int *i=connI;i!=connI+nbOfCells;i++)
6098 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6101 int pos=(int)std::distance(orderBg,where);
6103 tmp[std::distance(connI,i)]=pos;
6107 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6108 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6109 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6110 throw INTERP_KERNEL::Exception(oss.str().c_str());
6113 nbPerType=tmpb.retn();
6118 * 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'.
6119 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6120 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6121 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6123 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6125 DataArrayInt *nbPerType=0;
6126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6127 nbPerType->decrRef();
6128 return tmpa->buildPermArrPerLevel();
6132 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6133 * The number of cells remains unchanged after the call of this method.
6134 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6135 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6137 * @return the array giving the correspondance old to new.
6139 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6141 checkFullyDefined();
6143 const int *conn=_nodal_connec->getConstPointer();
6144 const int *connI=_nodal_connec_index->getConstPointer();
6145 int nbOfCells=getNumberOfCells();
6146 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6147 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6148 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6150 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6151 types.push_back(curType);
6152 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6154 DataArrayInt *ret=DataArrayInt::New();
6155 ret->alloc(nbOfCells,1);
6156 int *retPtr=ret->getPointer();
6157 std::fill(retPtr,retPtr+nbOfCells,-1);
6159 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6161 for(const int *i=connI;i!=connI+nbOfCells;i++)
6162 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6163 retPtr[std::distance(connI,i)]=newCellId++;
6165 renumberCells(retPtr,false);
6170 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6171 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6172 * This method makes asumption that connectivity is correctly set before calling.
6174 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6176 checkFullyDefined();
6177 const int *conn=_nodal_connec->getConstPointer();
6178 const int *connI=_nodal_connec_index->getConstPointer();
6179 int nbOfCells=getNumberOfCells();
6180 std::vector<MEDCouplingUMesh *> ret;
6181 for(const int *i=connI;i!=connI+nbOfCells;)
6183 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6184 int beginCellId=(int)std::distance(connI,i);
6185 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6186 int endCellId=(int)std::distance(connI,i);
6187 int sz=endCellId-beginCellId;
6188 int *cells=new int[sz];
6189 for(int j=0;j<sz;j++)
6190 cells[j]=beginCellId+j;
6191 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6199 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6200 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6201 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6202 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6203 * are not used here to avoid the build of big permutation array.
6205 * \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
6206 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6207 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6208 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6209 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6210 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6211 * \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
6212 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6214 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6215 DataArrayInt *&szOfCellGrpOfSameType,
6216 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6218 std::vector<const MEDCouplingUMesh *> ms2;
6219 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6222 (*it)->checkConnectivityFullyDefined();
6226 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6227 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6228 int meshDim=ms2[0]->getMeshDimension();
6229 std::vector<const MEDCouplingUMesh *> m1ssm;
6230 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6232 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6233 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6236 ret1->alloc(0,1); ret2->alloc(0,1);
6237 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6239 if(meshDim!=(*it)->getMeshDimension())
6240 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6241 if(refCoo!=(*it)->getCoords())
6242 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6243 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6244 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6245 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6246 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6248 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6249 m1ssmSingleAuto.push_back(singleCell);
6250 m1ssmSingle.push_back(singleCell);
6251 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6254 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6256 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6257 for(std::size_t i=0;i<m1ssm.size();i++)
6258 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6259 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6260 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6261 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6266 * This method returns a newly created DataArrayInt instance.
6267 * This method retrieves cell ids in [begin,end) that have the type 'type'.
6269 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6271 checkFullyDefined();
6272 const int *conn=_nodal_connec->getConstPointer();
6273 const int *connIndex=_nodal_connec_index->getConstPointer();
6274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6275 for(const int *w=begin;w!=end;w++)
6276 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6277 ret->pushBackSilent(*w);
6282 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6283 * are in [0:getNumberOfCells())
6285 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6287 checkFullyDefined();
6288 const int *conn=_nodal_connec->getConstPointer();
6289 const int *connI=_nodal_connec_index->getConstPointer();
6290 int nbOfCells=getNumberOfCells();
6291 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6292 int *tmp=new int[nbOfCells];
6293 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6296 for(const int *i=connI;i!=connI+nbOfCells;i++)
6297 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6298 tmp[std::distance(connI,i)]=j++;
6300 DataArrayInt *ret=DataArrayInt::New();
6301 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6302 ret->copyStringInfoFrom(*da);
6303 int *retPtr=ret->getPointer();
6304 const int *daPtr=da->getConstPointer();
6305 int nbOfElems=da->getNbOfElems();
6306 for(int k=0;k<nbOfElems;k++)
6307 retPtr[k]=tmp[daPtr[k]];
6313 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6314 * This method \b works \b for mesh sorted by type.
6315 * cells whose ids is in 'idsPerGeoType' array.
6316 * This method conserves coords and name of mesh.
6318 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6320 std::vector<int> code=getDistributionOfTypes();
6321 std::size_t nOfTypesInThis=code.size()/3;
6322 int sz=0,szOfType=0;
6323 for(std::size_t i=0;i<nOfTypesInThis;i++)
6328 szOfType=code[3*i+1];
6330 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6331 if(*work<0 || *work>=szOfType)
6333 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6334 oss << ". It should be in [0," << szOfType << ") !";
6335 throw INTERP_KERNEL::Exception(oss.str().c_str());
6337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6338 int *idsPtr=idsTokeep->getPointer();
6340 for(std::size_t i=0;i<nOfTypesInThis;i++)
6343 for(int j=0;j<code[3*i+1];j++)
6346 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6347 offset+=code[3*i+1];
6349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6350 ret->copyTinyInfoFrom(this);
6355 * This method returns a vector of size 'this->getNumberOfCells()'.
6356 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
6358 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6360 int ncell=getNumberOfCells();
6361 std::vector<bool> ret(ncell);
6362 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6363 const int *c=getNodalConnectivity()->getConstPointer();
6364 for(int i=0;i<ncell;i++)
6366 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6367 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6368 ret[i]=cm.isQuadratic();
6374 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
6376 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6378 if(other->getType()!=UNSTRUCTURED)
6379 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6380 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6381 return MergeUMeshes(this,otherC);
6385 * Returns an array with this->getNumberOfCells() tuples and this->getSpaceDimension() dimension.
6386 * The false barycenter is computed that is to say barycenter of a cell is computed using average on each
6387 * components of coordinates of the cell.
6389 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6391 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6392 int spaceDim=getSpaceDimension();
6393 int nbOfCells=getNumberOfCells();
6394 ret->alloc(nbOfCells,spaceDim);
6395 ret->copyStringInfoFrom(*getCoords());
6396 double *ptToFill=ret->getPointer();
6397 const int *nodal=_nodal_connec->getConstPointer();
6398 const int *nodalI=_nodal_connec_index->getConstPointer();
6399 const double *coor=_coords->getConstPointer();
6400 for(int i=0;i<nbOfCells;i++)
6402 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6403 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6410 * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
6411 * 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().
6412 * No check of that will be done !
6414 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6416 DataArrayDouble *ret=DataArrayDouble::New();
6417 int spaceDim=getSpaceDimension();
6418 int nbOfTuple=(int)std::distance(begin,end);
6419 ret->alloc(nbOfTuple,spaceDim);
6420 double *ptToFill=ret->getPointer();
6421 double *tmp=new double[spaceDim];
6422 const int *nodal=_nodal_connec->getConstPointer();
6423 const int *nodalI=_nodal_connec_index->getConstPointer();
6424 const double *coor=_coords->getConstPointer();
6425 for(const int *w=begin;w!=end;w++)
6427 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6428 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6436 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6439 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
6442 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6443 da->checkAllocated();
6444 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
6446 int nbOfTuples=da->getNumberOfTuples();
6447 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6449 c->alloc(2*nbOfTuples,1);
6450 cI->alloc(nbOfTuples+1,1);
6451 int *cp=c->getPointer();
6452 int *cip=cI->getPointer();
6454 for(int i=0;i<nbOfTuples;i++)
6456 *cp++=INTERP_KERNEL::NORM_POINT1;
6460 ret->setConnectivity(c,cI,true);
6465 * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
6466 * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
6468 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6470 std::vector<const MEDCouplingUMesh *> tmp(2);
6471 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6472 return MergeUMeshes(tmp);
6476 * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
6477 * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
6478 * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
6479 * cells in meshes in 'a' (in the same order too).
6481 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6483 std::size_t sz=a.size();
6485 return MergeUMeshesLL(a);
6486 for(std::size_t ii=0;ii<sz;ii++)
6489 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6490 throw INTERP_KERNEL::Exception(oss.str().c_str());
6492 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
6493 std::vector< const MEDCouplingUMesh * > aa(sz);
6495 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6497 const MEDCouplingUMesh *cur=a[i];
6498 const DataArrayDouble *coo=cur->getCoords();
6500 spaceDim=coo->getNumberOfComponents();
6503 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6504 for(std::size_t i=0;i<sz;i++)
6506 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6509 return MergeUMeshesLL(aa);
6514 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
6518 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
6519 int meshDim=(*it)->getMeshDimension();
6520 int nbOfCells=(*it)->getNumberOfCells();
6521 int meshLgth=(*it++)->getMeshLength();
6522 for(;it!=a.end();it++)
6524 if(meshDim!=(*it)->getMeshDimension())
6525 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
6526 nbOfCells+=(*it)->getNumberOfCells();
6527 meshLgth+=(*it)->getMeshLength();
6529 std::vector<const MEDCouplingPointSet *> aps(a.size());
6530 std::copy(a.begin(),a.end(),aps.begin());
6531 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
6532 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
6533 ret->setCoords(pts);
6534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6535 c->alloc(meshLgth,1);
6536 int *cPtr=c->getPointer();
6537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6538 cI->alloc(nbOfCells+1,1);
6539 int *cIPtr=cI->getPointer();
6543 for(it=a.begin();it!=a.end();it++)
6545 int curNbOfCell=(*it)->getNumberOfCells();
6546 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
6547 const int *curC=(*it)->_nodal_connec->getConstPointer();
6548 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
6549 for(int j=0;j<curNbOfCell;j++)
6551 const int *src=curC+curCI[j];
6553 for(;src!=curC+curCI[j+1];src++,cPtr++)
6561 offset+=curCI[curNbOfCell];
6562 offset2+=(*it)->getNumberOfNodes();
6565 ret->setConnectivity(c,cI,true);
6572 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6573 * 'meshes' must be a non empty vector.
6575 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6577 std::vector<const MEDCouplingUMesh *> tmp(2);
6578 tmp[0]=mesh1; tmp[1]=mesh2;
6579 return MergeUMeshesOnSameCoords(tmp);
6583 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6584 * 'meshes' must be a non empty vector.
6586 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6589 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6590 for(std::size_t ii=0;ii<meshes.size();ii++)
6593 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6594 throw INTERP_KERNEL::Exception(oss.str().c_str());
6596 const DataArrayDouble *coords=meshes.front()->getCoords();
6597 int meshDim=meshes.front()->getMeshDimension();
6598 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6600 int meshIndexLgth=0;
6601 for(;iter!=meshes.end();iter++)
6603 if(coords!=(*iter)->getCoords())
6604 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6605 if(meshDim!=(*iter)->getMeshDimension())
6606 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6607 meshLgth+=(*iter)->getMeshLength();
6608 meshIndexLgth+=(*iter)->getNumberOfCells();
6610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
6611 nodal->alloc(meshLgth,1);
6612 int *nodalPtr=nodal->getPointer();
6613 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
6614 nodalIndex->alloc(meshIndexLgth+1,1);
6615 int *nodalIndexPtr=nodalIndex->getPointer();
6617 for(iter=meshes.begin();iter!=meshes.end();iter++)
6619 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
6620 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
6621 int nbOfCells=(*iter)->getNumberOfCells();
6622 int meshLgth2=(*iter)->getMeshLength();
6623 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6624 if(iter!=meshes.begin())
6625 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6627 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6630 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6631 ret->setName("merge");
6632 ret->setMeshDimension(meshDim);
6633 ret->setConnectivity(nodal,nodalIndex,true);
6634 ret->setCoords(coords);
6639 * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
6640 * 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)
6642 * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
6643 * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
6644 * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
6645 * The arrays contained in 'corr' parameter are returned with refcounter set to one.
6646 * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
6647 * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
6648 * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
6650 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6652 //All checks are delegated to MergeUMeshesOnSameCoords
6653 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6654 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6655 corr.resize(meshes.size());
6656 std::size_t nbOfMeshes=meshes.size();
6658 const int *o2nPtr=o2n->getConstPointer();
6659 for(std::size_t i=0;i<nbOfMeshes;i++)
6661 DataArrayInt *tmp=DataArrayInt::New();
6662 int curNbOfCells=meshes[i]->getNumberOfCells();
6663 tmp->alloc(curNbOfCells,1);
6664 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6665 offset+=curNbOfCells;
6666 tmp->setName(meshes[i]->getName());
6673 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6674 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6675 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6676 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6678 * This method performs nothing if size of \b meshes is in [0,1].
6679 * This method is particulary useful in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6680 * coordinates DataArrayDouble instance.
6682 * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6684 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6686 std::size_t sz=meshes.size();
6689 std::vector< const DataArrayDouble * > coords(meshes.size());
6690 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6691 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6695 (*it)->checkConnectivityFullyDefined();
6696 const DataArrayDouble *coo=(*it)->getCoords();
6701 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6702 oss << " has no coordinate array defined !";
6703 throw INTERP_KERNEL::Exception(oss.str().c_str());
6708 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6709 oss << " is null !";
6710 throw INTERP_KERNEL::Exception(oss.str().c_str());
6713 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6714 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6715 int offset=(*it)->getNumberOfNodes();
6716 (*it++)->setCoords(res);
6717 for(;it!=meshes.end();it++)
6719 int oldNumberOfNodes=(*it)->getNumberOfNodes();
6720 (*it)->setCoords(res);
6721 (*it)->shiftNodeNumbersInConn(offset);
6722 offset+=oldNumberOfNodes;
6727 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6728 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6729 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6730 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6731 * 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.
6733 * This method performs nothing if size of \b meshes is empty.
6734 * This method is particulary useful in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6735 * coordinates DataArrayDouble instance.
6737 * \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.
6738 * \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.
6740 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6744 std::set<const DataArrayDouble *> s;
6745 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6748 s.insert((*it)->getCoords());
6751 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 !";
6752 throw INTERP_KERNEL::Exception(oss.str().c_str());
6757 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 !";
6758 throw INTERP_KERNEL::Exception(oss.str().c_str());
6760 const DataArrayDouble *coo=*(s.begin());
6764 DataArrayInt *comm,*commI;
6765 coo->findCommonTuples(eps,-1,comm,commI);
6766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6767 int oldNbOfNodes=coo->getNumberOfTuples();
6769 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6770 if(oldNbOfNodes==newNbOfNodes)
6772 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6773 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6775 (*it)->renumberNodesInConn(o2n->getConstPointer());
6776 (*it)->setCoords(newCoords);
6781 * 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.
6782 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6783 * @param isQuad specifies the policy of connectivity.
6784 * @ret in/out parameter in which the result will be append
6786 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6788 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6789 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6790 ret.push_back(cm.getExtrudedType());
6791 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6794 case INTERP_KERNEL::NORM_POINT1:
6796 ret.push_back(connBg[1]);
6797 ret.push_back(connBg[1]+nbOfNodesPerLev);
6800 case INTERP_KERNEL::NORM_SEG2:
6802 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6803 ret.insert(ret.end(),conn,conn+4);
6806 case INTERP_KERNEL::NORM_SEG3:
6808 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6809 ret.insert(ret.end(),conn,conn+8);
6812 case INTERP_KERNEL::NORM_QUAD4:
6814 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6815 ret.insert(ret.end(),conn,conn+8);
6818 case INTERP_KERNEL::NORM_TRI3:
6820 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6821 ret.insert(ret.end(),conn,conn+6);
6824 case INTERP_KERNEL::NORM_TRI6:
6826 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,
6827 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6828 ret.insert(ret.end(),conn,conn+15);
6831 case INTERP_KERNEL::NORM_QUAD8:
6834 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6835 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6836 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6838 ret.insert(ret.end(),conn,conn+20);
6841 case INTERP_KERNEL::NORM_POLYGON:
6843 std::back_insert_iterator< std::vector<int> > ii(ret);
6844 std::copy(connBg+1,connEnd,ii);
6846 std::reverse_iterator<const int *> rConnBg(connEnd);
6847 std::reverse_iterator<const int *> rConnEnd(connBg+1);
6848 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6849 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6850 for(std::size_t i=0;i<nbOfRadFaces;i++)
6853 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6854 std::copy(conn,conn+4,ii);
6859 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6864 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6866 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6868 double v[3]={0.,0.,0.};
6869 std::size_t sz=std::distance(begin,end);
6872 for(std::size_t i=0;i<sz;i++)
6874 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];
6875 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6876 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6878 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6882 * The polyhedron is specfied by its connectivity nodes in [begin,end).
6884 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6886 std::vector<std::pair<int,int> > edges;
6887 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6888 const int *bgFace=begin;
6889 for(std::size_t i=0;i<nbOfFaces;i++)
6891 const int *endFace=std::find(bgFace+1,end,-1);
6892 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6893 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6895 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6896 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6898 edges.push_back(p1);
6902 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6906 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
6908 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6910 double vec0[3],vec1[3];
6911 std::size_t sz=std::distance(begin,end);
6913 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6914 int nbOfNodes=(int)sz/2;
6915 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6916 const double *pt0=coords+3*begin[0];
6917 const double *pt1=coords+3*begin[nbOfNodes];
6918 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6919 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6922 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6924 std::size_t sz=std::distance(begin,end);
6925 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6926 std::size_t nbOfNodes(sz/2);
6927 std::copy(begin,end,(int *)tmp);
6928 for(std::size_t j=1;j<nbOfNodes;j++)
6930 begin[j]=tmp[nbOfNodes-j];
6931 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6935 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6937 std::size_t sz=std::distance(begin,end);
6939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
6940 double vec0[3],vec1[3];
6941 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6942 vec0[0]=pt1[0]-pt0[0]; vec0[1]=pt1[1]-pt0[1]; vec0[2]=pt1[2]-pt0[2]; vec1[0]=pt2[0]-pt0[0]; vec1[1]=pt2[1]-pt0[1]; vec1[2]=pt2[2]-pt0[2];
6943 return ((vec0[1]*vec1[2]-vec0[2]*vec1[1])*(pt3[0]-pt0[0])+(vec0[2]*vec1[0]-vec0[0]*vec1[2])*(pt3[1]-pt0[1])+(vec0[0]*vec1[1]-vec0[1]*vec1[0])*(pt3[2]-pt0[2]))<0;
6946 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
6948 std::size_t sz=std::distance(begin,end);
6950 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
6952 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
6953 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
6954 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
6958 * 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)
6959 * 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
6962 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6963 * \param [in] coords the coordinates with nb of components exactly equal to 3
6964 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6965 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6966 * \param [out] res the result is put at the end of the vector without any alteration of the data.
6968 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
6970 int nbFaces=std::count(begin+1,end,-1)+1;
6971 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6972 double *vPtr=v->getPointer();
6973 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6974 double *pPtr=p->getPointer();
6975 const int *stFaceConn=begin+1;
6976 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6978 const int *endFaceConn=std::find(stFaceConn,end,-1);
6979 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
6980 stFaceConn=endFaceConn+1;
6982 pPtr=p->getPointer(); vPtr=v->getPointer();
6983 DataArrayInt *comm1=0,*commI1=0;
6984 v->findCommonTuples(eps,-1,comm1,commI1);
6985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6986 const int *comm1Ptr=comm1->getConstPointer();
6987 const int *commI1Ptr=commI1->getConstPointer();
6988 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6989 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
6991 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
6992 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
6993 mm->finishInsertingCells();
6995 for(int i=0;i<nbOfGrps1;i++)
6997 int vecId=comm1Ptr[commI1Ptr[i]];
6998 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6999 DataArrayInt *comm2=0,*commI2=0;
7000 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7002 const int *comm2Ptr=comm2->getConstPointer();
7003 const int *commI2Ptr=commI2->getConstPointer();
7004 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7005 for(int j=0;j<nbOfGrps2;j++)
7007 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7009 res->insertAtTheEnd(begin,end);
7010 res->pushBackSilent(-1);
7014 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7016 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7017 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7018 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7019 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7020 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7021 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7022 const int *idsNodePtr=idsNode->getConstPointer();
7023 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];
7024 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7025 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7026 if(std::abs(norm)>eps)
7028 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7029 mm3->rotate(center,vec,angle);
7031 mm3->changeSpaceDimension(2);
7032 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7033 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7034 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7035 int nbOfCells=mm4->getNumberOfCells();
7036 for(int k=0;k<nbOfCells;k++)
7039 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7040 res->pushBackSilent(idsNodePtr[*work]);
7041 res->pushBackSilent(-1);
7046 res->popBackSilent();
7050 * 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
7051 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
7053 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7054 * \param [in] coords coordinates expected to have 3 components.
7055 * \param [in] begin start of the nodal connectivity of the face.
7056 * \param [in] end end of the nodal connectivity (excluded) of the face.
7057 * \param [out] v the normalized vector of size 3
7058 * \param [out] p the pos of plane
7060 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7062 std::size_t nbPoints=std::distance(begin,end);
7064 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7067 bool refFound=false;
7068 for(;j<nbPoints-1 && !refFound;j++)
7070 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7071 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7072 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7073 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7077 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7080 for(std::size_t i=j;i<nbPoints-1;i++)
7083 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7084 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7085 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7086 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7089 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7090 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];
7091 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7094 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7095 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7099 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7103 * This method tries to obtain a well oriented polyhedron.
7104 * If the algorithm fails, an exception will be thrown.
7106 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7108 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7109 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7110 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7112 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7113 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7114 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7116 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7119 std::size_t smthChanged=0;
7120 for(std::size_t i=0;i<nbOfFaces;i++)
7122 endFace=std::find(bgFace+1,end,-1);
7123 nbOfEdgesInFace=std::distance(bgFace,endFace);
7127 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7129 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7130 std::pair<int,int> p2(p1.second,p1.first);
7131 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7132 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7133 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7138 std::reverse(bgFace+1,endFace);
7139 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7141 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7142 std::pair<int,int> p2(p1.second,p1.first);
7143 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7144 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7145 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7146 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7147 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7148 if(it!=edgesOK.end())
7151 edgesFinished.push_back(p1);
7154 edgesOK.push_back(p1);
7161 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7163 if(!edgesOK.empty())
7164 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7165 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7166 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7168 for(std::size_t i=0;i<nbOfFaces;i++)
7170 endFace=std::find(bgFace+1,end,-1);
7171 std::reverse(bgFace+1,endFace);
7178 * This method makes the assumption spacedimension == meshdimension == 2.
7179 * This method works only for linear cells.
7181 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7183 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7185 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7187 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7189 int nbOfNodesExpected=m->getNumberOfNodes();
7190 if(m->getNumberOfCells()!=nbOfNodesExpected)
7191 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7192 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7193 const int *n2oPtr=n2o->getConstPointer();
7194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7195 m->getReverseNodalConnectivity(revNodal,revNodalI);
7196 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7197 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7198 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7200 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7201 if(nbOfNodesExpected<1)
7204 int prevNode=nodalPtr[nodalIPtr[0]+1];
7205 *work++=n2oPtr[prevNode];
7206 for(int i=1;i<nbOfNodesExpected;i++)
7208 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7210 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7211 conn.erase(prevNode);
7214 int curNode=*(conn.begin());
7215 *work++=n2oPtr[curNode];
7216 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7217 shar.erase(prevCell);
7220 prevCell=*(shar.begin());
7224 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7227 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7236 * This method makes the assumption spacedimension == meshdimension == 3.
7237 * This method works only for linear cells.
7239 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7241 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7243 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7245 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7246 const int *conn=m->getNodalConnectivity()->getConstPointer();
7247 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7248 int nbOfCells=m->getNumberOfCells();
7249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7250 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7253 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7254 for(int i=1;i<nbOfCells;i++)
7257 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7263 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7264 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7266 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7270 for(int i=0;i<nbOfNodesInCell;i++)
7271 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7272 else if(spaceDim==2)
7274 for(int i=0;i<nbOfNodesInCell;i++)
7276 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7284 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7286 int nbOfCells=getNumberOfCells();
7288 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7289 static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,-1,4};
7290 ofs << " <" << getVTKDataSetType() << ">\n";
7291 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7292 ofs << " <PointData>\n" << pointData << std::endl;
7293 ofs << " </PointData>\n";
7294 ofs << " <CellData>\n" << cellData << std::endl;
7295 ofs << " </CellData>\n";
7296 ofs << " <Points>\n";
7297 if(getSpaceDimension()==3)
7298 _coords->writeVTK(ofs,8,"Points");
7301 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7302 coo->writeVTK(ofs,8,"Points");
7304 ofs << " </Points>\n";
7305 ofs << " <Cells>\n";
7306 const int *cPtr=_nodal_connec->getConstPointer();
7307 const int *cIPtr=_nodal_connec_index->getConstPointer();
7308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7312 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7313 int szFaceOffsets=0,szConn=0;
7314 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7317 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7320 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7321 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7325 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7326 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7327 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7328 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7329 w4=std::copy(c.begin(),c.end(),w4);
7332 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
7333 types->writeVTK(ofs,8,"UInt8","types");
7334 offsets->writeVTK(ofs,8,"Int32","offsets");
7335 if(szFaceOffsets!=0)
7336 {//presence of Polyhedra
7337 connectivity->reAlloc(szConn);
7338 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
7339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7340 w1=faces->getPointer();
7341 for(int i=0;i<nbOfCells;i++)
7342 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7344 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7346 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7347 for(int j=0;j<nbFaces;j++)
7349 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7350 *w1++=(int)std::distance(w6,w5);
7351 w1=std::copy(w6,w5,w1);
7355 faces->writeVTK(ofs,8,"Int32","faces");
7357 connectivity->writeVTK(ofs,8,"Int32","connectivity");
7358 ofs << " </Cells>\n";
7359 ofs << " </Piece>\n";
7360 ofs << " </" << getVTKDataSetType() << ">\n";
7363 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
7365 return std::string("UnstructuredGrid");
7370 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
7372 m1->checkFullyDefined();
7373 m2->checkFullyDefined();
7374 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
7375 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
7376 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
7377 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
7378 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
7379 std::vector<double> addCoo,addCoordsQuadratic;
7380 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
7381 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
7382 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
7383 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
7384 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
7385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
7386 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
7387 std::vector< std::vector<int> > intersectEdge2;
7388 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
7389 subDiv2.clear(); dd5=0; dd6=0;
7390 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
7391 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
7392 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
7393 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
7395 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
7396 addCooDa->alloc((int)(addCoo.size())/2,2);
7397 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
7398 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
7399 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
7400 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
7401 std::vector<const DataArrayDouble *> coordss(4);
7402 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
7403 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
7404 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
7405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
7406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
7407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
7408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
7409 ret->setConnectivity(conn,connI,true);
7410 ret->setCoords(coo);
7411 cellNb1=c1.retn(); cellNb2=c2.retn();
7417 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
7418 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
7419 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
7420 const std::vector<double>& addCoords,
7421 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
7423 static const int SPACEDIM=2;
7424 std::vector<double> bbox1,bbox2;
7425 const double *coo1=m1->getCoords()->getConstPointer();
7426 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
7427 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
7428 int offset1=m1->getNumberOfNodes();
7429 const double *coo2=m2->getCoords()->getConstPointer();
7430 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
7431 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
7432 int offset2=offset1+m2->getNumberOfNodes();
7433 int offset3=offset2+((int)addCoords.size())/2;
7434 m1->getBoundingBoxForBBTree(bbox1);
7435 m2->getBoundingBoxForBBTree(bbox2);
7436 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
7437 int ncell1=m1->getNumberOfCells();
7439 for(int i=0;i<ncell1;i++)
7441 std::vector<int> candidates2;
7442 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7443 std::map<INTERP_KERNEL::Node *,int> mapp;
7444 std::map<int,INTERP_KERNEL::Node *> mappRev;
7445 INTERP_KERNEL::QuadraticPolygon pol1;
7446 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
7447 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7448 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
7449 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
7450 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
7452 std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result
7453 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
7454 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
7455 for(it1.first();!it1.finished();it1.next())
7456 edges1.insert(it1.current()->getPtr());
7458 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
7459 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
7461 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7463 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
7464 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
7465 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
7466 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
7467 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
7470 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7472 pol1.initLocationsWithOther(pol2s[ii]);
7473 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
7474 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
7475 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7481 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7483 catch(INTERP_KERNEL::Exception& e)
7485 std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
7486 throw INTERP_KERNEL::Exception(oss.str().c_str());
7489 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
7490 (*it).second->decrRef();
7495 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
7498 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
7499 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
7500 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
7501 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
7502 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
7504 static const int SPACEDIM=2;
7505 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
7506 desc2=DataArrayInt::New();
7507 descIndx2=DataArrayInt::New();
7508 revDesc2=DataArrayInt::New();
7509 revDescIndx2=DataArrayInt::New();
7510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
7511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
7512 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
7513 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
7514 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
7515 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
7516 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
7517 std::vector<double> bbox1,bbox2;
7518 m1Desc->getBoundingBoxForBBTree(bbox1);
7519 m2Desc->getBoundingBoxForBBTree(bbox2);
7520 int ncell1=m1Desc->getNumberOfCells();
7521 int ncell2=m2Desc->getNumberOfCells();
7522 intersectEdge1.resize(ncell1);
7523 colinear2.resize(ncell2);
7524 subDiv2.resize(ncell2);
7525 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
7526 std::vector<int> candidates1(1);
7527 int offset1=m1->getNumberOfNodes();
7528 int offset2=offset1+m2->getNumberOfNodes();
7529 for(int i=0;i<ncell1;i++)
7531 std::vector<int> candidates2;
7532 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7533 if(!candidates2.empty())
7535 std::map<INTERP_KERNEL::Node *,int> map1,map2;
7536 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
7538 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
7539 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
7544 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
7546 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
7547 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
7551 * This method performs the 2nd step of Partition of 2D mesh.
7552 * This method has 4 inputs :
7553 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
7554 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
7555 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
7556 * 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'
7557 * @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'
7558 * @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.
7559 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
7561 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)
7563 int offset1=m1->getNumberOfNodes();
7564 int ncell=m2->getNumberOfCells();
7565 const int *c=m2->getNodalConnectivity()->getConstPointer();
7566 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
7567 const double *coo=m2->getCoords()->getConstPointer();
7568 const double *cooBis=m1->getCoords()->getConstPointer();
7569 int offset2=offset1+m2->getNumberOfNodes();
7570 intersectEdge.resize(ncell);
7571 for(int i=0;i<ncell;i++,cI++)
7573 const std::vector<int>& divs=subDiv[i];
7574 int nnode=cI[1]-cI[0]-1;
7575 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
7576 std::map<INTERP_KERNEL::Node *, int> mapp22;
7577 for(int j=0;j<nnode;j++)
7579 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
7580 int nnid=c[(*cI)+j+1];
7581 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
7582 mapp22[nn]=nnid+offset1;
7584 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
7585 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
7586 ((*it).second.first)->decrRef();
7587 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
7588 std::map<INTERP_KERNEL::Node *,int> mapp3;
7589 for(std::size_t j=0;j<divs.size();j++)
7592 INTERP_KERNEL::Node *tmp=0;
7594 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
7596 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
7598 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
7602 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
7603 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
7610 * 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).
7611 * 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
7612 * with a plane. The result will be put in 'cut3DSuf' out parameter.
7613 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
7614 * @param nodesOnPlane, returns all the nodes that are on the plane.
7615 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
7616 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
7617 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
7618 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
7619 * @param desc is the descending connectivity 3DSurf->3DCurve
7620 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
7621 * @param cut3DSuf input/output param.
7623 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
7624 const int *nodal3DCurve, const int *nodalIndx3DCurve,
7625 const int *desc, const int *descIndx,
7626 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
7628 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
7629 int nbOf3DSurfCell=(int)cut3DSurf.size();
7630 for(int i=0;i<nbOf3DSurfCell;i++)
7632 std::vector<int> res;
7633 int offset=descIndx[i];
7634 int nbOfSeg=descIndx[i+1]-offset;
7635 for(int j=0;j<nbOfSeg;j++)
7637 int edgeId=desc[offset+j];
7638 int status=cut3DCurve[edgeId];
7642 res.push_back(status);
7645 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
7646 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
7654 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7660 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
7661 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
7664 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7668 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
7673 {// case when plane is on a multi colinear edge of a polyhedron
7674 if((int)res.size()==2*nbOfSeg)
7676 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
7679 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
7686 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
7687 * 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).
7688 * 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
7689 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
7690 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
7691 * @param desc is the descending connectivity 3D->3DSurf
7692 * @param descIndx is the descending connectivity index 3D->3DSurf
7694 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
7695 const int *desc, const int *descIndx,
7696 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
7698 checkFullyDefined();
7699 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
7701 const int *nodal3D=_nodal_connec->getConstPointer();
7702 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
7703 int nbOfCells=getNumberOfCells();
7704 for(int i=0;i<nbOfCells;i++)
7706 std::map<int, std::set<int> > m;
7707 int offset=descIndx[i];
7708 int nbOfFaces=descIndx[i+1]-offset;
7711 for(int j=0;j<nbOfFaces;j++)
7713 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
7714 if(p.first!=-1 && p.second!=-1)
7718 start=p.first; end=p.second;
7719 m[p.first].insert(p.second);
7720 m[p.second].insert(p.first);
7724 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
7725 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
7726 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7727 INTERP_KERNEL::NormalizedCellType cmsId;
7728 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
7729 start=tmp[0]; end=tmp[nbOfNodesSon-1];
7730 for(unsigned k=0;k<nbOfNodesSon;k++)
7732 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
7733 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
7740 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
7744 std::map<int, std::set<int> >::const_iterator it=m.find(start);
7745 const std::set<int>& s=(*it).second;
7746 std::set<int> s2; s2.insert(prev);
7748 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
7751 int val=*s3.begin();
7752 conn.push_back(start);
7759 conn.push_back(end);
7762 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
7763 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
7764 cellIds->pushBackSilent(i);
7770 * 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
7771 * 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
7772 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7773 * 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
7774 * 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.
7776 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7778 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
7780 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7783 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7784 if(cm.getDimension()==2)
7786 const int *node=nodalConnBg+1;
7787 int startNode=*node++;
7788 double refX=coords[2*startNode];
7789 for(;node!=nodalConnEnd;node++)
7791 if(coords[2*(*node)]<refX)
7794 refX=coords[2*startNode];
7797 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7801 double angle0=-M_PI/2;
7807 while(nextNode!=startNode)
7811 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7813 if(*node!=tmpOut.back() && *node!=prevNode)
7815 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7816 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7821 res=angle0-angleM+2.*M_PI;
7830 if(nextNode!=startNode)
7832 angle0=angleNext-M_PI;
7835 prevNode=tmpOut.back();
7836 tmpOut.push_back(nextNode);
7839 std::vector<int> tmp3(2*(sz-1));
7840 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7841 std::copy(nodalConnBg+1,nodalConnEnd,it);
7842 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7844 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7847 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7849 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7854 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7855 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7867 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7868 * 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.
7870 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7871 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7872 * \param [in,out] arr array in which the remove operation will be done.
7873 * \param [in,out] arrIndx array in the remove operation will modify
7874 * \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])
7875 * \return true if \b arr and \b arrIndx have been modified, false if not.
7877 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7879 if(!arrIndx || !arr)
7880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7881 if(offsetForRemoval<0)
7882 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7883 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7884 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7885 int *arrIPtr=arrIndx->getPointer();
7888 const int *arrPtr=arr->getConstPointer();
7889 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7890 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7892 if(*arrIPtr-previousArrI>offsetForRemoval)
7894 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7896 if(s.find(*work)==s.end())
7897 arrOut.push_back(*work);
7900 previousArrI=*arrIPtr;
7901 *arrIPtr=(int)arrOut.size();
7903 if(arr->getNumberOfTuples()==(int)arrOut.size())
7905 arr->alloc((int)arrOut.size(),1);
7906 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7911 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7912 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7913 * The selection of extraction is done standardly in new2old format.
7914 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
7916 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7917 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7918 * \param [in] arrIn arr origin array from which the extraction will be done.
7919 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7920 * \param [out] arrOut the resulting array
7921 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7923 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7924 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7926 if(!arrIn || !arrIndxIn)
7927 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7928 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7929 const int *arrInPtr=arrIn->getConstPointer();
7930 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7931 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7932 int maxSizeOfArr=arrIn->getNumberOfTuples();
7933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7935 arrIo->alloc((int)(sz+1),1);
7936 const int *idsIt=idsOfSelectBg;
7937 int *work=arrIo->getPointer();
7940 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7942 if(*idsIt>=0 && *idsIt<nbOfGrps)
7943 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7946 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7947 throw INTERP_KERNEL::Exception(oss.str().c_str());
7953 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7954 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7955 throw INTERP_KERNEL::Exception(oss.str().c_str());
7958 arro->alloc(lgth,1);
7959 work=arro->getPointer();
7960 idsIt=idsOfSelectBg;
7961 for(std::size_t i=0;i<sz;i++,idsIt++)
7963 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7964 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7967 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7968 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7969 throw INTERP_KERNEL::Exception(oss.str().c_str());
7973 arrIndexOut=arrIo.retn();
7977 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7978 * 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
7979 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7980 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7982 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7983 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7984 * \param [in] arrIn arr origin array from which the extraction will be done.
7985 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7986 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7987 * \param [in] srcArrIndex index array of \b srcArr
7988 * \param [out] arrOut the resulting array
7989 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7991 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7993 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7994 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7995 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7997 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7998 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8001 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8002 std::vector<bool> v(nbOfTuples,true);
8004 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8005 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8006 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8008 if(*it>=0 && *it<nbOfTuples)
8011 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8015 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8016 throw INTERP_KERNEL::Exception(oss.str().c_str());
8019 srcArrIndexPtr=srcArrIndex->getConstPointer();
8020 arrIo->alloc(nbOfTuples+1,1);
8021 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8022 const int *arrInPtr=arrIn->getConstPointer();
8023 const int *srcArrPtr=srcArr->getConstPointer();
8024 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8025 int *arroPtr=arro->getPointer();
8026 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8030 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8031 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8035 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8036 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8037 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8041 arrIndexOut=arrIo.retn();
8045 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8046 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8048 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8049 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8050 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8051 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8052 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8053 * \param [in] srcArrIndex index array of \b srcArr
8055 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8057 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8058 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8060 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8062 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8063 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8064 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8065 int *arrInOutPtr=arrInOut->getPointer();
8066 const int *srcArrPtr=srcArr->getConstPointer();
8067 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8069 if(*it>=0 && *it<nbOfTuples)
8071 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8072 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8075 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] !";
8076 throw INTERP_KERNEL::Exception(oss.str().c_str());
8081 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8082 throw INTERP_KERNEL::Exception(oss.str().c_str());
8088 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8089 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8090 * 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]].
8091 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8092 * A negative value in \b arrIn means that it is ignored.
8093 * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
8095 * \param [in] arrIn arr origin array from which the extraction will be done.
8096 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8097 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8098 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8100 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8102 int seed=0,nbOfDepthPeelingPerformed=0;
8103 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8107 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8108 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8109 * 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]].
8110 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8111 * A negative value in \b arrIn means that it is ignored.
8112 * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
8113 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8114 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8115 * \param [in] arrIn arr origin array from which the extraction will be done.
8116 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8117 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8118 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8119 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8120 * \sa MEDCouplingUMesh::partitionBySpreadZone
8122 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8124 nbOfDepthPeelingPerformed=0;
8126 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8127 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8130 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8134 std::vector<bool> fetched(nbOfTuples,false);
8135 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8138 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8140 nbOfDepthPeelingPerformed=0;
8141 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8142 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8143 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8144 std::vector<bool> fetched2(nbOfTuples,false);
8146 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8148 if(*seedElt>=0 && *seedElt<nbOfTuples)
8149 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8151 { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8153 const int *arrInPtr=arrIn->getConstPointer();
8154 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8155 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8156 std::vector<int> idsToFetch1(seedBg,seedEnd);
8157 std::vector<int> idsToFetch2;
8158 std::vector<int> *idsToFetch=&idsToFetch1;
8159 std::vector<int> *idsToFetchOther=&idsToFetch2;
8160 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8162 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8163 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8165 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8166 std::swap(idsToFetch,idsToFetchOther);
8167 idsToFetchOther->clear();
8168 nbOfDepthPeelingPerformed++;
8170 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8173 int *retPtr=ret->getPointer();
8174 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8181 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8182 * 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
8183 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8184 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8186 * \param [in] start begin of set of ids of the input extraction (included)
8187 * \param [in] end end of set of ids of the input extraction (excluded)
8188 * \param [in] step step of the set of ids in range mode.
8189 * \param [in] arrIn arr origin array from which the extraction will be done.
8190 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8191 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8192 * \param [in] srcArrIndex index array of \b srcArr
8193 * \param [out] arrOut the resulting array
8194 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8196 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8198 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8199 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8200 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8202 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8203 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8206 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8208 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8209 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8210 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8212 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8214 if(it>=0 && it<nbOfTuples)
8215 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8218 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8219 throw INTERP_KERNEL::Exception(oss.str().c_str());
8222 srcArrIndexPtr=srcArrIndex->getConstPointer();
8223 arrIo->alloc(nbOfTuples+1,1);
8224 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8225 const int *arrInPtr=arrIn->getConstPointer();
8226 const int *srcArrPtr=srcArr->getConstPointer();
8227 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8228 int *arroPtr=arro->getPointer();
8229 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8231 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8234 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8235 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8239 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8240 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8244 arrIndexOut=arrIo.retn();
8248 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8249 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8251 * \param [in] start begin of set of ids of the input extraction (included)
8252 * \param [in] end end of set of ids of the input extraction (excluded)
8253 * \param [in] step step of the set of ids in range mode.
8254 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8255 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8256 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8257 * \param [in] srcArrIndex index array of \b srcArr
8259 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8261 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8262 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8264 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8265 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
8266 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8267 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8268 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8269 int *arrInOutPtr=arrInOut->getPointer();
8270 const int *srcArrPtr=srcArr->getConstPointer();
8271 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
8273 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8275 if(it>=0 && it<nbOfTuples)
8277 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8278 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8281 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8282 throw INTERP_KERNEL::Exception(oss.str().c_str());
8287 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8288 throw INTERP_KERNEL::Exception(oss.str().c_str());
8294 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8295 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8296 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8297 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8298 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8300 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8302 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
8304 checkFullyDefined();
8305 int mdim=getMeshDimension();
8306 int spaceDim=getSpaceDimension();
8308 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8309 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8310 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8311 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
8312 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8313 ret->setCoords(getCoords());
8314 ret->allocateCells((int)partition.size());
8316 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
8323 cell=tmp->buildUnionOf2DMesh();
8326 cell=tmp->buildUnionOf3DMesh();
8329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8332 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
8335 ret->finishInsertingCells();
8340 * This method partitions \b this into contiguous zone.
8341 * This method only needs a well defined connectivity. Coordinates are not considered here.
8342 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8344 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
8347 int nbOfCellsCur=getNumberOfCells();
8348 std::vector<DataArrayInt *> ret;
8351 DataArrayInt *neigh=0,*neighI=0;
8352 computeNeighborsOfCells(neigh,neighI);
8353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8354 std::vector<bool> fetchedCells(nbOfCellsCur,false);
8355 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8357 while(seed<nbOfCellsCur)
8359 int nbOfPeelPerformed=0;
8360 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
8361 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8363 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8364 ret.push_back((*it).retn());
8368 int nbOfCellsCur=getNumberOfCells();
8369 DataArrayInt *neigh=0,*neighI=0;
8370 computeNeighborsOfCells(neigh,neighI);
8371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
8373 std::vector<DataArrayInt *> ret;
8374 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8375 while(nbOfCellsCur>0)
8377 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
8378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
8379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
8380 ret2.push_back(tmp2); ret.push_back(tmp2);
8381 nbOfCellsCur=tmp3->getNumberOfTuples();
8384 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
8385 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
8388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
8389 neighAuto->transformWithIndArr(renum->begin(),renum->end());
8392 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
8399 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8400 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8402 * \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.
8403 * \return a newly allocated DataArrayInt to be managed by the caller.
8404 * \throw In case of \a code has not the right format (typically of size 3*n)
8406 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
8408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
8409 std::size_t nb=code.size()/3;
8410 if(code.size()%3!=0)
8411 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8412 ret->alloc((int)nb,2);
8413 int *retPtr=ret->getPointer();
8414 for(std::size_t i=0;i<nb;i++,retPtr+=2)
8416 retPtr[0]=code[3*i+2];
8417 retPtr[1]=code[3*i+2]+code[3*i+1];
8422 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8423 _own_cell(true),_cell_id(-1),_nb_cell(0)
8428 _nb_cell=mesh->getNumberOfCells();
8432 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8440 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8441 _own_cell(false),_cell_id(bg-1),
8448 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8451 if(_cell_id<_nb_cell)
8460 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8466 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8468 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8471 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8477 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8485 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8491 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8496 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8501 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8503 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8506 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8511 _nb_cell=mesh->getNumberOfCells();
8515 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8522 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8524 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
8525 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
8526 if(_cell_id<_nb_cell)
8528 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8529 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
8530 int startId=_cell_id;
8531 _cell_id+=nbOfElems;
8532 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8538 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8542 _conn=mesh->getNodalConnectivity()->getPointer();
8543 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8547 void MEDCouplingUMeshCell::next()
8549 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8554 _conn_lgth=_conn_indx[1]-_conn_indx[0];
8557 std::string MEDCouplingUMeshCell::repr() const
8559 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8561 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8563 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8567 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8570 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8572 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8573 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8575 return INTERP_KERNEL::NORM_ERROR;
8578 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8581 if(_conn_lgth!=NOTICABLE_FIRST_VAL)