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)
210 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 !");
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))
559 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
560 * For speed reasons no check of this will be done.
561 * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
562 * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
563 * The algorithm to compute this p-1 mesh is the following :
564 * For each cell in 'this' it splits into p-1 elements.
565 * If this p-1 element does not already exists it is appended to the returned mesh
566 * If this p-1 element already exists, it is not appended.
567 * This method returns or 4 arrays plus the returned mesh.
568 * '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.
569 * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
571 * 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.
572 * 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])
574 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
575 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
577 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
579 return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
583 * WARNING this method do the assumption that connectivity lies on the coordinates set.
584 * For speed reasons no check of this will be done.
585 * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
586 * 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,
587 * 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
588 * an array in relative "FORTRAN" mode.
590 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
591 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
593 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
595 return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
599 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
600 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
601 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
602 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
604 * \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
605 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
606 * \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.
608 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
613 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
614 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
616 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
620 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
621 * 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,
622 * excluding a set of meshdim-1 cells in input descending connectivity.
623 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
624 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
625 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
627 * \param [in] desc descending connectivity array.
628 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
629 * \param [in] revDesc reverse descending connectivity array.
630 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
631 * \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
632 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
633 * \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.
635 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
636 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
638 if(!desc || !descIndx || !revDesc || !revDescIndx)
639 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
640 const int *descPtr=desc->getConstPointer();
641 const int *descIPtr=descIndx->getConstPointer();
642 const int *revDescPtr=revDesc->getConstPointer();
643 const int *revDescIPtr=revDescIndx->getConstPointer();
645 int nbCells=descIndx->getNumberOfTuples()-1;
646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
648 int *out1Ptr=out1->getPointer();
650 out0->reserve(desc->getNumberOfTuples());
651 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
653 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
655 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
657 out0->insertAtTheEnd(s.begin(),s.end());
659 *out1Ptr=out0->getNumberOfTuples();
661 neighbors=out0.retn();
662 neighborsIndx=out1.retn();
668 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
669 * For speed reasons no check of this will be done.
671 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
673 checkConnectivityFullyDefined();
674 int nbOfCells=getNumberOfCells();
675 int nbOfNodes=getNumberOfNodes();
676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
677 int *revNodalIndxPtr=revNodalIndx->getPointer();
678 const int *conn=_nodal_connec->getConstPointer();
679 const int *connIndex=_nodal_connec_index->getConstPointer();
680 std::string name="Mesh constituent of "; name+=getName();
681 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-1);
682 ret->setCoords(getCoords());
683 ret->allocateCells(2*nbOfCells);
684 descIndx->alloc(nbOfCells+1,1);
685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
686 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
687 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
689 int pos=connIndex[eltId];
690 int posP1=connIndex[eltId+1];
691 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
692 unsigned nbOfSons=cm.getNumberOfSons2(conn+pos+1,posP1-pos-1);
693 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
694 for(unsigned i=0;i<nbOfSons;i++)
696 INTERP_KERNEL::NormalizedCellType cmsId;
697 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
698 for(unsigned k=0;k<nbOfNodesSon;k++)
700 revNodalIndxPtr[tmp[k]+1]++;
701 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
702 revDesc2->pushBackSilent(eltId);
704 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
706 int nbOfCellsM1=ret->getNumberOfCells();
707 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
709 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
710 int *revNodalPtr=revNodal->getPointer();
711 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
712 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
713 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
715 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
716 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
717 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
718 if(*iter>=0)//for polyhedrons
719 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
722 DataArrayInt *commonCells=0,*commonCellsI=0;
723 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
724 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
725 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
726 int newNbOfCellsM1=-1;
727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
728 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
729 std::vector<bool> isImpacted(nbOfCellsM1,false);
730 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
731 for(int work2=work[0];work2!=work[1];work2++)
732 isImpacted[commonCellsPtr[work2]]=true;
733 const int *o2nM1Ptr=o2nM1->getConstPointer();
734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
735 const int *n2oM1Ptr=n2oM1->getConstPointer();
736 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
737 ret2->copyTinyInfoFrom(this);
738 desc->alloc(descIndx->back(),1);
739 int *descPtr=desc->getPointer();
740 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
741 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
744 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
747 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
749 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
750 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
753 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
756 revDesc->reserve(newNbOfCellsM1);
757 revDescIndx->alloc(newNbOfCellsM1+1,1);
758 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
759 const int *revDesc2Ptr=revDesc2->getConstPointer();
760 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
762 int oldCellIdM1=n2oM1Ptr[i];
763 if(!isImpacted[oldCellIdM1])
765 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
766 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
770 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
771 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
772 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
780 struct MEDCouplingAccVisit
782 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
783 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
784 int _new_nb_of_nodes;
791 * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
792 * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
793 * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
794 * If mesh dimension is not in [2,3] an exception is thrown.
795 * Of course pay attention that the resulting mesh is slower than previous one.
796 * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
797 * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
798 * If mesh==3, after throw the mesh is \b unconsistent !
799 * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
801 * \warning This method modifies can modify significantly the geometric type order in \a this.
802 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
804 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
807 int dim=getMeshDimension();
809 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
810 int nbOfCells=getNumberOfCells();
813 const int *connIndex=_nodal_connec_index->getConstPointer();
814 int *conn=_nodal_connec->getPointer();
815 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
817 if(*iter>=0 && *iter<nbOfCells)
819 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
821 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
823 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
827 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
828 oss << " in range [0," << nbOfCells << ") !";
829 throw INTERP_KERNEL::Exception(oss.str().c_str());
835 int *connIndex=_nodal_connec_index->getPointer();
836 int connIndexLgth=_nodal_connec_index->getNbOfElems();
837 const int *connOld=_nodal_connec->getConstPointer();
838 int connOldLgth=_nodal_connec->getNbOfElems();
839 std::vector<int> connNew(connOld,connOld+connOldLgth);
840 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
842 if(*iter>=0 && *iter<nbOfCells)
844 int pos=connIndex[*iter];
845 int posP1=connIndex[(*iter)+1];
846 int lgthOld=posP1-pos-1;
847 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
848 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
849 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
850 int *tmp=new int[nbOfFaces*lgthOld];
852 for(int j=0;j<(int)nbOfFaces;j++)
854 INTERP_KERNEL::NormalizedCellType type;
855 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
859 std::size_t newLgth=std::distance(tmp,work)-1;
860 std::size_t delta=newLgth-lgthOld;
861 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
862 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
863 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
868 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
869 oss << " in range [0," << nbOfCells << ") !";
870 throw INTERP_KERNEL::Exception(oss.str().c_str());
873 _nodal_connec->alloc((int)connNew.size(),1);
874 int *newConnPtr=_nodal_connec->getPointer();
875 std::copy(connNew.begin(),connNew.end(),newConnPtr);
881 * This method converts all cells into poly type if possible.
882 * This method is purely for userfriendliness.
883 * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
885 void MEDCouplingUMesh::convertAllToPoly()
887 int nbOfCells=getNumberOfCells();
888 std::vector<int> cellIds(nbOfCells);
889 for(int i=0;i<nbOfCells;i++)
891 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
895 * 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.
896 * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
897 * 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
898 * each 2 faces hidden in the single face of polyhedron).
899 * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
900 * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
901 * 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'
903 * This method is usefull only for users that wants to build extruded unstructured mesh.
904 * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
905 * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
907 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
910 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
912 int nbOfCells=getNumberOfCells();
913 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
914 newCi->alloc(nbOfCells+1,1);
915 int *newci=newCi->getPointer();
916 const int *ci=_nodal_connec_index->getConstPointer();
917 const int *c=_nodal_connec->getConstPointer();
919 for(int i=0;i<nbOfCells;i++)
921 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
922 if(type==INTERP_KERNEL::NORM_POLYHED)
924 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
926 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
927 throw INTERP_KERNEL::Exception(oss.str().c_str());
929 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
932 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 !";
933 throw INTERP_KERNEL::Exception(oss.str().c_str());
936 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)
939 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
942 newC->alloc(newci[nbOfCells],1);
943 int *newc=newC->getPointer();
944 for(int i=0;i<nbOfCells;i++)
946 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
947 if(type==INTERP_KERNEL::NORM_POLYHED)
949 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
950 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
952 for(std::size_t j=0;j<n1;j++)
954 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
956 newc[n1+5*j+1]=c[ci[i]+1+j];
957 newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
958 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
959 newc[n1+5*j+4]=c[ci[i]+1+j+n1];
964 newc=std::copy(c+ci[i],c+ci[i+1],newc);
966 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
967 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
971 * This method is the opposite of ParaMEDMEM::MEDCouplingUMesh::convertToPolyTypes method.
972 * The aim is to take all polygons or polyhedrons cell and to try to traduce them into classical cells.
974 * \return If true at least one cell has been unpolyzed.
975 \n If false has been returned the nodal connectivity of \a this has **not** been altered and \a this has remains unchanged.
977 * \warning This method modifies can modify significantly the geometric type order in \a this.
978 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
980 bool MEDCouplingUMesh::unPolyze()
983 int mdim=getMeshDimension();
985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
988 int nbOfCells=getNumberOfCells();
991 int initMeshLgth=getMeshLength();
992 int *conn=_nodal_connec->getPointer();
993 int *index=_nodal_connec_index->getPointer();
998 for(int i=0;i<nbOfCells;i++)
1000 lgthOfCurCell=index[i+1]-posOfCurCell;
1001 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1002 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1003 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1007 switch(cm.getDimension())
1011 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1012 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1013 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1018 int nbOfFaces,lgthOfPolyhConn;
1019 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1020 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1025 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1029 ret=ret || (newType!=type);
1030 conn[newPos]=newType;
1032 posOfCurCell=index[i+1];
1037 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1038 newPos+=lgthOfCurCell;
1039 posOfCurCell+=lgthOfCurCell;
1043 if(newPos!=initMeshLgth)
1044 _nodal_connec->reAlloc(newPos);
1051 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1052 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1053 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1055 * \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
1058 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1060 checkFullyDefined();
1061 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1062 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1063 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1064 coords->recenterForMaxPrecision(eps);
1066 int nbOfCells=getNumberOfCells();
1067 const int *conn=_nodal_connec->getConstPointer();
1068 const int *index=_nodal_connec_index->getConstPointer();
1069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1070 connINew->alloc(nbOfCells+1,1);
1071 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1074 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1076 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1078 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1082 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1083 *connINewPtr=connNew->getNumberOfTuples();
1086 setConnectivity(connNew,connINew,false);
1090 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1091 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1092 * the format of returned DataArrayInt instance.
1094 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1095 * \sa MEDCouplingUMesh::getNodeIdsInUse
1097 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1099 checkConnectivityFullyDefined();
1100 int nbOfCells=getNumberOfCells();
1101 const int *connIndex=_nodal_connec_index->getConstPointer();
1102 const int *conn=_nodal_connec->getConstPointer();
1103 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1104 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1105 std::vector<bool> retS(maxElt,false);
1106 for(int i=0;i<nbOfCells;i++)
1107 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1111 for(int i=0;i<maxElt;i++)
1114 DataArrayInt *ret=DataArrayInt::New();
1116 int *retPtr=ret->getPointer();
1117 for(int i=0;i<maxElt;i++)
1124 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1125 * \sa MEDCouplingUMesh::getNodeIdsInUse
1127 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1129 int nbOfNodes=(int)nodeIdsInUse.size();
1130 int nbOfCells=getNumberOfCells();
1131 const int *connIndex=_nodal_connec_index->getConstPointer();
1132 const int *conn=_nodal_connec->getConstPointer();
1133 for(int i=0;i<nbOfCells;i++)
1134 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1137 if(conn[j]<nbOfNodes)
1138 nodeIdsInUse[conn[j]]=true;
1141 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1142 throw INTERP_KERNEL::Exception(oss.str().c_str());
1148 * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
1149 * The returned array is newly created and should be dealt by the caller.
1150 * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
1151 * The size of returned array is the number of nodes of 'this'.
1152 * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
1153 * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
1154 * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
1155 * \throw if a cell contains in its nodal connectivity a node id >= nb of nodes an exception will be thrown.
1156 * \sa MEDCouplingUMesh::computeNodeIdsAlg
1158 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1161 int nbOfNodes=getNumberOfNodes();
1162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1163 ret->alloc(nbOfNodes,1);
1164 int *traducer=ret->getPointer();
1165 std::fill(traducer,traducer+nbOfNodes,-1);
1166 int nbOfCells=getNumberOfCells();
1167 const int *connIndex=_nodal_connec_index->getConstPointer();
1168 const int *conn=_nodal_connec->getConstPointer();
1169 for(int i=0;i<nbOfCells;i++)
1170 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1173 if(conn[j]<nbOfNodes)
1174 traducer[conn[j]]=1;
1177 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1178 throw INTERP_KERNEL::Exception(oss.str().c_str());
1181 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1182 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1187 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1188 * For each cell in \b this the number of nodes constituting cell is computed.
1189 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1190 * For polyhedrons, the face separation (-1) are excluded from the couting.
1192 * \return a newly allocated array
1194 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1196 checkConnectivityFullyDefined();
1197 int nbOfCells=getNumberOfCells();
1198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1199 ret->alloc(nbOfCells,1);
1200 int *retPtr=ret->getPointer();
1201 const int *conn=getNodalConnectivity()->getConstPointer();
1202 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1203 for(int i=0;i<nbOfCells;i++,retPtr++)
1205 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1206 *retPtr=connI[i+1]-connI[i]-1;
1208 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1214 * 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.
1215 * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
1216 * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
1217 * -1 values in returned array means that the corresponding old node is no more used.
1219 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1221 int newNbOfNodes=-1;
1222 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1223 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1228 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1229 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1231 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1236 return AreCellsEqual0(conn,connI,cell1,cell2);
1238 return AreCellsEqual1(conn,connI,cell1,cell2);
1240 return AreCellsEqual2(conn,connI,cell1,cell2);
1242 return AreCellsEqual3(conn,connI,cell1,cell2);
1244 return AreCellsEqual7(conn,connI,cell1,cell2);
1246 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2 or 3.");
1250 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1252 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1254 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1255 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1260 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1262 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1264 int sz=connI[cell1+1]-connI[cell1];
1265 if(sz==connI[cell2+1]-connI[cell2])
1267 if(conn[connI[cell1]]==conn[connI[cell2]])
1269 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1270 unsigned dim=cm.getDimension();
1276 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1277 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1278 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1279 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1280 return work!=tmp+sz1?1:0;
1283 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1286 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1293 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1295 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1297 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1299 if(conn[connI[cell1]]==conn[connI[cell2]])
1301 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1302 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1310 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1312 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1314 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1316 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1317 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1324 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1326 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1328 int sz=connI[cell1+1]-connI[cell1];
1329 if(sz==connI[cell2+1]-connI[cell2])
1331 if(conn[connI[cell1]]==conn[connI[cell2]])
1333 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1334 unsigned dim=cm.getDimension();
1340 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1341 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1342 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1343 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1348 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1349 std::reverse_iterator<int *> it2((int *)tmp);
1350 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1356 return work!=tmp+sz1?1:0;
1359 {//case of SEG2 and SEG3
1360 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1362 if(!cm.isQuadratic())
1364 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1365 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1366 if(std::equal(it1,it2,conn+connI[cell2]+1))
1372 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])
1379 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1387 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1388 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1390 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1392 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1394 std::vector<int> c1,c2;
1395 getNodeIdsOfCell(cellId,c1);
1396 other->getNodeIdsOfCell(cellId,c2);
1397 std::size_t sz=c1.size();
1400 for(std::size_t i=0;i<sz;i++)
1402 std::vector<double> n1,n2;
1403 getCoordinatesOfNode(c1[0],n1);
1404 other->getCoordinatesOfNode(c2[0],n2);
1405 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1406 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1407 if(*std::max_element(n1.begin(),n1.end())>prec)
1414 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1415 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1416 * and result remains unchanged.
1417 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1418 * If in 'candidates' pool -1 value is considered as an empty value.
1419 * WARNING this method returns only ONE set of result !
1421 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1423 if(candidates.size()<1)
1426 std::vector<int>::const_iterator iter=candidates.begin();
1427 int start=(*iter++);
1428 for(;iter!=candidates.end();iter++)
1430 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1435 result->pushBackSilent(start);
1439 result->pushBackSilent(*iter);
1441 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1448 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1449 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1451 * \param [in] compType input specifying the technique used to compare cells each other.
1452 * - 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.
1453 * - 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)
1454 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1455 * - 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
1456 * can be used for users not sensitive to orientation of cell
1457 * \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.
1458 * \param [out] commonCells
1459 * \param [out] commonCellsI
1460 * \return the correspondance array old to new in a newly allocated array.
1463 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1465 checkConnectivityFullyDefined();
1466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1467 getReverseNodalConnectivity(revNodal,revNodalI);
1468 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1471 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1472 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1475 int nbOfCells=nodalI->getNumberOfTuples()-1;
1476 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1477 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1478 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1479 std::vector<bool> isFetched(nbOfCells,false);
1482 for(int i=0;i<nbOfCells;i++)
1486 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1487 std::vector<int> v,v2;
1488 if(connOfNode!=connPtr+connIPtr[i+1])
1490 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1491 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1494 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1498 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1499 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1500 v2.resize(std::distance(v2.begin(),it));
1504 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1506 int pos=commonCellsI->back();
1507 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1508 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1509 isFetched[*it]=true;
1517 for(int i=startCellId;i<nbOfCells;i++)
1521 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1522 std::vector<int> v,v2;
1523 if(connOfNode!=connPtr+connIPtr[i+1])
1525 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1528 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1532 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1533 v2.resize(std::distance(v2.begin(),it));
1537 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1539 int pos=commonCellsI->back();
1540 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1541 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1542 isFetched[*it]=true;
1548 commonCellsArr=commonCells.retn();
1549 commonCellsIArr=commonCellsI.retn();
1553 * 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.
1554 * This method keeps the coordiantes of \a this.
1556 * \param [in] compType input specifying the technique used to compare cells each other.
1557 * - 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.
1558 * - 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)
1559 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1560 * - 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
1561 * can be used for users not sensitive to orientation of cell
1562 * \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
1563 * \return the correspondance array old to new in a newly allocated array.
1565 * \warning This method modifies can modify significantly the geometric type order in \a this.
1566 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1568 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1570 DataArrayInt *commonCells=0,*commonCellsI=0;
1571 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1572 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1573 int newNbOfCells=-1;
1574 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1575 commonCellsI->end(),newNbOfCells);
1576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1577 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1578 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1583 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1584 * 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.
1585 * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
1586 * The main difference is that this method is not expected to throw exception.
1587 * This method has two outputs :
1589 * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
1590 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1591 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1593 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1595 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1596 int nbOfCells=getNumberOfCells();
1597 static const int possibleCompType[]={0,1,2};
1598 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1600 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1601 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1603 throw INTERP_KERNEL::Exception(oss.str().c_str());
1605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1606 arr=o2n->substr(nbOfCells);
1607 arr->setName(other->getName());
1609 if(other->getNumberOfCells()==0)
1611 return arr->getMaxValue(tmp)<nbOfCells;
1615 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1616 * This method tries to determine if \b other is fully included in \b this.
1617 * The main difference is that this method is not expected to throw exception.
1618 * This method has two outputs :
1620 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1621 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1623 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1625 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1626 DataArrayInt *commonCells=0,*commonCellsI=0;
1627 int thisNbCells=getNumberOfCells();
1628 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1630 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1631 int otherNbCells=other->getNumberOfCells();
1632 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1633 arr2->alloc(otherNbCells,1);
1634 arr2->fillWithZero();
1635 int *arr2Ptr=arr2->getPointer();
1636 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1637 for(int i=0;i<nbOfCommon;i++)
1639 int start=commonCellsPtr[commonCellsIPtr[i]];
1640 if(start<thisNbCells)
1642 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1644 int sig=commonCellsPtr[j]>0?1:-1;
1645 int val=std::abs(commonCellsPtr[j])-1;
1646 if(val>=thisNbCells)
1647 arr2Ptr[val-thisNbCells]=sig*(start+1);
1651 arr2->setName(other->getName());
1652 if(arr2->presenceOfValue(0))
1659 * @param areNodesMerged if at least two nodes have been merged.
1660 * @return old to new node correspondance.
1662 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1664 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1666 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1671 * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
1673 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1675 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1677 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1682 * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
1683 * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
1684 * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
1685 * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
1687 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
1689 const DataArrayDouble *coords=other.getCoords();
1691 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
1693 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1694 int otherNbOfNodes=other.getNumberOfNodes();
1695 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1697 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1698 setCoords(newCoords);
1699 bool areNodesMerged;
1701 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1704 setCoords(oldCoords);
1705 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1707 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1708 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1709 if(pt!=da->getConstPointer()+da->getNbOfElems())
1711 setCoords(oldCoords);
1712 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1714 setCoords(oldCoords);
1715 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1720 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1721 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1722 * cellIds is not given explicitely but by a range python like.
1724 * \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.
1725 * \return a newly allocated
1727 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1728 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1730 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1732 if(getMeshDimension()!=-1)
1734 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
1741 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1743 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1745 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1747 return const_cast<MEDCouplingUMesh *>(this);
1752 * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
1753 * @param begin begin of array containing the cell ids to keep.
1754 * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
1755 * @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.
1757 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1758 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1760 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1762 if(getMeshDimension()!=-1)
1764 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
1772 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1774 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1776 return const_cast<MEDCouplingUMesh *>(this);
1781 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1783 * 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.
1784 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1785 * The number of cells of \b this will remain the same with this method.
1787 * \param [in] begin begin of cell ids (included) of cells in this to assign
1788 * \param [in] end end of cell ids (excluded) of cells in this to assign
1789 * \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).
1790 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1792 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1794 checkConnectivityFullyDefined();
1795 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1796 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1798 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1800 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1801 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1802 throw INTERP_KERNEL::Exception(oss.str().c_str());
1804 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1805 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1807 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1808 throw INTERP_KERNEL::Exception(oss.str().c_str());
1810 int nbOfCells=getNumberOfCells();
1811 bool easyAssign=true;
1812 const int *connI=_nodal_connec_index->getConstPointer();
1813 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1814 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1816 if(*it>=0 && *it<nbOfCells)
1818 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1822 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1823 throw INTERP_KERNEL::Exception(oss.str().c_str());
1828 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1833 DataArrayInt *arrOut=0,*arrIOut=0;
1834 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1837 setConnectivity(arrOut,arrIOut,true);
1841 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1843 checkConnectivityFullyDefined();
1844 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1845 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1846 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1847 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1849 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1850 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1851 throw INTERP_KERNEL::Exception(oss.str().c_str());
1853 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1854 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1856 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1857 throw INTERP_KERNEL::Exception(oss.str().c_str());
1859 int nbOfCells=getNumberOfCells();
1860 bool easyAssign=true;
1861 const int *connI=_nodal_connec_index->getConstPointer();
1862 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1864 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1866 if(it>=0 && it<nbOfCells)
1868 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1872 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1873 throw INTERP_KERNEL::Exception(oss.str().c_str());
1878 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1883 DataArrayInt *arrOut=0,*arrIOut=0;
1884 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1887 setConnectivity(arrOut,arrIOut,true);
1891 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1893 DataArrayInt *cellIdsKept=0;
1894 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
1895 cellIdsKept->setName(getName());
1900 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1901 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
1902 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1903 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1905 * \param [in] begin input start of array of node ids.
1906 * \param [in] end input end of array of node ids.
1907 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
1908 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
1910 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
1912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
1913 checkConnectivityFullyDefined();
1915 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
1916 std::vector<bool> fastFinder(sz,false);
1917 for(const int *work=begin;work!=end;work++)
1918 if(*work>=0 && *work<sz)
1919 fastFinder[*work]=true;
1920 int nbOfCells=getNumberOfCells();
1921 const int *conn=getNodalConnectivity()->getConstPointer();
1922 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
1923 for(int i=0;i<nbOfCells;i++)
1925 int ref=0,nbOfHit=0;
1926 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
1930 if(fastFinder[*work2])
1933 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
1934 cellIdsKept->pushBackSilent(i);
1936 cellIdsKeptArr=cellIdsKept.retn();
1940 * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
1942 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1944 DataArrayInt *cellIdsKept=0;
1945 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1946 cellIdsKept->setName(getName());
1951 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1952 * The return newly allocated mesh will share the same coordinates as 'this'.
1953 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1954 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1956 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1958 DataArrayInt *cellIdsKept=0;
1959 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
1961 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
1965 * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
1966 * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
1967 * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
1968 * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
1970 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
1973 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
1974 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
1975 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
1976 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
1980 * This method returns a mesh with meshDim=this->getMeshDimension()-1.
1981 * This returned mesh contains cells that are linked with one and only one cell of this.
1982 * @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.
1983 * @return mesh with ref counter equal to 1.
1985 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
1987 DataArrayInt *desc=DataArrayInt::New();
1988 DataArrayInt *descIndx=DataArrayInt::New();
1989 DataArrayInt *revDesc=DataArrayInt::New();
1990 DataArrayInt *revDescIndx=DataArrayInt::New();
1992 MEDCouplingUMesh *meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
1995 descIndx->decrRef();
1996 int nbOfCells=meshDM1->getNumberOfCells();
1997 const int *revDescIndxC=revDescIndx->getConstPointer();
1998 std::vector<int> boundaryCells;
1999 for(int i=0;i<nbOfCells;i++)
2000 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2001 boundaryCells.push_back(i);
2002 revDescIndx->decrRef();
2003 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2009 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2010 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2011 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2013 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2015 checkFullyDefined();
2016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2019 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2021 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2022 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2026 const int *revDescPtr=revDesc->getConstPointer();
2027 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2028 int nbOfCells=getNumberOfCells();
2029 std::vector<bool> ret1(nbOfCells,false);
2031 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2032 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2033 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2035 DataArrayInt *ret2=DataArrayInt::New();
2037 int *ret2Ptr=ret2->getPointer();
2039 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2042 ret2->setName("BoundaryCells");
2047 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2048 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2049 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2050 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2052 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2053 * This method method returns cells ids set s = s1 + s2 where :
2055 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2056 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2058 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2059 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2061 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2062 * \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
2063 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2065 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2067 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2068 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2069 checkConnectivityFullyDefined();
2070 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2071 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2073 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2075 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2077 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2078 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2079 DataArrayInt *idsOtherInConsti=0;
2080 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2083 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2085 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2086 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2089 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2090 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2092 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2093 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2094 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2095 neighThisPartAuto=0;
2096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2097 const int li[2]={0,1};
2098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2099 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2103 cellIdsRk0=s0arr.retn();
2104 cellIdsRk1=s_renum1.retn();
2108 * 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
2109 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2111 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2113 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2115 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2118 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2120 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2121 revDesc=0; desc=0; descIndx=0;
2122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2124 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2128 * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2129 * The returned nodes ids are those lying on the boundary of \b this.
2131 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2133 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2134 return skin->computeFetchedNodeIds();
2137 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2140 return const_cast<MEDCouplingUMesh *>(this);
2144 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2145 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2146 * This value is asked because often known by the caller of this method.
2147 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2149 * @param newNodeNumbers array specifying the new numbering in old2New convention.
2150 * @param newNbOfNodes the new number of nodes.
2152 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2154 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2155 renumberNodesInConn(newNodeNumbers);
2159 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2160 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2161 * This value is asked because often known by the caller of this method.
2162 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2163 * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2165 * @param newNodeNumbers array specifying the new numbering.
2166 * @param newNbOfNodes the new number of nodes.
2169 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2171 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2172 renumberNodesInConn(newNodeNumbers);
2176 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2177 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2178 * 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.
2179 * 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.
2180 * 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.
2182 * \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
2183 * parameter is altered during the call.
2184 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2185 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2186 * \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.
2188 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2190 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2191 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2193 checkFullyDefined();
2194 otherDimM1OnSameCoords.checkFullyDefined();
2195 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2196 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2197 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2198 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2199 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2200 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2203 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2204 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2208 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2210 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2212 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2213 DataArrayInt *idsTmp=0;
2214 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2215 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2218 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2219 DataArrayInt *tmp0=0,*tmp1=0;
2220 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2223 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2224 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2225 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2226 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2228 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2229 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2230 nodeIdsToDuplicate=s3.retn();
2234 * This method operates a modification of the connectivity and coords in \b this.
2235 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2236 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2237 * 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
2238 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2239 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2241 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2243 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2244 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2246 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2248 int nbOfNodes=getNumberOfNodes();
2249 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2250 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2254 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2255 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2256 * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2257 * @param [in] newNodeNumbers in old2New convention
2259 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2261 checkConnectivityFullyDefined();
2262 int *conn=getNodalConnectivity()->getPointer();
2263 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2264 int nbOfCells=getNumberOfCells();
2265 for(int i=0;i<nbOfCells;i++)
2266 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2268 int& node=conn[iconn];
2269 if(node>=0)//avoid polyhedron separator
2271 node=newNodeNumbersO2N[node];
2274 _nodal_connec->declareAsNew();
2279 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2280 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2281 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2283 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2285 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2287 checkConnectivityFullyDefined();
2288 int *conn=getNodalConnectivity()->getPointer();
2289 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2290 int nbOfCells=getNumberOfCells();
2291 for(int i=0;i<nbOfCells;i++)
2292 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2294 int& node=conn[iconn];
2295 if(node>=0)//avoid polyhedron separator
2300 _nodal_connec->declareAsNew();
2305 * This method operates a modification of the connectivity in \b this.
2306 * 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.
2307 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2308 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2309 * 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
2310 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2311 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2313 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2314 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2316 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2317 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2318 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2320 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2322 checkConnectivityFullyDefined();
2323 std::map<int,int> m;
2325 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2327 int *conn=getNodalConnectivity()->getPointer();
2328 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2329 int nbOfCells=getNumberOfCells();
2330 for(int i=0;i<nbOfCells;i++)
2331 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2333 int& node=conn[iconn];
2334 if(node>=0)//avoid polyhedron separator
2336 std::map<int,int>::iterator it=m.find(node);
2345 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2347 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2348 * After the call of this method the number of cells remains the same as before.
2350 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2351 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2352 * be strictly in [0;this->getNumberOfCells()).
2354 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2355 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2356 * should be contained in[0;this->getNumberOfCells()).
2358 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2360 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2362 checkConnectivityFullyDefined();
2363 int nbCells=getNumberOfCells();
2364 const int *array=old2NewBg;
2366 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2368 const int *conn=_nodal_connec->getConstPointer();
2369 const int *connI=_nodal_connec_index->getConstPointer();
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2371 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2372 newConn->copyStringInfoFrom(*_nodal_connec);
2373 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2374 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2375 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2377 int *newC=newConn->getPointer();
2378 int *newCI=newConnI->getPointer();
2381 for(int i=0;i<nbCells;i++)
2383 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2384 int nbOfElts=connI[pos+1]-connI[pos];
2385 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2390 setConnectivity(newConn,newConnI);
2392 delete [] const_cast<int *>(array);
2396 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2397 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2398 * added in 'elems' parameter.
2400 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2403 if(getMeshDimension()==-1)
2405 elems->pushBackSilent(0);
2406 return elems.retn();
2408 int dim=getSpaceDimension();
2409 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2410 const int* conn = getNodalConnectivity()->getConstPointer();
2411 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2412 const double* coords = getCoords()->getConstPointer();
2413 int nbOfCells=getNumberOfCells();
2414 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2416 for (int i=0; i<dim; i++)
2418 elem_bb[i*2]=std::numeric_limits<double>::max();
2419 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2422 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2424 int node= conn[inode];
2425 if(node>=0)//avoid polyhedron separator
2427 for (int idim=0; idim<dim; idim++)
2429 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2431 elem_bb[idim*2] = coords[node*dim+idim] ;
2433 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2435 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2440 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2441 elems->pushBackSilent(ielem);
2443 return elems.retn();
2447 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
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 INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
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(bbox, elem_bb, dim, eps))
2492 elems->pushBackSilent(ielem);
2494 return elems.retn();
2498 * Returns the cell type of cell with id 'cellId'.
2500 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2502 const int *ptI=_nodal_connec_index->getConstPointer();
2503 const int *pt=_nodal_connec->getConstPointer();
2504 if(cellId>=0 && cellId<_nodal_connec_index->getNbOfElems()-1)
2505 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2508 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2509 throw INTERP_KERNEL::Exception(oss.str().c_str());
2514 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2515 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2516 * The coordinates array is not considered here.
2518 * \param [in] type the geometric type
2519 * \return cell ids in this having geometric type \a type.
2521 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2524 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2526 checkConnectivityFullyDefined();
2527 int nbCells=getNumberOfCells();
2528 int mdim=getMeshDimension();
2529 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2530 if(mdim!=(int)cm.getDimension())
2531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2532 const int *ptI=_nodal_connec_index->getConstPointer();
2533 const int *pt=_nodal_connec->getConstPointer();
2534 for(int i=0;i<nbCells;i++)
2536 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2537 ret->pushBackSilent(i);
2543 * Returns nb of cells having the geometric type 'type'.
2545 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2547 const int *ptI=_nodal_connec_index->getConstPointer();
2548 const int *pt=_nodal_connec->getConstPointer();
2549 int nbOfCells=getNumberOfCells();
2551 for(int i=0;i<nbOfCells;i++)
2552 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2558 * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2559 * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2560 * That is to say -1 separator is omitted in returned conn.
2562 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2564 const int *ptI=_nodal_connec_index->getConstPointer();
2565 const int *pt=_nodal_connec->getConstPointer();
2566 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2571 std::string MEDCouplingUMesh::simpleRepr() const
2573 static const char msg0[]="No coordinates specified !";
2574 std::ostringstream ret;
2575 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2576 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2578 double tt=getTime(tmpp1,tmpp2);
2579 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2580 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2581 ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2584 const int spaceDim=getSpaceDimension();
2585 ret << spaceDim << "\nInfo attached on space dimension : ";
2586 for(int i=0;i<spaceDim;i++)
2587 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2591 ret << msg0 << "\n";
2592 ret << "Number of nodes : ";
2594 ret << getNumberOfNodes() << "\n";
2596 ret << msg0 << "\n";
2597 ret << "Number of cells : ";
2598 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2599 ret << getNumberOfCells() << "\n";
2601 ret << "No connectivity specified !" << "\n";
2602 ret << "Cell types present : ";
2603 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2605 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2606 ret << cm.getRepr() << " ";
2612 std::string MEDCouplingUMesh::advancedRepr() const
2614 std::ostringstream ret;
2615 ret << simpleRepr();
2616 ret << "\nCoordinates array : \n___________________\n\n";
2618 _coords->reprWithoutNameStream(ret);
2620 ret << "No array set !\n";
2621 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2622 reprConnectivityOfThisLL(ret);
2627 * This method returns a C++ code that is a dump of \a this.
2628 * This method will throw if this is not fully defined.
2630 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2632 static const char coordsName[]="coords";
2633 static const char connName[]="conn";
2634 static const char connIName[]="connI";
2635 checkFullyDefined();
2636 std::ostringstream ret; ret << "// coordinates" << std::endl;
2637 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2638 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2639 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2640 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2641 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2642 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2643 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2647 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2649 std::ostringstream ret;
2650 reprConnectivityOfThisLL(ret);
2655 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2656 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2657 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2660 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2661 * 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
2662 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2664 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2666 int mdim=getMeshDimension();
2668 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2669 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2671 bool needToCpyCT=true;
2674 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2682 if(!_nodal_connec_index)
2684 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2689 tmp2=_nodal_connec_index;
2692 ret->setConnectivity(tmp1,tmp2,false);
2697 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2698 ret->setCoords(coords);
2701 ret->setCoords(_coords);
2705 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2707 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2709 int nbOfCells=getNumberOfCells();
2710 const int *c=_nodal_connec->getConstPointer();
2711 const int *ci=_nodal_connec_index->getConstPointer();
2712 for(int i=0;i<nbOfCells;i++)
2714 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2715 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2716 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2721 stream << "Connectivity not defined !\n";
2724 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2726 const int *ptI=_nodal_connec_index->getConstPointer();
2727 const int *pt=_nodal_connec->getConstPointer();
2728 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2729 return ptI[cellId+1]-ptI[cellId]-1;
2731 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2735 * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2736 * This method avoids to compute explicitely submesh to get its types.
2738 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2740 checkFullyDefined();
2741 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2742 const int *conn=_nodal_connec->getConstPointer();
2743 const int *connIndex=_nodal_connec_index->getConstPointer();
2744 for(const int *w=begin;w!=end;w++)
2745 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2750 * Method reserved for advanced users having prepared their connectivity before.
2751 * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2753 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2755 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2756 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2757 if(isComputingTypes)
2763 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2764 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2766 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2767 _nodal_connec(0),_nodal_connec_index(0),
2768 _types(other._types)
2770 if(other._nodal_connec)
2771 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2772 if(other._nodal_connec_index)
2773 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2776 MEDCouplingUMesh::~MEDCouplingUMesh()
2779 _nodal_connec->decrRef();
2780 if(_nodal_connec_index)
2781 _nodal_connec_index->decrRef();
2785 * This method recomputes all cell types of 'this'.
2787 void MEDCouplingUMesh::computeTypes()
2789 if(_nodal_connec && _nodal_connec_index)
2792 const int *conn=_nodal_connec->getConstPointer();
2793 const int *connIndex=_nodal_connec_index->getConstPointer();
2794 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2795 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
2796 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2801 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2803 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2805 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2806 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2810 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2812 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2814 if(!_nodal_connec_index || !_nodal_connec)
2815 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2818 int MEDCouplingUMesh::getNumberOfCells() const
2820 if(_nodal_connec_index)
2821 return _nodal_connec_index->getNumberOfTuples()-1;
2826 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2829 int MEDCouplingUMesh::getMeshDimension() const
2832 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2837 * This method is for test reason. Normally the integer returned is not useable by user.
2839 int MEDCouplingUMesh::getMeshLength() const
2841 return _nodal_connec->getNbOfElems();
2845 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2847 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2849 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2850 tinyInfo.push_back(getMeshDimension());
2851 tinyInfo.push_back(getNumberOfCells());
2853 tinyInfo.push_back(getMeshLength());
2855 tinyInfo.push_back(-1);
2859 * First step of unserialization process.
2861 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2863 return tinyInfo[6]<=0;
2867 * Second step of serialization process.
2868 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2870 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2872 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2874 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2878 * Third and final step of serialization process.
2880 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2882 MEDCouplingPointSet::serialize(a1,a2);
2883 if(getMeshDimension()>-1)
2885 a1=DataArrayInt::New();
2886 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2887 int *ptA1=a1->getPointer();
2888 const int *conn=getNodalConnectivity()->getConstPointer();
2889 const int *index=getNodalConnectivityIndex()->getConstPointer();
2890 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2891 std::copy(conn,conn+getMeshLength(),ptA1);
2898 * Second and final unserialization process.
2899 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2901 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2903 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2904 setMeshDimension(tinyInfo[5]);
2908 const int *recvBuffer=a1->getConstPointer();
2909 DataArrayInt* myConnecIndex=DataArrayInt::New();
2910 myConnecIndex->alloc(tinyInfo[6]+1,1);
2911 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2912 DataArrayInt* myConnec=DataArrayInt::New();
2913 myConnec->alloc(tinyInfo[7],1);
2914 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2915 setConnectivity(myConnec, myConnecIndex) ;
2916 myConnec->decrRef();
2917 myConnecIndex->decrRef();
2922 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2923 * CellIds are given using range specified by a start an end and step.
2925 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2927 checkFullyDefined();
2928 int ncell=getNumberOfCells();
2929 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2930 ret->_mesh_dim=_mesh_dim;
2931 ret->setCoords(_coords);
2932 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2934 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2936 const int *conn=_nodal_connec->getConstPointer();
2937 const int *connIndex=_nodal_connec_index->getConstPointer();
2938 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2940 if(work>=0 && work<ncell)
2942 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2946 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2947 throw INTERP_KERNEL::Exception(oss.str().c_str());
2950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
2951 int *newConnPtr=newConn->getPointer();
2952 std::set<INTERP_KERNEL::NormalizedCellType> types;
2954 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2956 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
2957 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
2959 ret->setConnectivity(newConn,newConnI,false);
2961 ret->copyTinyInfoFrom(this);
2966 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
2967 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2968 * The return newly allocated mesh will share the same coordinates as 'this'.
2970 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
2972 checkFullyDefined();
2973 int ncell=getNumberOfCells();
2974 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2975 ret->_mesh_dim=_mesh_dim;
2976 ret->setCoords(_coords);
2977 std::size_t nbOfElemsRet=std::distance(begin,end);
2978 int *connIndexRet=new int[nbOfElemsRet+1];
2980 const int *conn=_nodal_connec->getConstPointer();
2981 const int *connIndex=_nodal_connec_index->getConstPointer();
2983 for(const int *work=begin;work!=end;work++,newNbring++)
2985 if(*work>=0 && *work<ncell)
2986 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
2989 delete [] connIndexRet;
2990 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
2991 throw INTERP_KERNEL::Exception(oss.str().c_str());
2994 int *connRet=new int[connIndexRet[nbOfElemsRet]];
2995 int *connRetWork=connRet;
2996 std::set<INTERP_KERNEL::NormalizedCellType> types;
2997 for(const int *work=begin;work!=end;work++)
2999 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3000 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3002 DataArrayInt *connRetArr=DataArrayInt::New();
3003 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3004 DataArrayInt *connIndexRetArr=DataArrayInt::New();
3005 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3006 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3008 connRetArr->decrRef();
3009 connIndexRetArr->decrRef();
3010 ret->copyTinyInfoFrom(this);
3015 * brief returns the volumes of the cells underlying the field \a field
3017 * For 2D geometries, the returned field contains the areas.
3018 * For 3D geometries, the returned field contains the volumes.
3020 * param field field on which cells the volumes are required
3021 * return field containing the volumes, area or length depending the meshdimension.
3023 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3025 std::string name="MeasureOfMesh_";
3027 int nbelem=getNumberOfCells();
3028 MEDCouplingFieldDouble *field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3029 field->setName(name.c_str());
3030 DataArrayDouble* array=DataArrayDouble::New();
3031 array->alloc(nbelem,1);
3032 double *area_vol=array->getPointer();
3033 field->setArray(array) ;
3035 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3036 field->synchronizeTimeWithMesh();
3037 if(getMeshDimension()!=-1)
3040 INTERP_KERNEL::NormalizedCellType type;
3041 int dim_space=getSpaceDimension();
3042 const double *coords=getCoords()->getConstPointer();
3043 const int *connec=getNodalConnectivity()->getConstPointer();
3044 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3045 for(int iel=0;iel<nbelem;iel++)
3047 ipt=connec_index[iel];
3048 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3049 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);
3052 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3056 area_vol[0]=std::numeric_limits<double>::max();
3062 * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3063 * This method avoids to build explicitely part of this to perform the work.
3065 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3067 std::string name="PartMeasureOfMesh_";
3069 int nbelem=(int)std::distance(begin,end);
3070 DataArrayDouble* array=DataArrayDouble::New();
3071 array->setName(name.c_str());
3072 array->alloc(nbelem,1);
3073 double *area_vol=array->getPointer();
3074 if(getMeshDimension()!=-1)
3077 INTERP_KERNEL::NormalizedCellType type;
3078 int dim_space=getSpaceDimension();
3079 const double *coords=getCoords()->getConstPointer();
3080 const int *connec=getNodalConnectivity()->getConstPointer();
3081 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3082 for(const int *iel=begin;iel!=end;iel++)
3084 ipt=connec_index[*iel];
3085 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3086 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3089 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3093 area_vol[0]=std::numeric_limits<double>::max();
3099 * This methods returns a field on nodes and no time. This method is usefull to check "P1*" conservative interpolators.
3100 * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3102 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3104 MEDCouplingFieldDouble *tmp=getMeasureField(isAbs);
3105 std::string name="MeasureOnNodeOfMesh_";
3107 int nbNodes=getNumberOfNodes();
3108 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_NODES);
3109 double cst=1./((double)getMeshDimension()+1.);
3110 DataArrayDouble* array=DataArrayDouble::New();
3111 array->alloc(nbNodes,1);
3112 double *valsToFill=array->getPointer();
3113 std::fill(valsToFill,valsToFill+nbNodes,0.);
3114 const double *values=tmp->getArray()->getConstPointer();
3115 DataArrayInt *da=DataArrayInt::New();
3116 DataArrayInt *daInd=DataArrayInt::New();
3117 getReverseNodalConnectivity(da,daInd);
3118 const int *daPtr=da->getConstPointer();
3119 const int *daIPtr=daInd->getConstPointer();
3120 for(int i=0;i<nbNodes;i++)
3121 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3122 valsToFill[i]+=cst*values[*cell];
3126 ret->setArray(array);
3133 * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3134 * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3136 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3138 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3139 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3140 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3141 DataArrayDouble *array=DataArrayDouble::New();
3142 int nbOfCells=getNumberOfCells();
3143 int nbComp=getMeshDimension()+1;
3144 array->alloc(nbOfCells,nbComp);
3145 double *vals=array->getPointer();
3146 const int *connI=_nodal_connec_index->getConstPointer();
3147 const int *conn=_nodal_connec->getConstPointer();
3148 const double *coords=_coords->getConstPointer();
3149 if(getMeshDimension()==2)
3151 if(getSpaceDimension()==3)
3153 DataArrayDouble *loc=getBarycenterAndOwner();
3154 const double *locPtr=loc->getConstPointer();
3155 for(int i=0;i<nbOfCells;i++,vals+=3)
3157 int offset=connI[i];
3158 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3159 double n=INTERP_KERNEL::norm<3>(vals);
3160 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3166 for(int i=0;i<nbOfCells;i++)
3167 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3170 else//meshdimension==1
3173 for(int i=0;i<nbOfCells;i++)
3175 int offset=connI[i];
3176 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3177 double n=INTERP_KERNEL::norm<2>(tmp);
3178 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3183 ret->setArray(array);
3186 ret->synchronizeTimeWithSupport();
3191 * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3192 * This method avoids to build explicitely part of this to perform the work.
3194 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3196 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3197 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3198 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3199 DataArrayDouble *array=DataArrayDouble::New();
3200 std::size_t nbelems=std::distance(begin,end);
3201 int nbComp=getMeshDimension()+1;
3202 array->alloc((int)nbelems,nbComp);
3203 double *vals=array->getPointer();
3204 const int *connI=_nodal_connec_index->getConstPointer();
3205 const int *conn=_nodal_connec->getConstPointer();
3206 const double *coords=_coords->getConstPointer();
3207 if(getMeshDimension()==2)
3209 if(getSpaceDimension()==3)
3211 DataArrayDouble *loc=getPartBarycenterAndOwner(begin,end);
3212 const double *locPtr=loc->getConstPointer();
3213 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3215 int offset=connI[*i];
3216 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3217 double n=INTERP_KERNEL::norm<3>(vals);
3218 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3224 for(std::size_t i=0;i<nbelems;i++)
3225 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3228 else//meshdimension==1
3231 for(const int *i=begin;i!=end;i++)
3233 int offset=connI[*i];
3234 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3235 double n=INTERP_KERNEL::norm<2>(tmp);
3236 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3241 ret->setArray(array);
3244 ret->synchronizeTimeWithSupport();
3249 * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3250 * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3252 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3254 if(getMeshDimension()!=1)
3255 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3256 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3257 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3258 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3259 DataArrayDouble *array=DataArrayDouble::New();
3260 int nbOfCells=getNumberOfCells();
3261 int spaceDim=getSpaceDimension();
3262 array->alloc(nbOfCells,spaceDim);
3263 double *pt=array->getPointer();
3264 const double *coo=getCoords()->getConstPointer();
3265 std::vector<int> conn;
3267 for(int i=0;i<nbOfCells;i++)
3270 getNodeIdsOfCell(i,conn);
3271 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3273 ret->setArray(array);
3276 ret->synchronizeTimeWithSupport();
3281 * 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.
3282 * This method returns 2 objects :
3283 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3284 * - 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
3285 * mesh the 3D cell id is 'this' it comes from.
3286 * This method works only for linear meshes (non quadratic).
3287 * 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
3288 * face. Only 'cellIds' parameter can distinguish the 2.
3289 * @param origin is the origin of the plane. It should be an array of length 3.
3290 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3291 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3292 * 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).
3294 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3296 checkFullyDefined();
3297 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3298 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3300 if(candidates->empty())
3301 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3302 std::vector<int> nodes;
3303 DataArrayInt *cellIds1D=0;
3304 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3305 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3310 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3311 revDesc2=0; revDescIndx2=0;
3312 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3313 revDesc1=0; revDescIndx1=0;
3314 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3317 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3318 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3320 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3321 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3322 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3323 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3324 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3326 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3327 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3328 if(cellIds2->empty())
3329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3330 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3331 ret->setCoords(mDesc1->getCoords());
3332 ret->setConnectivity(conn,connI,true);
3333 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3338 * 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.
3339 * This method returns 2 objects :
3340 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3341 * - 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
3342 * mesh the 3DSurf cell id is 'this' it comes from.
3343 * This method works only for linear meshes (non quadratic).
3344 * 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
3345 * face. Only 'cellIds' parameter can distinguish the 2.
3346 * @param origin is the origin of the plane. It should be an array of length 3.
3347 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3348 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3349 * 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).
3351 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3353 checkFullyDefined();
3354 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3357 if(candidates->empty())
3358 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3359 std::vector<int> nodes;
3360 DataArrayInt *cellIds1D=0;
3361 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3362 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3364 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3367 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3368 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3371 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3372 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3374 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3375 int ncellsSub=subMesh->getNumberOfCells();
3376 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3377 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3378 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3379 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3382 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3383 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3384 for(int i=0;i<ncellsSub;i++)
3386 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3388 if(cut3DSurf[i].first!=-2)
3390 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3391 connI->pushBackSilent(conn->getNumberOfTuples());
3392 cellIds2->pushBackSilent(i);
3396 int cellId3DSurf=cut3DSurf[i].second;
3397 int offset=nodalI[cellId3DSurf]+1;
3398 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3399 for(int j=0;j<nbOfEdges;j++)
3401 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3402 connI->pushBackSilent(conn->getNumberOfTuples());
3403 cellIds2->pushBackSilent(cellId3DSurf);
3408 if(cellIds2->empty())
3409 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3410 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3411 ret->setCoords(mDesc1->getCoords());
3412 ret->setConnectivity(conn,connI,true);
3413 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3418 * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3419 * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3420 * @param origin is the origin of the plane. It should be an array of length 3.
3421 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3423 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3425 checkFullyDefined();
3426 if(getSpaceDimension()!=3)
3427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3428 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3432 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3433 double angle=acos(vec[2]/normm);
3434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3438 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3439 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3440 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3442 mw->getBoundingBox(bbox);
3443 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3444 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3448 getBoundingBox(bbox);
3449 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3450 cellIds=getCellsInBoundingBox(bbox,eps);
3452 return cellIds.retn();
3456 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3457 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3458 * No consideration of coordinate is done by this method.
3459 * 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)
3460 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3462 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3464 if(getMeshDimension()!=1)
3465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3466 int nbCells=getNumberOfCells();
3468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3469 const int *connI=_nodal_connec_index->getConstPointer();
3470 const int *conn=_nodal_connec->getConstPointer();
3471 int ref=conn[connI[0]+2];
3472 for(int i=1;i<nbCells;i++)
3474 if(conn[connI[i]+1]!=ref)
3476 ref=conn[connI[i]+2];
3482 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3483 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3484 * @param pt reference point of the line
3485 * @param v normalized director vector of the line
3486 * @param eps max precision before throwing an exception
3487 * @param res output of size this->getNumberOfCells
3489 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3491 if(getMeshDimension()!=1)
3492 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3493 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3494 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3495 if(getSpaceDimension()!=3)
3496 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3497 MEDCouplingFieldDouble *f=buildDirectionVectorField();
3498 const double *fPtr=f->getArray()->getConstPointer();
3500 for(int i=0;i<getNumberOfCells();i++)
3502 const double *tmp1=fPtr+3*i;
3503 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3504 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3505 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3506 double n1=INTERP_KERNEL::norm<3>(tmp);
3507 n1/=INTERP_KERNEL::norm<3>(tmp1);
3511 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3514 const double *coo=getCoords()->getConstPointer();
3515 for(int i=0;i<getNumberOfNodes();i++)
3517 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3518 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3519 res[i]=std::accumulate(tmp,tmp+3,0.);
3525 * 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.
3526 * \a this is expected to be a mesh so that its space dimension is equal to its
3527 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3528 * 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).
3530 * 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
3531 * 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
3532 * to the node that minimizes distance with the input point then -1 is returned in cellId.
3534 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3535 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3537 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3538 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3539 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3540 * \return the positive value of the distance.
3541 * \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
3543 * \sa DataArrayDouble::distanceToTuple
3545 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
3547 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3548 if(meshDim!=spaceDim-1)
3549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3550 if(meshDim!=2 && meshDim!=1)
3551 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3552 checkFullyDefined();
3553 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3554 { 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()); }
3556 double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
3558 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
3559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
3564 distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
3569 distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
3573 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3581 * \param [in] pt the start pointer (included) of the coordinates of the point
3582 * \param [in] cellIds
3583 * \param [in,out] ret0 the min distance between \a this and the external input point
3584 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3585 * \sa MEDCouplingUMesh::distanceToPoint
3587 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3589 const double *coords=_coords->getConstPointer();
3591 if(cellIds->empty())
3593 const int *ptr=_nodal_connec->getConstPointer();
3594 const int *ptrI=_nodal_connec_index->getConstPointer();
3595 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3597 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3599 case INTERP_KERNEL::NORM_TRI3:
3601 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
3603 { ret0=tmp; cellId=*zeCell; }
3606 case INTERP_KERNEL::NORM_QUAD4:
3607 case INTERP_KERNEL::NORM_POLYGON:
3609 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
3611 { ret0=tmp; cellId=*zeCell; }
3615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3621 * \param [in] pt the start pointer (included) of the coordinates of the point
3622 * \param [in] cellIds
3623 * \param [in,out] ret0 the min distance between \a this and the external input point
3624 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3625 * \sa MEDCouplingUMesh::distanceToPoint
3627 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3629 const double *coords=_coords->getConstPointer();
3630 if(cellIds->empty())
3631 { cellId=-1; return; }
3632 const int *ptr=_nodal_connec->getConstPointer();
3633 const int *ptrI=_nodal_connec_index->getConstPointer();
3634 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3636 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3638 case INTERP_KERNEL::NORM_SEG2:
3640 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
3641 if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
3643 { ret0=tmp; cellId=*zeCell; }
3647 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3653 * Returns a cell if any that contains the point located on 'pos' with precison eps.
3654 * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3655 * \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'
3656 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3658 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3660 std::vector<int> elts;
3661 getCellsContainingPoint(pos,eps,elts);
3664 return elts.front();
3668 * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3669 * \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'
3670 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3672 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3674 std::vector<int> eltsIndex;
3675 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3680 namespace ParaMEDMEM
3682 template<const int SPACEDIMM>
3686 static const int MY_SPACEDIM=SPACEDIMM;
3687 static const int MY_MESHDIM=8;
3688 typedef int MyConnType;
3689 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3691 // useless, but for windows compilation ...
3692 const double* getCoordinatesPtr() const { return 0; }
3693 const int* getConnectivityPtr() const { return 0; }
3694 const int* getConnectivityIndexPtr() const { return 0; }
3695 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3699 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3701 INTERP_KERNEL::Edge *ret=0;
3704 case INTERP_KERNEL::NORM_SEG2:
3706 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3709 case INTERP_KERNEL::NORM_SEG3:
3711 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3712 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3713 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3714 bool colinearity=inters.areColinears();
3715 delete e1; delete e2;
3717 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3719 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3720 mapp2[bg[2]].second=false;
3724 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3730 * 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'.
3731 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3732 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3734 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3737 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.
3738 const double *coo=mDesc->getCoords()->getConstPointer();
3739 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3740 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3742 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3743 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3744 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3746 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3747 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3749 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3750 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3752 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3753 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3755 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3757 if((*it2).second.second)
3758 mapp[(*it2).second.first]=(*it2).first;
3759 ((*it2).second.first)->decrRef();
3764 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3768 int locId=nodeId-offset2;
3769 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3773 int locId=nodeId-offset1;
3774 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3776 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3779 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3780 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3781 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3783 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3785 int eltId1=abs(*desc1)-1;
3786 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3788 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3789 if(it==mappRev.end())
3791 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3802 template<int SPACEDIM>
3803 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3804 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3806 std::vector<double> bbox;
3807 eltsIndex.resize(nbOfPoints+1);
3810 getBoundingBoxForBBTree(bbox);
3811 int nbOfCells=getNumberOfCells();
3812 const int *conn=_nodal_connec->getConstPointer();
3813 const int *connI=_nodal_connec_index->getConstPointer();
3814 double bb[2*SPACEDIM];
3815 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3816 for(int i=0;i<nbOfPoints;i++)
3818 eltsIndex[i+1]=eltsIndex[i];
3819 for(int j=0;j<SPACEDIM;j++)
3821 bb[2*j]=pos[SPACEDIM*i+j];
3822 bb[2*j+1]=pos[SPACEDIM*i+j];
3824 std::vector<int> candidates;
3825 myTree.getIntersectingElems(bb,candidates);
3826 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3828 int sz=connI[(*iter)+1]-connI[*iter]-1;
3829 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3830 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3831 coords,conn+connI[*iter]+1,sz,eps))
3834 elts.push_back(*iter);
3841 * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3842 * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3843 * in case of multi points searching.
3844 * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3845 * 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]).
3847 * \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...
3849 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3850 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3852 int spaceDim=getSpaceDimension();
3853 int mDim=getMeshDimension();
3858 const double *coords=_coords->getConstPointer();
3859 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3866 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3868 else if(spaceDim==2)
3872 const double *coords=_coords->getConstPointer();
3873 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3876 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3878 else if(spaceDim==1)
3882 const double *coords=_coords->getConstPointer();
3883 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3886 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3889 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3893 * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3894 * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3895 * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3896 * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3898 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3900 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3901 if(getMeshDimension()!=2)
3902 throw INTERP_KERNEL::Exception(msg);
3903 int spaceDim=getSpaceDimension();
3904 if(spaceDim!=2 && spaceDim!=3)
3905 throw INTERP_KERNEL::Exception(msg);
3906 const int *conn=_nodal_connec->getConstPointer();
3907 const int *connI=_nodal_connec_index->getConstPointer();
3908 int nbOfCells=getNumberOfCells();
3909 std::vector<double> cell2DinS2;
3910 for(int i=0;i<nbOfCells;i++)
3912 int offset=connI[i];
3913 int nbOfNodesForCell=connI[i+1]-offset-1;
3914 if(nbOfNodesForCell<=3)
3916 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3917 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3918 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3925 * This method is typically requested to unbutterfly 2D linear cells in \b this.
3927 * 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.
3928 * 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.
3930 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3931 * This convex envelop is computed using Jarvis march algorithm.
3932 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3933 * 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)
3934 * 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.
3936 * @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.
3938 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3940 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
3942 checkFullyDefined();
3943 const double *coords=getCoords()->getConstPointer();
3944 int nbOfCells=getNumberOfCells();
3945 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3946 nodalConnecIndexOut->alloc(nbOfCells+1,1);
3947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
3948 int *workIndexOut=nodalConnecIndexOut->getPointer();
3950 const int *nodalConnecIn=_nodal_connec->getConstPointer();
3951 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3952 std::set<INTERP_KERNEL::NormalizedCellType> types;
3953 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
3954 isChanged->alloc(0,1);
3955 for(int i=0;i<nbOfCells;i++,workIndexOut++)
3957 int pos=nodalConnecOut->getNumberOfTuples();
3958 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3959 isChanged->pushBackSilent(i);
3960 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
3961 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
3963 if(isChanged->empty())
3965 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
3967 return isChanged.retn();
3971 * This method is \b NOT const because it can modify 'this'.
3972 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
3973 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
3974 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
3975 * \b 1 for translation and rotation around point of 'mesh1D'.
3976 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
3978 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
3980 checkFullyDefined();
3981 mesh1D->checkFullyDefined();
3982 if(!mesh1D->isContiguous1D())
3983 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
3984 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
3985 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same dimension !");
3986 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3987 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
3988 if(mesh1D->getMeshDimension()!=1)
3989 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
3991 if(isPresenceOfQuadratic())
3993 if(mesh1D->isFullyQuadratic())
3996 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
3999 int oldNbOfNodes=getNumberOfNodes();
4000 DataArrayDouble *newCoords=0;
4005 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4010 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4014 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4016 setCoords(newCoords);
4017 newCoords->decrRef();
4018 MEDCouplingUMesh *ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4024 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4025 * If it is not the case an exception will be thrown.
4026 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4027 * intersection of plane defined by ('origin','vec').
4028 * This method has one in/out parameter : 'cut3DCurve'.
4029 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4030 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4031 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4032 * This method will throw an exception if 'this' contains a non linear segment.
4034 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4036 checkFullyDefined();
4037 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4038 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4039 int ncells=getNumberOfCells();
4040 int nnodes=getNumberOfNodes();
4041 double vec2[3],vec3[3],vec4[3];
4042 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4044 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4045 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4046 const int *conn=_nodal_connec->getConstPointer();
4047 const int *connI=_nodal_connec_index->getConstPointer();
4048 const double *coo=_coords->getConstPointer();
4049 std::vector<double> addCoo;
4050 for(int i=0;i<ncells;i++)
4052 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4054 if(cut3DCurve[i]==-2)
4056 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4057 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];
4058 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4059 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4060 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4062 const double *st2=coo+3*st;
4063 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4064 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]));
4065 if(pos>eps && pos<1-eps)
4067 int nNode=((int)addCoo.size())/3;
4068 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4069 addCoo.insert(addCoo.end(),vec4,vec4+3);
4070 cut3DCurve[i]=nnodes+nNode;
4076 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4080 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4081 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4082 coo2->alloc(newNbOfNodes,3);
4083 double *tmp=coo2->getPointer();
4084 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4085 std::copy(addCoo.begin(),addCoo.end(),tmp);
4086 DataArrayDouble::SetArrayIn(coo2,_coords);
4091 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4092 * @param mesh1D is the input 1D mesh used for translation computation.
4093 * @return newCoords new coords filled by this method.
4095 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4097 int oldNbOfNodes=getNumberOfNodes();
4098 int nbOf1DCells=mesh1D->getNumberOfCells();
4099 int spaceDim=getSpaceDimension();
4100 DataArrayDouble *ret=DataArrayDouble::New();
4101 std::vector<bool> isQuads;
4102 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4103 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4104 double *retPtr=ret->getPointer();
4105 const double *coords=getCoords()->getConstPointer();
4106 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4108 std::vector<double> c;
4112 for(int i=0;i<nbOf1DCells;i++)
4115 mesh1D->getNodeIdsOfCell(i,v);
4117 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4118 mesh1D->getCoordinatesOfNode(v[0],c);
4119 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4120 for(int j=0;j<oldNbOfNodes;j++)
4121 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4125 mesh1D->getCoordinatesOfNode(v[1],c);
4126 mesh1D->getCoordinatesOfNode(v[0],c);
4127 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4128 for(int j=0;j<oldNbOfNodes;j++)
4129 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4132 ret->copyStringInfoFrom(*getCoords());
4137 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4138 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4139 * @return newCoords new coords filled by this method.
4141 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4143 if(mesh1D->getSpaceDimension()==2)
4144 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4145 if(mesh1D->getSpaceDimension()==3)
4146 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4147 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4151 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4152 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4153 * @return newCoords new coords filled by this method.
4155 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4158 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4159 int oldNbOfNodes=getNumberOfNodes();
4160 int nbOf1DCells=mesh1D->getNumberOfCells();
4162 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4163 DataArrayDouble *ret=DataArrayDouble::New();
4164 int nbOfLevsInVec=nbOf1DCells+1;
4165 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4166 double *retPtr=ret->getPointer();
4167 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4168 MEDCouplingUMesh *tmp=MEDCouplingUMesh::New();
4169 DataArrayDouble *tmp2=getCoords()->deepCpy();
4170 tmp->setCoords(tmp2);
4172 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4173 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4174 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4175 for(int i=1;i<nbOfLevsInVec;i++)
4177 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4178 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4179 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4180 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4181 tmp->translate(vec);
4182 double tmp3[2],radius,alpha,alpha0;
4183 const double *p0=i+1<nbOfLevsInVec?begin:third;
4184 const double *p1=i+1<nbOfLevsInVec?end:begin;
4185 const double *p2=i+1<nbOfLevsInVec?third:end;
4186 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4187 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]);
4188 double angle=acos(cosangle/(radius*radius));
4189 tmp->rotate(end,0,angle);
4190 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4197 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4198 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4199 * @return newCoords new coords filled by this method.
4201 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4204 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4205 int oldNbOfNodes=getNumberOfNodes();
4206 int nbOf1DCells=mesh1D->getNumberOfCells();
4208 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4209 DataArrayDouble *ret=DataArrayDouble::New();
4210 int nbOfLevsInVec=nbOf1DCells+1;
4211 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4212 double *retPtr=ret->getPointer();
4213 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4214 MEDCouplingUMesh *tmp=MEDCouplingUMesh::New();
4215 DataArrayDouble *tmp2=getCoords()->deepCpy();
4216 tmp->setCoords(tmp2);
4218 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4219 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4220 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4221 for(int i=1;i<nbOfLevsInVec;i++)
4223 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4224 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4225 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4226 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4227 tmp->translate(vec);
4228 double tmp3[2],radius,alpha,alpha0;
4229 const double *p0=i+1<nbOfLevsInVec?begin:third;
4230 const double *p1=i+1<nbOfLevsInVec?end:begin;
4231 const double *p2=i+1<nbOfLevsInVec?third:end;
4232 double vecPlane[3]={
4233 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4234 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4235 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4237 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4240 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4241 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4242 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4244 double c2=cos(asin(s2));
4246 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4247 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4248 {-vec2[1]*s2, vec2[0]*s2, c2}
4250 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]};
4251 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]};
4252 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]};
4253 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4254 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]);
4255 double angle=acos(cosangle/(radius*radius));
4256 tmp->rotate(end,vecPlane,angle);
4259 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4266 * This method is private because not easy to use for end user. This method is const contrary to
4267 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4268 * the coords sorted slice by slice.
4269 * @param isQuad specifies presence of quadratic cells.
4271 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4273 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4274 int nbOf2DCells=getNumberOfCells();
4275 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4276 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4277 const int *conn=_nodal_connec->getConstPointer();
4278 const int *connI=_nodal_connec_index->getConstPointer();
4279 DataArrayInt *newConn=DataArrayInt::New();
4280 DataArrayInt *newConnI=DataArrayInt::New();
4281 newConnI->alloc(nbOf3DCells+1,1);
4282 int *newConnIPtr=newConnI->getPointer();
4284 std::vector<int> newc;
4285 for(int j=0;j<nbOf2DCells;j++)
4287 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4288 *newConnIPtr++=(int)newc.size();
4290 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4291 int *newConnPtr=newConn->getPointer();
4292 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4293 newConnIPtr=newConnI->getPointer();
4294 for(int iz=0;iz<nbOf1DCells;iz++)
4297 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4298 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4300 int icell=(int)(iter-newc.begin());
4301 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4304 *newConnPtr=(*iter)+iz*deltaPerLev;
4309 *newConnPtr=(*iter);
4312 ret->setConnectivity(newConn,newConnI,true);
4314 newConnI->decrRef();
4315 ret->setCoords(getCoords());
4320 * This method returns if 'this' is constituted by only quadratic cells.
4322 bool MEDCouplingUMesh::isFullyQuadratic() const
4324 checkFullyDefined();
4326 int nbOfCells=getNumberOfCells();
4327 for(int i=0;i<nbOfCells && ret;i++)
4329 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4330 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4331 ret=cm.isQuadratic();
4337 * This method returns if there is at least one quadratic cell.
4339 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4341 checkFullyDefined();
4343 int nbOfCells=getNumberOfCells();
4344 for(int i=0;i<nbOfCells && !ret;i++)
4346 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4347 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4348 ret=cm.isQuadratic();
4354 * This method convert quadratic cells to linear cells if any was found.
4355 * If no such cells exists 'this' remains unchanged.
4357 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4359 checkFullyDefined();
4360 int nbOfCells=getNumberOfCells();
4362 for(int i=0;i<nbOfCells;i++)
4364 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4365 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4366 if(cm.isQuadratic())
4368 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4369 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4370 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4377 newConn->alloc(getMeshLength()-delta,1);
4378 newConnI->alloc(nbOfCells+1,1);
4379 const int *icptr=_nodal_connec->getConstPointer();
4380 const int *iciptr=_nodal_connec_index->getConstPointer();
4381 int *ocptr=newConn->getPointer();
4382 int *ociptr=newConnI->getPointer();
4385 for(int i=0;i<nbOfCells;i++,ociptr++)
4387 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4388 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4389 if(!cm.isQuadratic())
4391 _types.insert(type);
4392 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4393 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4397 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4398 _types.insert(typel);
4399 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4400 int newNbOfNodes=cml.getNumberOfNodes();
4401 *ocptr++=(int)typel;
4402 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4403 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4406 setConnectivity(newConn,newConnI,false);
4410 * This method tessallates 'this' so that the number of cells remains the same.
4411 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4412 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4414 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4415 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4417 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4419 checkFullyDefined();
4420 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4422 double epsa=fabs(eps);
4423 if(epsa<std::numeric_limits<double>::min())
4424 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 !");
4425 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4429 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4430 revDesc1=0; revDescIndx1=0;
4431 mDesc->tessellate2DCurve(eps);
4432 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4433 setCoords(mDesc->getCoords());
4437 * This method tessallates 'this' so that the number of cells remains the same.
4438 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4439 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4441 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4442 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4444 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4446 checkFullyDefined();
4447 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4448 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4449 double epsa=fabs(eps);
4450 if(epsa<std::numeric_limits<double>::min())
4451 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 !");
4452 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4453 int nbCells=getNumberOfCells();
4454 int nbNodes=getNumberOfNodes();
4455 const int *conn=_nodal_connec->getConstPointer();
4456 const int *connI=_nodal_connec_index->getConstPointer();
4457 const double *coords=_coords->getConstPointer();
4458 std::vector<double> addCoo;
4459 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
4460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
4461 newConnI->alloc(nbCells+1,1);
4462 int *newConnIPtr=newConnI->getPointer();
4465 INTERP_KERNEL::Node *tmp2[3];
4466 std::set<INTERP_KERNEL::NormalizedCellType> types;
4467 for(int i=0;i<nbCells;i++,newConnIPtr++)
4469 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4470 if(cm.isQuadratic())
4471 {//assert(connI[i+1]-connI[i]-1==3)
4472 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4473 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4474 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4475 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4476 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4479 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4480 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4482 newConnIPtr[1]=(int)newConn.size();
4486 types.insert(INTERP_KERNEL::NORM_SEG2);
4487 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4488 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4489 newConnIPtr[1]=newConnIPtr[0]+3;
4494 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4495 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4496 newConnIPtr[1]=newConnIPtr[0]+3;
4499 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4502 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4503 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4504 newConnArr->alloc((int)newConn.size(),1);
4505 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4506 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4507 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4508 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4509 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4510 std::copy(addCoo.begin(),addCoo.end(),work);
4511 DataArrayDouble::SetArrayIn(newCoords,_coords);
4516 * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4517 * This cut into simplex is performed following the parameter \a policy. This method so typically increases the number of cells of \a this.
4518 * 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.
4519 * This method returns new2old newly allocated array that specifies a each cell of \a this after the call what was its id it comes.
4521 * The semantic of \a policy parameter :
4522 * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4523 * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4524 * - PLANAR_FACE_5 only HEXA8. All HEXA8 are split into 5 TETRA4
4525 * - PLANAR_FACE_6 only HEXA8. All HEXA8 are split into 6 TETRA4
4527 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4532 return simplexizePol0();
4534 return simplexizePol1();
4535 case (int) INTERP_KERNEL::PLANAR_FACE_5:
4536 return simplexizePlanarFace5();
4537 case (int) INTERP_KERNEL::PLANAR_FACE_6:
4538 return simplexizePlanarFace6();
4540 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)");
4544 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4546 checkFullyDefined();
4547 if(getMeshDimension()<1)
4548 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4549 int nbCells=getNumberOfCells();
4550 const int *conn=_nodal_connec->getConstPointer();
4551 const int *connI=_nodal_connec_index->getConstPointer();
4552 for(int i=0;i<nbCells;i++)
4554 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4562 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4564 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4566 checkConnectivityFullyDefined();
4567 if(getMeshDimension()!=2)
4568 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4569 int nbOfCells=getNumberOfCells();
4570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4571 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4572 ret->alloc(nbOfCells+nbOfCutCells,1);
4573 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4574 int *retPt=ret->getPointer();
4575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4577 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4578 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4579 int *pt=newConn->getPointer();
4580 int *ptI=newConnI->getPointer();
4582 const int *oldc=_nodal_connec->getConstPointer();
4583 const int *ci=_nodal_connec_index->getConstPointer();
4584 for(int i=0;i<nbOfCells;i++,ci++)
4586 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4588 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4589 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4590 pt=std::copy(tmp,tmp+8,pt);
4599 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4600 ptI[1]=ptI[0]+ci[1]-ci[0];
4605 _nodal_connec->decrRef();
4606 _nodal_connec=newConn.retn();
4607 _nodal_connec_index->decrRef();
4608 _nodal_connec_index=newConnI.retn();
4615 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4617 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4619 checkConnectivityFullyDefined();
4620 if(getMeshDimension()!=2)
4621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4622 int nbOfCells=getNumberOfCells();
4623 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4624 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4625 ret->alloc(nbOfCells+nbOfCutCells,1);
4626 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4627 int *retPt=ret->getPointer();
4628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4630 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4631 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4632 int *pt=newConn->getPointer();
4633 int *ptI=newConnI->getPointer();
4635 const int *oldc=_nodal_connec->getConstPointer();
4636 const int *ci=_nodal_connec_index->getConstPointer();
4637 for(int i=0;i<nbOfCells;i++,ci++)
4639 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4641 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4642 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4643 pt=std::copy(tmp,tmp+8,pt);
4652 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4653 ptI[1]=ptI[0]+ci[1]-ci[0];
4658 _nodal_connec->decrRef();
4659 _nodal_connec=newConn.retn();
4660 _nodal_connec_index->decrRef();
4661 _nodal_connec_index=newConnI.retn();
4668 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4670 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
4672 checkConnectivityFullyDefined();
4673 if(getMeshDimension()!=3)
4674 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
4675 int nbOfCells=getNumberOfCells();
4676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4677 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
4678 ret->alloc(nbOfCells+4*nbOfCutCells,1);
4679 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4680 int *retPt=ret->getPointer();
4681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4682 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4683 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
4684 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
4685 int *pt=newConn->getPointer();
4686 int *ptI=newConnI->getPointer();
4688 const int *oldc=_nodal_connec->getConstPointer();
4689 const int *ci=_nodal_connec_index->getConstPointer();
4690 for(int i=0;i<nbOfCells;i++,ci++)
4692 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
4694 for(int j=0;j<5;j++,pt+=5,ptI++)
4696 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
4697 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];
4704 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4705 ptI[1]=ptI[0]+ci[1]-ci[0];
4710 _nodal_connec->decrRef();
4711 _nodal_connec=newConn.retn();
4712 _nodal_connec_index->decrRef();
4713 _nodal_connec_index=newConnI.retn();
4720 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4722 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
4724 checkConnectivityFullyDefined();
4725 if(getMeshDimension()!=3)
4726 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
4727 int nbOfCells=getNumberOfCells();
4728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4729 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
4730 ret->alloc(nbOfCells+5*nbOfCutCells,1);
4731 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4732 int *retPt=ret->getPointer();
4733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4735 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
4736 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
4737 int *pt=newConn->getPointer();
4738 int *ptI=newConnI->getPointer();
4740 const int *oldc=_nodal_connec->getConstPointer();
4741 const int *ci=_nodal_connec_index->getConstPointer();
4742 for(int i=0;i<nbOfCells;i++,ci++)
4744 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
4746 for(int j=0;j<6;j++,pt+=5,ptI++)
4748 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
4749 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];
4756 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4757 ptI[1]=ptI[0]+ci[1]-ci[0];
4762 _nodal_connec->decrRef();
4763 _nodal_connec=newConn.retn();
4764 _nodal_connec_index->decrRef();
4765 _nodal_connec_index=newConnI.retn();
4772 * 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.
4773 * This method completly ignore coordinates.
4774 * @param nodeSubdived is the nodal connectivity of subdivision of edges
4775 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
4776 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4777 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4779 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
4781 checkFullyDefined();
4782 if(getMeshDimension()!=2)
4783 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
4784 int nbOfCells=getNumberOfCells();
4785 int *connI=_nodal_connec_index->getPointer();
4787 for(int i=0;i<nbOfCells;i++,connI++)
4789 int offset=descIndex[i];
4790 int nbOfEdges=descIndex[i+1]-offset;
4792 bool ddirect=desc[offset+nbOfEdges-1]>0;
4793 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
4794 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
4795 for(int j=0;j<nbOfEdges;j++)
4797 bool direct=desc[offset+j]>0;
4798 int edgeId=std::abs(desc[offset+j])-1;
4799 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
4801 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
4802 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
4803 int ref2=direct?id1:id2;
4806 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4807 newConnLgth+=nbOfSubNodes-1;
4812 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
4813 throw INTERP_KERNEL::Exception(oss.str().c_str());
4818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
4821 newConnLgth++;//+1 is for cell type
4822 connI[1]=newConnLgth;
4825 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4826 newConn->alloc(newConnLgth,1);
4827 int *work=newConn->getPointer();
4828 for(int i=0;i<nbOfCells;i++)
4830 *work++=INTERP_KERNEL::NORM_POLYGON;
4831 int offset=descIndex[i];
4832 int nbOfEdges=descIndex[i+1]-offset;
4833 for(int j=0;j<nbOfEdges;j++)
4835 bool direct=desc[offset+j]>0;
4836 int edgeId=std::abs(desc[offset+j])-1;
4838 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
4841 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4842 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
4843 work=std::copy(it,it+nbOfSubNodes-1,work);
4847 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
4850 _types.insert(INTERP_KERNEL::NORM_POLYGON);
4854 * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
4855 * nodal connectivity will be transform to a NORM_TRI3 cell.
4856 * This method works \b only \b on \b linear cells.
4857 * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
4858 * method could be usefull before calling this method in case of presence of several pair of nodes located on same position.
4859 * This method throws an exception if 'this' is not fully defined (connectivity).
4860 * 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.
4862 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
4864 checkFullyDefined();
4865 if(getMeshDimension()<=1)
4866 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4867 int nbOfCells=getNumberOfCells();
4870 int initMeshLgth=getMeshLength();
4871 int *conn=_nodal_connec->getPointer();
4872 int *index=_nodal_connec_index->getPointer();
4876 for(int i=0;i<nbOfCells;i++)
4878 lgthOfCurCell=index[i+1]-posOfCurCell;
4879 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4881 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4882 conn+newPos+1,newLgth);
4883 conn[newPos]=newType;
4885 posOfCurCell=index[i+1];
4888 if(newPos!=initMeshLgth)
4889 _nodal_connec->reAlloc(newPos);
4894 * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
4895 * The 'vec' vector has to have a non nul norm.
4896 * If not 'cells' parameter will be appended with cellIds of incorrect cells.
4897 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
4899 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
4901 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4902 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4903 int nbOfCells=getNumberOfCells();
4904 const int *conn=_nodal_connec->getConstPointer();
4905 const int *connI=_nodal_connec_index->getConstPointer();
4906 const double *coordsPtr=_coords->getConstPointer();
4907 for(int i=0;i<nbOfCells;i++)
4909 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4910 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4912 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4913 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4920 * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
4921 * The 'vec' vector has to have a non nul norm.
4922 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
4924 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
4926 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4927 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4928 int nbOfCells=getNumberOfCells();
4929 int *conn=_nodal_connec->getPointer();
4930 const int *connI=_nodal_connec_index->getConstPointer();
4931 const double *coordsPtr=_coords->getConstPointer();
4932 bool isModified=false;
4933 for(int i=0;i<nbOfCells;i++)
4935 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4936 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4938 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4939 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4942 std::vector<int> tmp(connI[i+1]-connI[i]-2);
4943 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
4944 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
4949 _nodal_connec->declareAsNew();
4954 * This method checks that all polyhedrons cells have correctly oriented faces.
4955 * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
4956 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
4958 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
4960 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4961 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4962 int nbOfCells=getNumberOfCells();
4963 const int *conn=_nodal_connec->getConstPointer();
4964 const int *connI=_nodal_connec_index->getConstPointer();
4965 const double *coordsPtr=_coords->getConstPointer();
4966 for(int i=0;i<nbOfCells;i++)
4968 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4969 if(type==INTERP_KERNEL::NORM_POLYHED)
4971 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4978 * This method tries to orient correctly polhedrons cells.
4980 * \throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
4981 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4983 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
4985 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4986 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4987 int nbOfCells=getNumberOfCells();
4988 int *conn=_nodal_connec->getPointer();
4989 const int *connI=_nodal_connec_index->getConstPointer();
4990 const double *coordsPtr=_coords->getConstPointer();
4991 for(int i=0;i<nbOfCells;i++)
4993 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4994 if(type==INTERP_KERNEL::NORM_POLYHED)
4998 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4999 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5001 catch(INTERP_KERNEL::Exception& e)
5003 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5004 throw INTERP_KERNEL::Exception(oss.str().c_str());
5012 * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
5013 * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
5014 * 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).
5015 * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
5017 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5018 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5020 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5022 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5023 if(getMeshDimension()!=3)
5024 throw INTERP_KERNEL::Exception(msg);
5025 int spaceDim=getSpaceDimension();
5027 throw INTERP_KERNEL::Exception(msg);
5029 int nbOfCells=getNumberOfCells();
5030 int *conn=_nodal_connec->getPointer();
5031 const int *connI=_nodal_connec_index->getConstPointer();
5032 const double *coo=getCoords()->getConstPointer();
5033 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5034 for(int i=0;i<nbOfCells;i++)
5036 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5037 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5039 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5041 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5042 cells->pushBackSilent(i);
5046 return cells.retn();
5050 * This method is a faster method to correct orientation of all 3D cells in \a this.
5051 * 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.
5052 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5054 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5055 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5057 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5059 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5060 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5061 int nbOfCells=getNumberOfCells();
5062 int *conn=_nodal_connec->getPointer();
5063 const int *connI=_nodal_connec_index->getConstPointer();
5064 const double *coordsPtr=_coords->getConstPointer();
5065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5066 for(int i=0;i<nbOfCells;i++)
5068 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5071 case INTERP_KERNEL::NORM_TETRA4:
5073 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5075 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5076 ret->pushBackSilent(i);
5080 case INTERP_KERNEL::NORM_PYRA5:
5082 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5084 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5085 ret->pushBackSilent(i);
5089 case INTERP_KERNEL::NORM_PENTA6:
5090 case INTERP_KERNEL::NORM_HEXA8:
5091 case INTERP_KERNEL::NORM_HEXGP12:
5093 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5095 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5096 ret->pushBackSilent(i);
5100 case INTERP_KERNEL::NORM_POLYHED:
5102 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5104 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5105 ret->pushBackSilent(i);
5110 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 !");
5118 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5119 * If it is not the case an exception will be thrown.
5120 * This method is fast because the first cell of 'this' is used to compute the plane.
5121 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5122 * @param pos output of size at least 3 used to store a point owned of searched plane.
5124 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5126 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5127 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5128 const int *conn=_nodal_connec->getConstPointer();
5129 const int *connI=_nodal_connec_index->getConstPointer();
5130 const double *coordsPtr=_coords->getConstPointer();
5131 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5132 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5136 * The returned newly created field has to be managed by the caller.
5137 * 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.
5138 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5139 * If a cell has an another type an exception will be thrown.
5141 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5144 int spaceDim=getSpaceDimension();
5145 int meshDim=getMeshDimension();
5146 if(spaceDim!=2 && spaceDim!=3)
5147 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5148 if(meshDim!=2 && meshDim!=3)
5149 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5150 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5152 int nbOfCells=getNumberOfCells();
5153 DataArrayDouble *arr=DataArrayDouble::New();
5154 arr->alloc(nbOfCells,1);
5155 double *pt=arr->getPointer();
5156 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5158 const int *conn=_nodal_connec->getConstPointer();
5159 const int *connI=_nodal_connec_index->getConstPointer();
5160 const double *coo=_coords->getConstPointer();
5162 for(int i=0;i<nbOfCells;i++,pt++)
5164 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5167 case INTERP_KERNEL::NORM_TRI3:
5169 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5170 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5173 case INTERP_KERNEL::NORM_QUAD4:
5175 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5176 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5179 case INTERP_KERNEL::NORM_TETRA4:
5181 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5182 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5188 conn+=connI[i+1]-connI[i];
5190 ret->setName("EdgeRatio");
5191 ret->synchronizeTimeWithSupport();
5196 * The returned newly created field has to be managed by the caller.
5197 * 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.
5198 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5199 * If a cell has an another type an exception will be thrown.
5201 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5204 int spaceDim=getSpaceDimension();
5205 int meshDim=getMeshDimension();
5206 if(spaceDim!=2 && spaceDim!=3)
5207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5208 if(meshDim!=2 && meshDim!=3)
5209 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5210 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5212 int nbOfCells=getNumberOfCells();
5213 DataArrayDouble *arr=DataArrayDouble::New();
5214 arr->alloc(nbOfCells,1);
5215 double *pt=arr->getPointer();
5216 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5218 const int *conn=_nodal_connec->getConstPointer();
5219 const int *connI=_nodal_connec_index->getConstPointer();
5220 const double *coo=_coords->getConstPointer();
5222 for(int i=0;i<nbOfCells;i++,pt++)
5224 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5227 case INTERP_KERNEL::NORM_TRI3:
5229 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5230 *pt=INTERP_KERNEL::triAspectRatio(tmp);
5233 case INTERP_KERNEL::NORM_QUAD4:
5235 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5236 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5239 case INTERP_KERNEL::NORM_TETRA4:
5241 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5242 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5246 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5248 conn+=connI[i+1]-connI[i];
5250 ret->setName("AspectRatio");
5251 ret->synchronizeTimeWithSupport();
5256 * The returned newly created field has to be managed by the caller.
5257 * 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.
5258 * This method for the moment only deals with NORM_QUAD4 geometric type.
5259 * If a cell has an another type an exception will be thrown.
5261 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
5264 int spaceDim=getSpaceDimension();
5265 int meshDim=getMeshDimension();
5267 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5269 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5270 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5272 int nbOfCells=getNumberOfCells();
5273 DataArrayDouble *arr=DataArrayDouble::New();
5274 arr->alloc(nbOfCells,1);
5275 double *pt=arr->getPointer();
5276 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5278 const int *conn=_nodal_connec->getConstPointer();
5279 const int *connI=_nodal_connec_index->getConstPointer();
5280 const double *coo=_coords->getConstPointer();
5282 for(int i=0;i<nbOfCells;i++,pt++)
5284 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5287 case INTERP_KERNEL::NORM_QUAD4:
5289 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5290 *pt=INTERP_KERNEL::quadWarp(tmp);
5294 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5296 conn+=connI[i+1]-connI[i];
5298 ret->setName("Warp");
5299 ret->synchronizeTimeWithSupport();
5304 * The returned newly created field has to be managed by the caller.
5305 * 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.
5306 * This method for the moment only deals with NORM_QUAD4 geometric type.
5307 * If a cell has an another type an exception will be thrown.
5309 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5312 int spaceDim=getSpaceDimension();
5313 int meshDim=getMeshDimension();
5315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5317 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5320 int nbOfCells=getNumberOfCells();
5321 DataArrayDouble *arr=DataArrayDouble::New();
5322 arr->alloc(nbOfCells,1);
5323 double *pt=arr->getPointer();
5324 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5326 const int *conn=_nodal_connec->getConstPointer();
5327 const int *connI=_nodal_connec_index->getConstPointer();
5328 const double *coo=_coords->getConstPointer();
5330 for(int i=0;i<nbOfCells;i++,pt++)
5332 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5335 case INTERP_KERNEL::NORM_QUAD4:
5337 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5338 *pt=INTERP_KERNEL::quadSkew(tmp);
5342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5344 conn+=connI[i+1]-connI[i];
5346 ret->setName("Skew");
5347 ret->synchronizeTimeWithSupport();
5352 * This method aggregate the bbox of each cell and put it into bbox parameter.
5353 * @param bbox out parameter of size 2*spacedim*nbOfcells.
5355 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5357 int spaceDim=getSpaceDimension();
5358 int nbOfCells=getNumberOfCells();
5359 bbox.resize(2*nbOfCells*spaceDim);
5360 for(int i=0;i<nbOfCells*spaceDim;i++)
5362 bbox[2*i]=std::numeric_limits<double>::max();
5363 bbox[2*i+1]=-std::numeric_limits<double>::max();
5365 const double *coordsPtr=_coords->getConstPointer();
5366 const int *conn=_nodal_connec->getConstPointer();
5367 const int *connI=_nodal_connec_index->getConstPointer();
5368 for(int i=0;i<nbOfCells;i++)
5370 int offset=connI[i]+1;
5371 int nbOfNodesForCell=connI[i+1]-offset;
5372 for(int j=0;j<nbOfNodesForCell;j++)
5374 int nodeId=conn[offset+j];
5376 for(int k=0;k<spaceDim;k++)
5378 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5379 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5387 namespace ParaMEDMEMImpl
5392 ConnReader(const int *c, int val):_conn(c),_val(val) { }
5393 bool operator() (const int& pos) { return _conn[pos]!=_val; }
5402 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5403 bool operator() (const int& pos) { return _conn[pos]==_val; }
5413 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5414 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5415 * 'this' is composed in cell types.
5416 * The returned array is of size 3*n where n is the number of different types present in 'this'.
5417 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
5418 * This parameter is kept only for compatibility with other methode listed above.
5420 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5422 checkConnectivityFullyDefined();
5423 const int *conn=_nodal_connec->getConstPointer();
5424 const int *connI=_nodal_connec_index->getConstPointer();
5425 const int *work=connI;
5426 int nbOfCells=getNumberOfCells();
5427 std::size_t n=getAllTypes().size();
5428 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5429 std::set<INTERP_KERNEL::NormalizedCellType> types;
5430 for(std::size_t i=0;work!=connI+nbOfCells;i++)
5432 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5433 if(types.find(typ)!=types.end())
5435 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5436 oss << " is not contiguous !";
5437 throw INTERP_KERNEL::Exception(oss.str().c_str());
5441 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5442 ret[3*i+1]=(int)std::distance(work,work2);
5449 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5450 * only for types cell, type node is not managed.
5451 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5452 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5453 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5454 * If 2 or more same geometric type is in 'code' and exception is thrown too.
5456 * This method firstly checks
5457 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5458 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5459 * an exception is thrown too.
5461 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5462 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
5463 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5465 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5469 std::size_t sz=code.size();
5472 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5473 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5475 for(std::size_t i=0;i<n;i++)
5476 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5478 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5480 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5481 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5484 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5485 if(idsPerType.empty())
5487 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5488 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5489 if(types.size()==_types.size())
5492 DataArrayInt *ret=DataArrayInt::New();
5494 int *retPtr=ret->getPointer();
5495 const int *connI=_nodal_connec_index->getConstPointer();
5496 const int *conn=_nodal_connec->getConstPointer();
5497 int nbOfCells=getNumberOfCells();
5500 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5502 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5503 int offset=(int)std::distance(connI,i);
5504 if(code[3*kk+2]==-1)
5506 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5507 std::size_t pos2=std::distance(i,j);
5508 for(std::size_t k=0;k<pos2;k++)
5509 *retPtr++=(int)k+offset;
5514 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5515 retPtr,std::bind2nd(std::plus<int>(),offset));
5522 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
5523 * 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.
5524 * 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.
5525 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
5527 * @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.
5528 * @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,
5529 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5530 * @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.
5531 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5532 * @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
5534 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5536 if(profile->getNumberOfComponents()!=1)
5537 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5538 checkConnectivityFullyDefined();
5539 const int *conn=_nodal_connec->getConstPointer();
5540 const int *connI=_nodal_connec_index->getConstPointer();
5541 int nbOfCells=getNumberOfCells();
5542 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5543 std::vector<int> typeRangeVals(1);
5544 for(const int *i=connI;i!=connI+nbOfCells;)
5546 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5547 if(std::find(types.begin(),types.end(),curType)!=types.end())
5549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5551 types.push_back(curType);
5552 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5553 typeRangeVals.push_back((int)std::distance(connI,i));
5556 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5557 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5562 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5563 code.resize(3*nbOfCastsFinal);
5564 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5565 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5566 for(int i=0;i<nbOfCastsFinal;i++)
5568 int castId=castsPresent->getIJ(i,0);
5569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5570 idsInPflPerType2.push_back(tmp3);
5571 code[3*i]=(int)types[castId];
5572 code[3*i+1]=tmp3->getNumberOfTuples();
5573 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5574 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5576 tmp4->copyStringInfoFrom(*profile);
5577 idsPerType2.push_back(tmp4);
5578 code[3*i+2]=(int)idsPerType2.size()-1;
5585 std::size_t sz2=idsInPflPerType2.size();
5586 idsInPflPerType.resize(sz2);
5587 for(std::size_t i=0;i<sz2;i++)
5589 DataArrayInt *locDa=idsInPflPerType2[i];
5591 idsInPflPerType[i]=locDa;
5593 std::size_t sz=idsPerType2.size();
5594 idsPerType.resize(sz);
5595 for(std::size_t i=0;i<sz;i++)
5597 DataArrayInt *locDa=idsPerType2[i];
5599 idsPerType[i]=locDa;
5604 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5605 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5606 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5607 * 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.
5609 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5611 checkFullyDefined();
5612 nM1LevMesh->checkFullyDefined();
5613 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5614 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5615 if(_coords!=nM1LevMesh->getCoords())
5616 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5618 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5619 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5620 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5621 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5622 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5623 tmp->setConnectivity(tmp0,tmp1);
5624 tmp->renumberCells(ret0->getConstPointer(),false);
5625 revDesc=tmp->getNodalConnectivity();
5626 revDescIndx=tmp->getNodalConnectivityIndex();
5627 DataArrayInt *ret=0;
5628 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5631 ret->getMaxValue(tmp2);
5633 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5634 throw INTERP_KERNEL::Exception(oss.str().c_str());
5639 revDescIndx->incrRef();
5642 meshnM1Old2New=ret0;
5647 * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5648 * It avoids to deal with renum in MEDLoader so it is usefull for MED file R/W with multi types.
5649 * This method returns a newly allocated array old2New.
5650 * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5652 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5654 checkConnectivityFullyDefined();
5655 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5656 renumberCells(ret->getConstPointer(),false);
5661 * This methods checks that cells are sorted by their types.
5662 * This method makes asumption (no check) that connectivity is correctly set before calling.
5664 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5666 checkFullyDefined();
5667 const int *conn=_nodal_connec->getConstPointer();
5668 const int *connI=_nodal_connec_index->getConstPointer();
5669 int nbOfCells=getNumberOfCells();
5670 std::set<INTERP_KERNEL::NormalizedCellType> types;
5671 for(const int *i=connI;i!=connI+nbOfCells;)
5673 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5674 if(types.find(curType)!=types.end())
5676 types.insert(curType);
5677 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5683 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5684 * The geometric type order is specified by MED file.
5686 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5688 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
5690 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5694 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5695 * that the order is specified in array defined by [orderBg,orderEnd).
5697 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5699 checkFullyDefined();
5700 const int *conn=_nodal_connec->getConstPointer();
5701 const int *connI=_nodal_connec_index->getConstPointer();
5702 int nbOfCells=getNumberOfCells();
5704 for(const int *i=connI;i!=connI+nbOfCells;)
5706 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5707 int pos=(int)std::distance(orderBg,std::find(orderBg,orderEnd,curType));
5711 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5717 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5718 * 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
5719 * 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'.
5721 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
5723 checkConnectivityFullyDefined();
5724 int nbOfCells=getNumberOfCells();
5725 const int *conn=_nodal_connec->getConstPointer();
5726 const int *connI=_nodal_connec_index->getConstPointer();
5727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
5728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
5729 tmpa->alloc(nbOfCells,1);
5730 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5731 tmpb->fillWithZero();
5732 int *tmp=tmpa->getPointer();
5733 int *tmp2=tmpb->getPointer();
5734 for(const int *i=connI;i!=connI+nbOfCells;i++)
5736 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5739 int pos=(int)std::distance(orderBg,where);
5741 tmp[std::distance(connI,i)]=pos;
5745 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5746 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5747 oss << " has a type " << cm.getRepr() << " not in input array of type !";
5748 throw INTERP_KERNEL::Exception(oss.str().c_str());
5751 nbPerType=tmpb.retn();
5756 * 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'.
5757 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5758 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5759 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5761 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
5763 DataArrayInt *nbPerType=0;
5764 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5765 nbPerType->decrRef();
5766 return tmpa->buildPermArrPerLevel();
5770 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
5771 * The number of cells remains unchanged after the call of this method.
5772 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5773 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5775 * @return the array giving the correspondance old to new.
5777 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5779 checkFullyDefined();
5781 const int *conn=_nodal_connec->getConstPointer();
5782 const int *connI=_nodal_connec_index->getConstPointer();
5783 int nbOfCells=getNumberOfCells();
5784 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5785 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5786 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5788 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5789 types.push_back(curType);
5790 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5792 DataArrayInt *ret=DataArrayInt::New();
5793 ret->alloc(nbOfCells,1);
5794 int *retPtr=ret->getPointer();
5795 std::fill(retPtr,retPtr+nbOfCells,-1);
5797 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5799 for(const int *i=connI;i!=connI+nbOfCells;i++)
5800 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5801 retPtr[std::distance(connI,i)]=newCellId++;
5803 renumberCells(retPtr,false);
5808 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
5809 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5810 * This method makes asumption that connectivity is correctly set before calling.
5812 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5814 checkFullyDefined();
5815 const int *conn=_nodal_connec->getConstPointer();
5816 const int *connI=_nodal_connec_index->getConstPointer();
5817 int nbOfCells=getNumberOfCells();
5818 std::vector<MEDCouplingUMesh *> ret;
5819 for(const int *i=connI;i!=connI+nbOfCells;)
5821 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5822 int beginCellId=(int)std::distance(connI,i);
5823 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5824 int endCellId=(int)std::distance(connI,i);
5825 int sz=endCellId-beginCellId;
5826 int *cells=new int[sz];
5827 for(int j=0;j<sz;j++)
5828 cells[j]=beginCellId+j;
5829 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
5837 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
5838 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
5839 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
5840 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
5841 * are not used here to avoid the build of big permutation array.
5843 * \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
5844 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5845 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
5846 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
5847 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
5848 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
5849 * \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
5850 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5852 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
5853 DataArrayInt *&szOfCellGrpOfSameType,
5854 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
5856 std::vector<const MEDCouplingUMesh *> ms2;
5857 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5860 (*it)->checkConnectivityFullyDefined();
5864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
5865 const DataArrayDouble *refCoo=ms2[0]->getCoords();
5866 int meshDim=ms2[0]->getMeshDimension();
5867 std::vector<const MEDCouplingUMesh *> m1ssm;
5868 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
5870 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
5871 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
5873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
5874 ret1->alloc(0,1); ret2->alloc(0,1);
5875 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
5877 if(meshDim!=(*it)->getMeshDimension())
5878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
5879 if(refCoo!=(*it)->getCoords())
5880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
5881 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
5882 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
5883 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
5884 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
5886 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
5887 m1ssmSingleAuto.push_back(singleCell);
5888 m1ssmSingle.push_back(singleCell);
5889 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
5892 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
5893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
5894 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
5895 for(std::size_t i=0;i<m1ssm.size();i++)
5896 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
5897 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
5898 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
5899 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
5904 * This method returns a newly created DataArrayInt instance.
5905 * This method retrieves cell ids in [begin,end) that have the type 'type'.
5907 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
5909 checkFullyDefined();
5910 const int *conn=_nodal_connec->getConstPointer();
5911 const int *connIndex=_nodal_connec_index->getConstPointer();
5912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5913 for(const int *w=begin;w!=end;w++)
5914 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
5915 ret->pushBackSilent(*w);
5920 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
5921 * are in [0:getNumberOfCells())
5923 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
5925 checkFullyDefined();
5926 const int *conn=_nodal_connec->getConstPointer();
5927 const int *connI=_nodal_connec_index->getConstPointer();
5928 int nbOfCells=getNumberOfCells();
5929 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
5930 int *tmp=new int[nbOfCells];
5931 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5934 for(const int *i=connI;i!=connI+nbOfCells;i++)
5935 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5936 tmp[std::distance(connI,i)]=j++;
5938 DataArrayInt *ret=DataArrayInt::New();
5939 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
5940 ret->copyStringInfoFrom(*da);
5941 int *retPtr=ret->getPointer();
5942 const int *daPtr=da->getConstPointer();
5943 int nbOfElems=da->getNbOfElems();
5944 for(int k=0;k<nbOfElems;k++)
5945 retPtr[k]=tmp[daPtr[k]];
5951 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
5952 * This method \b works \b for mesh sorted by type.
5953 * cells whose ids is in 'idsPerGeoType' array.
5954 * This method conserves coords and name of mesh.
5956 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
5958 std::vector<int> code=getDistributionOfTypes();
5959 std::size_t nOfTypesInThis=code.size()/3;
5960 int sz=0,szOfType=0;
5961 for(std::size_t i=0;i<nOfTypesInThis;i++)
5966 szOfType=code[3*i+1];
5968 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
5969 if(*work<0 || *work>=szOfType)
5971 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
5972 oss << ". It should be in [0," << szOfType << ") !";
5973 throw INTERP_KERNEL::Exception(oss.str().c_str());
5975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
5976 int *idsPtr=idsTokeep->getPointer();
5978 for(std::size_t i=0;i<nOfTypesInThis;i++)
5981 for(int j=0;j<code[3*i+1];j++)
5984 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
5985 offset+=code[3*i+1];
5987 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
5988 ret->copyTinyInfoFrom(this);
5993 * This method returns a vector of size 'this->getNumberOfCells()'.
5994 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
5996 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
5998 int ncell=getNumberOfCells();
5999 std::vector<bool> ret(ncell);
6000 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6001 const int *c=getNodalConnectivity()->getConstPointer();
6002 for(int i=0;i<ncell;i++)
6004 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6005 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6006 ret[i]=cm.isQuadratic();
6012 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
6014 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6016 if(other->getType()!=UNSTRUCTURED)
6017 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6018 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6019 return MergeUMeshes(this,otherC);
6023 * Returns an array with this->getNumberOfCells() tuples and this->getSpaceDimension() dimension.
6024 * The false barycenter is computed that is to say barycenter of a cell is computed using average on each
6025 * components of coordinates of the cell.
6027 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6029 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6030 int spaceDim=getSpaceDimension();
6031 int nbOfCells=getNumberOfCells();
6032 ret->alloc(nbOfCells,spaceDim);
6033 ret->copyStringInfoFrom(*getCoords());
6034 double *ptToFill=ret->getPointer();
6035 const int *nodal=_nodal_connec->getConstPointer();
6036 const int *nodalI=_nodal_connec_index->getConstPointer();
6037 const double *coor=_coords->getConstPointer();
6038 for(int i=0;i<nbOfCells;i++)
6040 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6041 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6048 * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
6049 * 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().
6050 * No check of that will be done !
6052 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6054 DataArrayDouble *ret=DataArrayDouble::New();
6055 int spaceDim=getSpaceDimension();
6056 int nbOfTuple=(int)std::distance(begin,end);
6057 ret->alloc(nbOfTuple,spaceDim);
6058 double *ptToFill=ret->getPointer();
6059 double *tmp=new double[spaceDim];
6060 const int *nodal=_nodal_connec->getConstPointer();
6061 const int *nodalI=_nodal_connec_index->getConstPointer();
6062 const double *coor=_coords->getConstPointer();
6063 for(const int *w=begin;w!=end;w++)
6065 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6066 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6074 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6077 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
6080 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6081 da->checkAllocated();
6082 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
6084 int nbOfTuples=da->getNumberOfTuples();
6085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6086 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6087 c->alloc(2*nbOfTuples,1);
6088 cI->alloc(nbOfTuples+1,1);
6089 int *cp=c->getPointer();
6090 int *cip=cI->getPointer();
6092 for(int i=0;i<nbOfTuples;i++)
6094 *cp++=INTERP_KERNEL::NORM_POINT1;
6098 ret->setConnectivity(c,cI,true);
6103 * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
6104 * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
6106 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6108 std::vector<const MEDCouplingUMesh *> tmp(2);
6109 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6110 return MergeUMeshes(tmp);
6114 * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
6115 * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
6116 * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
6117 * cells in meshes in 'a' (in the same order too).
6119 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6121 std::size_t sz=a.size();
6123 return MergeUMeshesLL(a);
6124 for(std::size_t ii=0;ii<sz;ii++)
6127 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6128 throw INTERP_KERNEL::Exception(oss.str().c_str());
6130 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
6131 std::vector< const MEDCouplingUMesh * > aa(sz);
6133 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6135 const MEDCouplingUMesh *cur=a[i];
6136 const DataArrayDouble *coo=cur->getCoords();
6138 spaceDim=coo->getNumberOfComponents();
6141 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6142 for(std::size_t i=0;i<sz;i++)
6144 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6147 return MergeUMeshesLL(aa);
6152 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
6156 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
6157 int meshDim=(*it)->getMeshDimension();
6158 int nbOfCells=(*it)->getNumberOfCells();
6159 int meshLgth=(*it++)->getMeshLength();
6160 for(;it!=a.end();it++)
6162 if(meshDim!=(*it)->getMeshDimension())
6163 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
6164 nbOfCells+=(*it)->getNumberOfCells();
6165 meshLgth+=(*it)->getMeshLength();
6167 std::vector<const MEDCouplingPointSet *> aps(a.size());
6168 std::copy(a.begin(),a.end(),aps.begin());
6169 DataArrayDouble *pts=MergeNodesArray(aps);
6170 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
6171 ret->setCoords(pts);
6173 DataArrayInt *c=DataArrayInt::New();
6174 c->alloc(meshLgth,1);
6175 int *cPtr=c->getPointer();
6176 DataArrayInt *cI=DataArrayInt::New();
6177 cI->alloc(nbOfCells+1,1);
6178 int *cIPtr=cI->getPointer();
6182 for(it=a.begin();it!=a.end();it++)
6184 int curNbOfCell=(*it)->getNumberOfCells();
6185 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
6186 const int *curC=(*it)->_nodal_connec->getConstPointer();
6187 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
6188 for(int j=0;j<curNbOfCell;j++)
6190 const int *src=curC+curCI[j];
6192 for(;src!=curC+curCI[j+1];src++,cPtr++)
6200 offset+=curCI[curNbOfCell];
6201 offset2+=(*it)->getNumberOfNodes();
6204 ret->setConnectivity(c,cI,true);
6213 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6214 * 'meshes' must be a non empty vector.
6216 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6218 std::vector<const MEDCouplingUMesh *> tmp(2);
6219 tmp[0]=mesh1; tmp[1]=mesh2;
6220 return MergeUMeshesOnSameCoords(tmp);
6224 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6225 * 'meshes' must be a non empty vector.
6227 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6230 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6231 for(std::size_t ii=0;ii<meshes.size();ii++)
6234 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6235 throw INTERP_KERNEL::Exception(oss.str().c_str());
6237 const DataArrayDouble *coords=meshes.front()->getCoords();
6238 int meshDim=meshes.front()->getMeshDimension();
6239 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6241 int meshIndexLgth=0;
6242 for(;iter!=meshes.end();iter++)
6244 if(coords!=(*iter)->getCoords())
6245 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6246 if(meshDim!=(*iter)->getMeshDimension())
6247 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6248 meshLgth+=(*iter)->getMeshLength();
6249 meshIndexLgth+=(*iter)->getNumberOfCells();
6251 DataArrayInt *nodal=DataArrayInt::New();
6252 nodal->alloc(meshLgth,1);
6253 int *nodalPtr=nodal->getPointer();
6254 DataArrayInt *nodalIndex=DataArrayInt::New();
6255 nodalIndex->alloc(meshIndexLgth+1,1);
6256 int *nodalIndexPtr=nodalIndex->getPointer();
6258 for(iter=meshes.begin();iter!=meshes.end();iter++)
6260 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
6261 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
6262 int nbOfCells=(*iter)->getNumberOfCells();
6263 int meshLgth2=(*iter)->getMeshLength();
6264 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6265 if(iter!=meshes.begin())
6266 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6268 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6271 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6272 ret->setName("merge");
6273 ret->setMeshDimension(meshDim);
6274 ret->setConnectivity(nodal,nodalIndex,true);
6275 ret->setCoords(coords);
6276 nodalIndex->decrRef();
6282 * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
6283 * 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)
6285 * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
6286 * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
6287 * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
6288 * The arrays contained in 'corr' parameter are returned with refcounter set to one.
6289 * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
6290 * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
6291 * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
6293 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6295 //All checks are delegated to MergeUMeshesOnSameCoords
6296 MEDCouplingUMesh *ret=MergeUMeshesOnSameCoords(meshes);
6297 DataArrayInt *o2n=ret->zipConnectivityTraducer(compType);
6298 corr.resize(meshes.size());
6299 std::size_t nbOfMeshes=meshes.size();
6301 const int *o2nPtr=o2n->getConstPointer();
6302 for(std::size_t i=0;i<nbOfMeshes;i++)
6304 DataArrayInt *tmp=DataArrayInt::New();
6305 int curNbOfCells=meshes[i]->getNumberOfCells();
6306 tmp->alloc(curNbOfCells,1);
6307 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6308 offset+=curNbOfCells;
6309 tmp->setName(meshes[i]->getName());
6317 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6318 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6319 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6320 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6322 * This method performs nothing if size of \b meshes is in [0,1].
6323 * This method is particulary usefull in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6324 * coordinates DataArrayDouble instance.
6326 * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6328 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6330 std::size_t sz=meshes.size();
6333 std::vector< const DataArrayDouble * > coords(meshes.size());
6334 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6335 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6339 (*it)->checkConnectivityFullyDefined();
6340 const DataArrayDouble *coo=(*it)->getCoords();
6345 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6346 oss << " has no coordinate array defined !";
6347 throw INTERP_KERNEL::Exception(oss.str().c_str());
6352 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6353 oss << " is null !";
6354 throw INTERP_KERNEL::Exception(oss.str().c_str());
6357 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6358 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6359 int offset=(*it)->getNumberOfNodes();
6360 (*it++)->setCoords(res);
6361 for(;it!=meshes.end();it++)
6363 int oldNumberOfNodes=(*it)->getNumberOfNodes();
6364 (*it)->setCoords(res);
6365 (*it)->shiftNodeNumbersInConn(offset);
6366 offset+=oldNumberOfNodes;
6371 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6372 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6373 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6374 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6375 * 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.
6377 * This method performs nothing if size of \b meshes is empty.
6378 * This method is particulary usefull in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6379 * coordinates DataArrayDouble instance.
6381 * \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.
6382 * \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.
6384 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6388 std::set<const DataArrayDouble *> s;
6389 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6392 s.insert((*it)->getCoords());
6395 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 !";
6396 throw INTERP_KERNEL::Exception(oss.str().c_str());
6401 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 !";
6402 throw INTERP_KERNEL::Exception(oss.str().c_str());
6404 const DataArrayDouble *coo=*(s.begin());
6408 DataArrayInt *comm,*commI;
6409 coo->findCommonTuples(eps,-1,comm,commI);
6410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6411 int oldNbOfNodes=coo->getNumberOfTuples();
6413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6414 if(oldNbOfNodes==newNbOfNodes)
6416 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6417 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6419 (*it)->renumberNodesInConn(o2n->getConstPointer());
6420 (*it)->setCoords(newCoords);
6425 * 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.
6426 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6427 * @param isQuad specifies the policy of connectivity.
6428 * @ret in/out parameter in which the result will be append
6430 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6432 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6433 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6434 ret.push_back(cm.getExtrudedType());
6435 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6438 case INTERP_KERNEL::NORM_POINT1:
6440 ret.push_back(connBg[1]);
6441 ret.push_back(connBg[1]+nbOfNodesPerLev);
6444 case INTERP_KERNEL::NORM_SEG2:
6446 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6447 ret.insert(ret.end(),conn,conn+4);
6450 case INTERP_KERNEL::NORM_SEG3:
6452 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6453 ret.insert(ret.end(),conn,conn+8);
6456 case INTERP_KERNEL::NORM_QUAD4:
6458 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6459 ret.insert(ret.end(),conn,conn+8);
6462 case INTERP_KERNEL::NORM_TRI3:
6464 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6465 ret.insert(ret.end(),conn,conn+6);
6468 case INTERP_KERNEL::NORM_TRI6:
6470 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,
6471 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6472 ret.insert(ret.end(),conn,conn+15);
6475 case INTERP_KERNEL::NORM_QUAD8:
6478 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6479 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6480 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6482 ret.insert(ret.end(),conn,conn+20);
6485 case INTERP_KERNEL::NORM_POLYGON:
6487 std::back_insert_iterator< std::vector<int> > ii(ret);
6488 std::copy(connBg+1,connEnd,ii);
6490 std::reverse_iterator<const int *> rConnBg(connEnd);
6491 std::reverse_iterator<const int *> rConnEnd(connBg+1);
6492 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6493 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6494 for(std::size_t i=0;i<nbOfRadFaces;i++)
6497 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6498 std::copy(conn,conn+4,ii);
6503 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6508 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6510 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6512 double v[3]={0.,0.,0.};
6513 std::size_t sz=std::distance(begin,end);
6516 for(std::size_t i=0;i<sz;i++)
6518 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];
6519 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6520 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6522 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6526 * The polyhedron is specfied by its connectivity nodes in [begin,end).
6528 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6530 std::vector<std::pair<int,int> > edges;
6531 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6532 const int *bgFace=begin;
6533 for(std::size_t i=0;i<nbOfFaces;i++)
6535 const int *endFace=std::find(bgFace+1,end,-1);
6536 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6537 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6539 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6540 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6542 edges.push_back(p1);
6546 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6550 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
6552 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6554 double vec0[3],vec1[3];
6555 std::size_t sz=std::distance(begin,end);
6557 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6558 int nbOfNodes=(int)sz/2;
6559 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6560 const double *pt0=coords+3*begin[0];
6561 const double *pt1=coords+3*begin[nbOfNodes];
6562 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6563 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6566 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6568 std::size_t sz=std::distance(begin,end);
6569 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6570 std::size_t nbOfNodes(sz/2);
6571 std::copy(begin,end,(int *)tmp);
6572 for(std::size_t j=1;j<nbOfNodes;j++)
6574 begin[j]=tmp[nbOfNodes-j];
6575 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6579 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6581 std::size_t sz=std::distance(begin,end);
6583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
6584 double vec0[3],vec1[3];
6585 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6586 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];
6587 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;
6590 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
6592 std::size_t sz=std::distance(begin,end);
6594 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
6596 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
6597 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
6598 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
6602 * 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)
6603 * 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
6606 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6607 * \param [in] coords the coordinates with nb of components exactly equal to 3
6608 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6609 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6610 * \param [out] res the result is put at the end of the vector without any alteration of the data.
6612 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
6614 int nbFaces=std::count(begin+1,end,-1)+1;
6615 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6616 double *vPtr=v->getPointer();
6617 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6618 double *pPtr=p->getPointer();
6619 const int *stFaceConn=begin+1;
6620 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6622 const int *endFaceConn=std::find(stFaceConn,end,-1);
6623 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
6624 stFaceConn=endFaceConn+1;
6626 pPtr=p->getPointer(); vPtr=v->getPointer();
6627 DataArrayInt *comm1=0,*commI1=0;
6628 v->findCommonTuples(eps,-1,comm1,commI1);
6629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6630 const int *comm1Ptr=comm1->getConstPointer();
6631 const int *commI1Ptr=commI1->getConstPointer();
6632 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6633 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
6635 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
6636 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
6637 mm->finishInsertingCells();
6639 for(int i=0;i<nbOfGrps1;i++)
6641 int vecId=comm1Ptr[commI1Ptr[i]];
6642 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6643 DataArrayInt *comm2=0,*commI2=0;
6644 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
6645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
6646 const int *comm2Ptr=comm2->getConstPointer();
6647 const int *commI2Ptr=commI2->getConstPointer();
6648 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
6649 for(int j=0;j<nbOfGrps2;j++)
6651 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
6653 res->insertAtTheEnd(begin,end);
6654 res->pushBackSilent(-1);
6658 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
6659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
6660 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6661 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
6662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
6663 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
6664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
6665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
6666 const int *idsNodePtr=idsNode->getConstPointer();
6667 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];
6668 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
6669 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
6670 if(std::abs(norm)>eps)
6672 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
6673 mm3->rotate(center,vec,angle);
6675 mm3->changeSpaceDimension(2);
6676 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
6677 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
6678 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
6679 int nbOfCells=mm4->getNumberOfCells();
6680 for(int k=0;k<nbOfCells;k++)
6683 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
6684 res->pushBackSilent(idsNodePtr[*work]);
6685 res->pushBackSilent(-1);
6690 res->popBackSilent();
6694 * 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
6695 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
6697 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
6698 * \param [in] coords coordinates expected to have 3 components.
6699 * \param [in] begin start of the nodal connectivity of the face.
6700 * \param [in] end end of the nodal connectivity (excluded) of the face.
6701 * \param [out] v the normalized vector of size 3
6702 * \param [out] p the pos of plane
6704 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
6706 std::size_t nbPoints=std::distance(begin,end);
6708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
6711 bool refFound=false;
6712 for(;j<nbPoints-1 && !refFound;j++)
6714 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
6715 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
6716 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
6717 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
6721 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
6724 for(std::size_t i=j;i<nbPoints-1;i++)
6727 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
6728 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
6729 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
6730 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
6733 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
6734 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];
6735 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
6738 v[0]/=norm; v[1]/=norm; v[2]/=norm;
6739 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
6743 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
6747 * This method tries to obtain a well oriented polyhedron.
6748 * If the algorithm fails, an exception will be thrown.
6750 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
6752 std::list< std::pair<int,int> > edgesOK,edgesFinished;
6753 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6754 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
6756 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
6757 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6758 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
6760 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
6763 std::size_t smthChanged=0;
6764 for(std::size_t i=0;i<nbOfFaces;i++)
6766 endFace=std::find(bgFace+1,end,-1);
6767 nbOfEdgesInFace=std::distance(bgFace,endFace);
6771 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6773 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6774 std::pair<int,int> p2(p1.second,p1.first);
6775 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
6776 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
6777 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
6782 std::reverse(bgFace+1,endFace);
6783 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6785 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6786 std::pair<int,int> p2(p1.second,p1.first);
6787 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
6788 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
6789 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
6790 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
6791 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
6792 if(it!=edgesOK.end())
6795 edgesFinished.push_back(p1);
6798 edgesOK.push_back(p1);
6805 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
6807 if(!edgesOK.empty())
6808 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
6809 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
6810 {//not lucky ! The first face was not correctly oriented : reorient all faces...
6812 for(std::size_t i=0;i<nbOfFaces;i++)
6814 endFace=std::find(bgFace+1,end,-1);
6815 std::reverse(bgFace+1,endFace);
6822 * This method makes the assumption spacedimension == meshdimension == 2.
6823 * This method works only for linear cells.
6825 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
6827 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
6829 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
6830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
6831 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
6833 int nbOfNodesExpected=m->getNumberOfNodes();
6834 if(m->getNumberOfCells()!=nbOfNodesExpected)
6835 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
6836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
6837 const int *n2oPtr=n2o->getConstPointer();
6838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
6839 m->getReverseNodalConnectivity(revNodal,revNodalI);
6840 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
6841 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
6842 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
6843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
6844 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
6845 if(nbOfNodesExpected<1)
6848 int prevNode=nodalPtr[nodalIPtr[0]+1];
6849 *work++=n2oPtr[prevNode];
6850 for(int i=1;i<nbOfNodesExpected;i++)
6852 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
6854 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
6855 conn.erase(prevNode);
6858 int curNode=*(conn.begin());
6859 *work++=n2oPtr[curNode];
6860 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
6861 shar.erase(prevCell);
6864 prevCell=*(shar.begin());
6868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
6871 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
6874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
6880 * This method makes the assumption spacedimension == meshdimension == 3.
6881 * This method works only for linear cells.
6883 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
6885 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
6887 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
6889 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6890 const int *conn=m->getNodalConnectivity()->getConstPointer();
6891 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
6892 int nbOfCells=m->getNumberOfCells();
6893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
6894 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
6897 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
6898 for(int i=1;i<nbOfCells;i++)
6901 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
6907 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
6908 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
6910 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
6914 for(int i=0;i<nbOfNodesInCell;i++)
6915 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
6916 else if(spaceDim==2)
6918 for(int i=0;i<nbOfNodesInCell;i++)
6920 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
6925 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
6928 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
6930 int nbOfCells=getNumberOfCells();
6932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
6933 static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,-1,23,-1,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,-1,-1,-1,25,42,-1,4};
6934 ofs << " <" << getVTKDataSetType() << ">\n";
6935 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
6936 ofs << " <PointData>\n" << pointData << std::endl;
6937 ofs << " </PointData>\n";
6938 ofs << " <CellData>\n" << cellData << std::endl;
6939 ofs << " </CellData>\n";
6940 ofs << " <Points>\n";
6941 if(getSpaceDimension()==3)
6942 _coords->writeVTK(ofs,8,"Points");
6945 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
6946 coo->writeVTK(ofs,8,"Points");
6948 ofs << " </Points>\n";
6949 ofs << " <Cells>\n";
6950 const int *cPtr=_nodal_connec->getConstPointer();
6951 const int *cIPtr=_nodal_connec_index->getConstPointer();
6952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
6953 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
6954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
6955 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
6956 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
6957 int szFaceOffsets=0,szConn=0;
6958 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
6961 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
6964 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
6965 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
6969 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
6970 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
6971 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
6972 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
6973 w4=std::copy(c.begin(),c.end(),w4);
6976 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
6977 types->writeVTK(ofs,8,"UInt8","types");
6978 offsets->writeVTK(ofs,8,"Int32","offsets");
6979 if(szFaceOffsets!=0)
6980 {//presence of Polyhedra
6981 connectivity->reAlloc(szConn);
6982 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
6983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
6984 w1=faces->getPointer();
6985 for(int i=0;i<nbOfCells;i++)
6986 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
6988 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
6990 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
6991 for(int j=0;j<nbFaces;j++)
6993 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
6994 *w1++=(int)std::distance(w6,w5);
6995 w1=std::copy(w6,w5,w1);
6999 faces->writeVTK(ofs,8,"Int32","faces");
7001 connectivity->writeVTK(ofs,8,"Int32","connectivity");
7002 ofs << " </Cells>\n";
7003 ofs << " </Piece>\n";
7004 ofs << " </" << getVTKDataSetType() << ">\n";
7007 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
7009 return std::string("UnstructuredGrid");
7014 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
7016 m1->checkFullyDefined();
7017 m2->checkFullyDefined();
7018 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
7019 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
7020 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
7021 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
7022 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
7023 std::vector<double> addCoo,addCoordsQuadratic;
7024 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
7025 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
7026 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
7027 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
7028 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
7029 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
7030 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
7031 std::vector< std::vector<int> > intersectEdge2;
7032 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
7033 subDiv2.clear(); dd5=0; dd6=0;
7034 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
7035 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
7036 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
7037 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
7039 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
7040 addCooDa->alloc((int)(addCoo.size())/2,2);
7041 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
7042 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
7043 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
7044 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
7045 std::vector<const DataArrayDouble *> coordss(4);
7046 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
7047 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
7048 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
7049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
7050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
7051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
7052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
7053 ret->setConnectivity(conn,connI,true);
7054 ret->setCoords(coo);
7055 cellNb1=c1.retn(); cellNb2=c2.retn();
7061 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
7062 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
7063 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
7064 const std::vector<double>& addCoords,
7065 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
7067 static const int SPACEDIM=2;
7068 std::vector<double> bbox1,bbox2;
7069 const double *coo1=m1->getCoords()->getConstPointer();
7070 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
7071 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
7072 int offset1=m1->getNumberOfNodes();
7073 const double *coo2=m2->getCoords()->getConstPointer();
7074 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
7075 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
7076 int offset2=offset1+m2->getNumberOfNodes();
7077 int offset3=offset2+((int)addCoords.size())/2;
7078 m1->getBoundingBoxForBBTree(bbox1);
7079 m2->getBoundingBoxForBBTree(bbox2);
7080 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
7081 int ncell1=m1->getNumberOfCells();
7083 for(int i=0;i<ncell1;i++)
7085 std::vector<int> candidates2;
7086 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7087 std::map<INTERP_KERNEL::Node *,int> mapp;
7088 std::map<int,INTERP_KERNEL::Node *> mappRev;
7089 INTERP_KERNEL::QuadraticPolygon pol1;
7090 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
7091 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7092 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
7093 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
7094 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
7096 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
7097 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
7098 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
7099 for(it1.first();!it1.finished();it1.next())
7100 edges1.insert(it1.current()->getPtr());
7102 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
7103 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
7105 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7107 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
7108 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
7109 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
7110 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
7111 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
7114 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7116 pol1.initLocationsWithOther(pol2s[ii]);
7117 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
7118 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
7119 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7125 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7127 catch(INTERP_KERNEL::Exception& e)
7129 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();
7130 throw INTERP_KERNEL::Exception(oss.str().c_str());
7133 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
7134 (*it).second->decrRef();
7139 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
7142 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
7143 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
7144 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
7145 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
7146 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
7148 static const int SPACEDIM=2;
7149 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
7150 desc2=DataArrayInt::New();
7151 descIndx2=DataArrayInt::New();
7152 revDesc2=DataArrayInt::New();
7153 revDescIndx2=DataArrayInt::New();
7154 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
7155 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
7156 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
7157 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
7158 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
7159 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
7160 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
7161 std::vector<double> bbox1,bbox2;
7162 m1Desc->getBoundingBoxForBBTree(bbox1);
7163 m2Desc->getBoundingBoxForBBTree(bbox2);
7164 int ncell1=m1Desc->getNumberOfCells();
7165 int ncell2=m2Desc->getNumberOfCells();
7166 intersectEdge1.resize(ncell1);
7167 colinear2.resize(ncell2);
7168 subDiv2.resize(ncell2);
7169 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
7170 std::vector<int> candidates1(1);
7171 int offset1=m1->getNumberOfNodes();
7172 int offset2=offset1+m2->getNumberOfNodes();
7173 for(int i=0;i<ncell1;i++)
7175 std::vector<int> candidates2;
7176 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7177 if(!candidates2.empty())
7179 std::map<INTERP_KERNEL::Node *,int> map1,map2;
7180 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
7182 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
7183 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
7188 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
7190 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
7191 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
7195 * This method performs the 2nd step of Partition of 2D mesh.
7196 * This method has 4 inputs :
7197 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
7198 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
7199 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
7200 * 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'
7201 * @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'
7202 * @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.
7203 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
7205 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)
7207 int offset1=m1->getNumberOfNodes();
7208 int ncell=m2->getNumberOfCells();
7209 const int *c=m2->getNodalConnectivity()->getConstPointer();
7210 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
7211 const double *coo=m2->getCoords()->getConstPointer();
7212 const double *cooBis=m1->getCoords()->getConstPointer();
7213 int offset2=offset1+m2->getNumberOfNodes();
7214 intersectEdge.resize(ncell);
7215 for(int i=0;i<ncell;i++,cI++)
7217 const std::vector<int>& divs=subDiv[i];
7218 int nnode=cI[1]-cI[0]-1;
7219 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
7220 std::map<INTERP_KERNEL::Node *, int> mapp22;
7221 for(int j=0;j<nnode;j++)
7223 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
7224 int nnid=c[(*cI)+j+1];
7225 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
7226 mapp22[nn]=nnid+offset1;
7228 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
7229 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
7230 ((*it).second.first)->decrRef();
7231 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
7232 std::map<INTERP_KERNEL::Node *,int> mapp3;
7233 for(std::size_t j=0;j<divs.size();j++)
7236 INTERP_KERNEL::Node *tmp=0;
7238 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
7240 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
7242 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
7246 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
7247 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
7254 * 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).
7255 * 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
7256 * with a plane. The result will be put in 'cut3DSuf' out parameter.
7257 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
7258 * @param nodesOnPlane, returns all the nodes that are on the plane.
7259 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
7260 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
7261 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
7262 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
7263 * @param desc is the descending connectivity 3DSurf->3DCurve
7264 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
7265 * @param cut3DSuf input/output param.
7267 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
7268 const int *nodal3DCurve, const int *nodalIndx3DCurve,
7269 const int *desc, const int *descIndx,
7270 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
7272 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
7273 int nbOf3DSurfCell=(int)cut3DSurf.size();
7274 for(int i=0;i<nbOf3DSurfCell;i++)
7276 std::vector<int> res;
7277 int offset=descIndx[i];
7278 int nbOfSeg=descIndx[i+1]-offset;
7279 for(int j=0;j<nbOfSeg;j++)
7281 int edgeId=desc[offset+j];
7282 int status=cut3DCurve[edgeId];
7286 res.push_back(status);
7289 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
7290 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
7298 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7304 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
7305 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
7308 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7312 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
7317 {// case when plane is on a multi colinear edge of a polyhedron
7318 if((int)res.size()==2*nbOfSeg)
7320 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
7323 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
7330 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
7331 * 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).
7332 * 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
7333 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
7334 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
7335 * @param desc is the descending connectivity 3D->3DSurf
7336 * @param descIndx is the descending connectivity index 3D->3DSurf
7338 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
7339 const int *desc, const int *descIndx,
7340 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
7342 checkFullyDefined();
7343 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
7345 const int *nodal3D=_nodal_connec->getConstPointer();
7346 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
7347 int nbOfCells=getNumberOfCells();
7348 for(int i=0;i<nbOfCells;i++)
7350 std::map<int, std::set<int> > m;
7351 int offset=descIndx[i];
7352 int nbOfFaces=descIndx[i+1]-offset;
7355 for(int j=0;j<nbOfFaces;j++)
7357 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
7358 if(p.first!=-1 && p.second!=-1)
7362 start=p.first; end=p.second;
7363 m[p.first].insert(p.second);
7364 m[p.second].insert(p.first);
7368 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
7369 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
7370 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7371 INTERP_KERNEL::NormalizedCellType cmsId;
7372 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
7373 start=tmp[0]; end=tmp[nbOfNodesSon-1];
7374 for(unsigned k=0;k<nbOfNodesSon;k++)
7376 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
7377 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
7384 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
7388 std::map<int, std::set<int> >::const_iterator it=m.find(start);
7389 const std::set<int>& s=(*it).second;
7390 std::set<int> s2; s2.insert(prev);
7392 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
7395 int val=*s3.begin();
7396 conn.push_back(start);
7403 conn.push_back(end);
7406 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
7407 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
7408 cellIds->pushBackSilent(i);
7414 * 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
7415 * 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
7416 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7417 * 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
7418 * 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.
7420 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7422 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
7424 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7427 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7428 if(cm.getDimension()==2)
7430 const int *node=nodalConnBg+1;
7431 int startNode=*node++;
7432 double refX=coords[2*startNode];
7433 for(;node!=nodalConnEnd;node++)
7435 if(coords[2*(*node)]<refX)
7438 refX=coords[2*startNode];
7441 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7445 double angle0=-M_PI/2;
7451 while(nextNode!=startNode)
7455 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7457 if(*node!=tmpOut.back() && *node!=prevNode)
7459 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7460 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7465 res=angle0-angleM+2.*M_PI;
7474 if(nextNode!=startNode)
7476 angle0=angleNext-M_PI;
7479 prevNode=tmpOut.back();
7480 tmpOut.push_back(nextNode);
7483 std::vector<int> tmp3(2*(sz-1));
7484 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7485 std::copy(nodalConnBg+1,nodalConnEnd,it);
7486 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7488 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7491 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7493 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7498 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7499 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7504 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7507 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7511 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7512 * 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.
7514 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7515 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7516 * \param [in,out] arr array in which the remove operation will be done.
7517 * \param [in,out] arrIndx array in the remove operation will modify
7518 * \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])
7519 * \return true if \b arr and \b arrIndx have been modified, false if not.
7521 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7523 if(!arrIndx || !arr)
7524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7525 if(offsetForRemoval<0)
7526 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7527 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7528 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7529 int *arrIPtr=arrIndx->getPointer();
7532 const int *arrPtr=arr->getConstPointer();
7533 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7534 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7536 if(*arrIPtr-previousArrI>offsetForRemoval)
7538 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7540 if(s.find(*work)==s.end())
7541 arrOut.push_back(*work);
7544 previousArrI=*arrIPtr;
7545 *arrIPtr=(int)arrOut.size();
7547 if(arr->getNumberOfTuples()==(int)arrOut.size())
7549 arr->alloc((int)arrOut.size(),1);
7550 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7555 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7556 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7557 * The selection of extraction is done standardly in new2old format.
7558 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
7560 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7561 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7562 * \param [in] arrIn arr origin array from which the extraction will be done.
7563 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7564 * \param [out] arrOut the resulting array
7565 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7567 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7568 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7570 if(!arrIn || !arrIndxIn)
7571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7572 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7573 const int *arrInPtr=arrIn->getConstPointer();
7574 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7575 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7576 int maxSizeOfArr=arrIn->getNumberOfTuples();
7577 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7578 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7579 arrIo->alloc((int)(sz+1),1);
7580 const int *idsIt=idsOfSelectBg;
7581 int *work=arrIo->getPointer();
7584 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7586 if(*idsIt>=0 && *idsIt<nbOfGrps)
7587 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7590 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7591 throw INTERP_KERNEL::Exception(oss.str().c_str());
7597 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7598 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7599 throw INTERP_KERNEL::Exception(oss.str().c_str());
7602 arro->alloc(lgth,1);
7603 work=arro->getPointer();
7604 idsIt=idsOfSelectBg;
7605 for(std::size_t i=0;i<sz;i++,idsIt++)
7607 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7608 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7611 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7612 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7613 throw INTERP_KERNEL::Exception(oss.str().c_str());
7617 arrIndexOut=arrIo.retn();
7621 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7622 * 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
7623 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7624 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7626 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7627 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7628 * \param [in] arrIn arr origin array from which the extraction will be done.
7629 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7630 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7631 * \param [in] srcArrIndex index array of \b srcArr
7632 * \param [out] arrOut the resulting array
7633 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7635 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7637 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7638 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7639 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7641 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7642 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7645 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7646 std::vector<bool> v(nbOfTuples,true);
7648 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7649 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7650 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7652 if(*it>=0 && *it<nbOfTuples)
7655 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7659 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7660 throw INTERP_KERNEL::Exception(oss.str().c_str());
7663 srcArrIndexPtr=srcArrIndex->getConstPointer();
7664 arrIo->alloc(nbOfTuples+1,1);
7665 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7666 const int *arrInPtr=arrIn->getConstPointer();
7667 const int *srcArrPtr=srcArr->getConstPointer();
7668 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7669 int *arroPtr=arro->getPointer();
7670 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7674 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7675 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7679 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7680 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7681 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7685 arrIndexOut=arrIo.retn();
7689 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7690 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7692 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7693 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7694 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7695 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7696 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7697 * \param [in] srcArrIndex index array of \b srcArr
7699 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7701 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7702 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7704 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7706 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7707 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7708 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7709 int *arrInOutPtr=arrInOut->getPointer();
7710 const int *srcArrPtr=srcArr->getConstPointer();
7711 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7713 if(*it>=0 && *it<nbOfTuples)
7715 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7716 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7719 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] !";
7720 throw INTERP_KERNEL::Exception(oss.str().c_str());
7725 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7726 throw INTERP_KERNEL::Exception(oss.str().c_str());
7732 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7733 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7734 * 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]].
7735 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7736 * A negative value in \b arrIn means that it is ignored.
7737 * This method is usefull to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
7739 * \param [in] arrIn arr origin array from which the extraction will be done.
7740 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7741 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7742 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
7744 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
7746 int seed=0,nbOfDepthPeelingPerformed=0;
7747 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
7751 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7752 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7753 * 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]].
7754 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7755 * A negative value in \b arrIn means that it is ignored.
7756 * This method is usefull to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
7757 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
7758 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
7759 * \param [in] arrIn arr origin array from which the extraction will be done.
7760 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7761 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
7762 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
7763 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7764 * \sa MEDCouplingUMesh::partitionBySpreadZone
7766 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
7768 nbOfDepthPeelingPerformed=0;
7770 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
7771 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7774 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
7778 std::vector<bool> fetched(nbOfTuples,false);
7779 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
7782 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)
7784 nbOfDepthPeelingPerformed=0;
7785 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
7786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
7787 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7788 std::vector<bool> fetched2(nbOfTuples,false);
7790 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
7792 if(*seedElt>=0 && *seedElt<nbOfTuples)
7793 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
7795 { 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()); }
7797 const int *arrInPtr=arrIn->getConstPointer();
7798 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7799 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
7800 std::vector<int> idsToFetch1(seedBg,seedEnd);
7801 std::vector<int> idsToFetch2;
7802 std::vector<int> *idsToFetch=&idsToFetch1;
7803 std::vector<int> *idsToFetchOther=&idsToFetch2;
7804 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
7806 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
7807 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
7809 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
7810 std::swap(idsToFetch,idsToFetchOther);
7811 idsToFetchOther->clear();
7812 nbOfDepthPeelingPerformed++;
7814 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
7816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
7817 int *retPtr=ret->getPointer();
7818 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
7825 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7826 * 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
7827 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7828 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7830 * \param [in] start begin of set of ids of the input extraction (included)
7831 * \param [in] end end of set of ids of the input extraction (excluded)
7832 * \param [in] step step of the set of ids in range mode.
7833 * \param [in] arrIn arr origin array from which the extraction will be done.
7834 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7835 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7836 * \param [in] srcArrIndex index array of \b srcArr
7837 * \param [out] arrOut the resulting array
7838 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7840 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
7842 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7843 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7844 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7846 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7847 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
7848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7850 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7852 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7853 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7854 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
7856 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7858 if(it>=0 && it<nbOfTuples)
7859 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7862 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7863 throw INTERP_KERNEL::Exception(oss.str().c_str());
7866 srcArrIndexPtr=srcArrIndex->getConstPointer();
7867 arrIo->alloc(nbOfTuples+1,1);
7868 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7869 const int *arrInPtr=arrIn->getConstPointer();
7870 const int *srcArrPtr=srcArr->getConstPointer();
7871 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7872 int *arroPtr=arro->getPointer();
7873 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7875 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
7878 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7879 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7883 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7884 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7888 arrIndexOut=arrIo.retn();
7892 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7893 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7895 * \param [in] start begin of set of ids of the input extraction (included)
7896 * \param [in] end end of set of ids of the input extraction (excluded)
7897 * \param [in] step step of the set of ids in range mode.
7898 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7899 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7900 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7901 * \param [in] srcArrIndex index array of \b srcArr
7903 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7905 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7906 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7908 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
7910 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7911 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7912 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7913 int *arrInOutPtr=arrInOut->getPointer();
7914 const int *srcArrPtr=srcArr->getConstPointer();
7915 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
7917 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7919 if(it>=0 && it<nbOfTuples)
7921 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
7922 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
7925 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7926 throw INTERP_KERNEL::Exception(oss.str().c_str());
7931 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7932 throw INTERP_KERNEL::Exception(oss.str().c_str());
7938 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
7939 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
7940 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
7941 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
7942 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
7944 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
7946 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
7948 checkFullyDefined();
7949 int mdim=getMeshDimension();
7950 int spaceDim=getSpaceDimension();
7952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
7953 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
7954 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
7955 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
7956 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
7957 ret->setCoords(getCoords());
7958 ret->allocateCells((int)partition.size());
7960 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
7962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
7963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
7967 cell=tmp->buildUnionOf2DMesh();
7970 cell=tmp->buildUnionOf3DMesh();
7973 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
7976 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
7979 ret->finishInsertingCells();
7984 * This method partitions \b this into contiguous zone.
7985 * This method only needs a well defined connectivity. Coordinates are not considered here.
7986 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
7988 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
7991 int nbOfCellsCur=getNumberOfCells();
7992 std::vector<DataArrayInt *> ret;
7995 DataArrayInt *neigh=0,*neighI=0;
7996 computeNeighborsOfCells(neigh,neighI);
7997 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
7998 std::vector<bool> fetchedCells(nbOfCellsCur,false);
7999 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8001 while(seed<nbOfCellsCur)
8003 int nbOfPeelPerformed=0;
8004 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
8005 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8007 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8008 ret.push_back((*it).retn());
8012 int nbOfCellsCur=getNumberOfCells();
8013 DataArrayInt *neigh=0,*neighI=0;
8014 computeNeighborsOfCells(neigh,neighI);
8015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
8017 std::vector<DataArrayInt *> ret;
8018 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8019 while(nbOfCellsCur>0)
8021 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
8022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
8023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
8024 ret2.push_back(tmp2); ret.push_back(tmp2);
8025 nbOfCellsCur=tmp3->getNumberOfTuples();
8028 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
8029 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
8032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
8033 neighAuto->transformWithIndArr(renum->begin(),renum->end());
8036 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
8043 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8044 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8046 * \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.
8047 * \return a newly allocated DataArrayInt to be managed by the caller.
8048 * \throw In case of \a code has not the right format (typically of size 3*n)
8050 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
8052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
8053 std::size_t nb=code.size()/3;
8054 if(code.size()%3!=0)
8055 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8056 ret->alloc((int)nb,2);
8057 int *retPtr=ret->getPointer();
8058 for(std::size_t i=0;i<nb;i++,retPtr+=2)
8060 retPtr[0]=code[3*i+2];
8061 retPtr[1]=code[3*i+2]+code[3*i+1];
8066 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8067 _own_cell(true),_cell_id(-1),_nb_cell(0)
8072 _nb_cell=mesh->getNumberOfCells();
8076 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8084 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8085 _own_cell(false),_cell_id(bg-1),
8092 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8095 if(_cell_id<_nb_cell)
8104 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8110 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8112 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8115 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8121 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8129 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8135 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8140 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8145 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8147 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8150 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8155 _nb_cell=mesh->getNumberOfCells();
8159 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8166 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8168 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
8169 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
8170 if(_cell_id<_nb_cell)
8172 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8173 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
8174 int startId=_cell_id;
8175 _cell_id+=nbOfElems;
8176 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8182 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8186 _conn=mesh->getNodalConnectivity()->getPointer();
8187 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8191 void MEDCouplingUMeshCell::next()
8193 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8198 _conn_lgth=_conn_indx[1]-_conn_indx[0];
8201 std::string MEDCouplingUMeshCell::repr() const
8203 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8205 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8207 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8211 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8214 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8216 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8217 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8219 return INTERP_KERNEL::NORM_ERROR;
8222 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8225 if(_conn_lgth!=NOTICABLE_FIRST_VAL)