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 MEDCouplingAutoRefCountObjectPtr<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);
2008 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2009 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2010 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2012 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2014 checkFullyDefined();
2015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2017 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2020 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2021 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2025 const int *revDescPtr=revDesc->getConstPointer();
2026 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2027 int nbOfCells=getNumberOfCells();
2028 std::vector<bool> ret1(nbOfCells,false);
2030 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2031 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2032 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2034 DataArrayInt *ret2=DataArrayInt::New();
2036 int *ret2Ptr=ret2->getPointer();
2038 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2041 ret2->setName("BoundaryCells");
2046 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2047 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2048 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2049 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2051 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2052 * This method method returns cells ids set s = s1 + s2 where :
2054 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2055 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2057 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2058 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2060 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2061 * \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
2062 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2064 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2066 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2067 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2068 checkConnectivityFullyDefined();
2069 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2070 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2071 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2073 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2074 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2076 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2077 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2078 DataArrayInt *idsOtherInConsti=0;
2079 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2080 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2084 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2085 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2086 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2088 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2089 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2091 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2092 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2093 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2094 neighThisPartAuto=0;
2095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2096 const int li[2]={0,1};
2097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2098 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2102 cellIdsRk0=s0arr.retn();
2103 cellIdsRk1=s_renum1.retn();
2107 * 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
2108 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2110 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2112 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2115 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2119 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2120 revDesc=0; desc=0; descIndx=0;
2121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2123 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2127 * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2128 * The returned nodes ids are those lying on the boundary of \b this.
2130 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2132 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2133 return skin->computeFetchedNodeIds();
2136 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2139 return const_cast<MEDCouplingUMesh *>(this);
2143 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2144 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2145 * This value is asked because often known by the caller of this method.
2146 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2148 * @param newNodeNumbers array specifying the new numbering in old2New convention.
2149 * @param newNbOfNodes the new number of nodes.
2151 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2153 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2154 renumberNodesInConn(newNodeNumbers);
2158 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2159 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2160 * This value is asked because often known by the caller of this method.
2161 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2162 * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2164 * @param newNodeNumbers array specifying the new numbering.
2165 * @param newNbOfNodes the new number of nodes.
2168 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2170 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2171 renumberNodesInConn(newNodeNumbers);
2175 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2176 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2177 * 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.
2178 * 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.
2179 * 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.
2181 * \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
2182 * parameter is altered during the call.
2183 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2184 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2185 * \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.
2187 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2189 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2190 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2192 checkFullyDefined();
2193 otherDimM1OnSameCoords.checkFullyDefined();
2194 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2196 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2198 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2199 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2202 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2203 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2207 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2209 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2211 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2212 DataArrayInt *idsTmp=0;
2213 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2216 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2217 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2218 DataArrayInt *tmp0=0,*tmp1=0;
2219 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2223 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2224 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2225 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2227 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2228 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2229 nodeIdsToDuplicate=s3.retn();
2233 * This method operates a modification of the connectivity and coords in \b this.
2234 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2235 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2236 * 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
2237 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2238 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2240 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2242 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2243 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2245 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2247 int nbOfNodes=getNumberOfNodes();
2248 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2249 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2253 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2254 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2255 * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2256 * @param [in] newNodeNumbers in old2New convention
2258 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2260 checkConnectivityFullyDefined();
2261 int *conn=getNodalConnectivity()->getPointer();
2262 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2263 int nbOfCells=getNumberOfCells();
2264 for(int i=0;i<nbOfCells;i++)
2265 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2267 int& node=conn[iconn];
2268 if(node>=0)//avoid polyhedron separator
2270 node=newNodeNumbersO2N[node];
2273 _nodal_connec->declareAsNew();
2278 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2279 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2280 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2282 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2284 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2286 checkConnectivityFullyDefined();
2287 int *conn=getNodalConnectivity()->getPointer();
2288 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2289 int nbOfCells=getNumberOfCells();
2290 for(int i=0;i<nbOfCells;i++)
2291 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2293 int& node=conn[iconn];
2294 if(node>=0)//avoid polyhedron separator
2299 _nodal_connec->declareAsNew();
2304 * This method operates a modification of the connectivity in \b this.
2305 * 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.
2306 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2307 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2308 * 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
2309 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2310 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2312 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2313 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2315 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2316 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2317 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2319 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2321 checkConnectivityFullyDefined();
2322 std::map<int,int> m;
2324 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2326 int *conn=getNodalConnectivity()->getPointer();
2327 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2328 int nbOfCells=getNumberOfCells();
2329 for(int i=0;i<nbOfCells;i++)
2330 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2332 int& node=conn[iconn];
2333 if(node>=0)//avoid polyhedron separator
2335 std::map<int,int>::iterator it=m.find(node);
2344 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2346 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2347 * After the call of this method the number of cells remains the same as before.
2349 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2350 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2351 * be strictly in [0;this->getNumberOfCells()).
2353 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2354 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2355 * should be contained in[0;this->getNumberOfCells()).
2357 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2359 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2361 checkConnectivityFullyDefined();
2362 int nbCells=getNumberOfCells();
2363 const int *array=old2NewBg;
2365 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2367 const int *conn=_nodal_connec->getConstPointer();
2368 const int *connI=_nodal_connec_index->getConstPointer();
2369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2370 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2371 newConn->copyStringInfoFrom(*_nodal_connec);
2372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2373 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2374 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2376 int *newC=newConn->getPointer();
2377 int *newCI=newConnI->getPointer();
2380 for(int i=0;i<nbCells;i++)
2382 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2383 int nbOfElts=connI[pos+1]-connI[pos];
2384 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2389 setConnectivity(newConn,newConnI);
2391 delete [] const_cast<int *>(array);
2395 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2396 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2397 * added in 'elems' parameter.
2399 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2401 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2402 if(getMeshDimension()==-1)
2404 elems->pushBackSilent(0);
2405 return elems.retn();
2407 int dim=getSpaceDimension();
2408 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2409 const int* conn = getNodalConnectivity()->getConstPointer();
2410 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2411 const double* coords = getCoords()->getConstPointer();
2412 int nbOfCells=getNumberOfCells();
2413 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2415 for (int i=0; i<dim; i++)
2417 elem_bb[i*2]=std::numeric_limits<double>::max();
2418 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2421 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2423 int node= conn[inode];
2424 if(node>=0)//avoid polyhedron separator
2426 for (int idim=0; idim<dim; idim++)
2428 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2430 elem_bb[idim*2] = coords[node*dim+idim] ;
2432 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2434 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2439 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2440 elems->pushBackSilent(ielem);
2442 return elems.retn();
2446 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2447 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2448 * added in 'elems' parameter.
2450 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2453 if(getMeshDimension()==-1)
2455 elems->pushBackSilent(0);
2456 return elems.retn();
2458 int dim=getSpaceDimension();
2459 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2460 const int* conn = getNodalConnectivity()->getConstPointer();
2461 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2462 const double* coords = getCoords()->getConstPointer();
2463 int nbOfCells=getNumberOfCells();
2464 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2466 for (int i=0; i<dim; i++)
2468 elem_bb[i*2]=std::numeric_limits<double>::max();
2469 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2472 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2474 int node= conn[inode];
2475 if(node>=0)//avoid polyhedron separator
2477 for (int idim=0; idim<dim; idim++)
2479 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2481 elem_bb[idim*2] = coords[node*dim+idim] ;
2483 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2485 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2490 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2491 elems->pushBackSilent(ielem);
2493 return elems.retn();
2497 * Returns the cell type of cell with id 'cellId'.
2499 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2501 const int *ptI=_nodal_connec_index->getConstPointer();
2502 const int *pt=_nodal_connec->getConstPointer();
2503 if(cellId>=0 && cellId<_nodal_connec_index->getNbOfElems()-1)
2504 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2507 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2508 throw INTERP_KERNEL::Exception(oss.str().c_str());
2513 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2514 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2515 * The coordinates array is not considered here.
2517 * \param [in] type the geometric type
2518 * \return cell ids in this having geometric type \a type.
2520 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2525 checkConnectivityFullyDefined();
2526 int nbCells=getNumberOfCells();
2527 int mdim=getMeshDimension();
2528 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2529 if(mdim!=(int)cm.getDimension())
2530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2531 const int *ptI=_nodal_connec_index->getConstPointer();
2532 const int *pt=_nodal_connec->getConstPointer();
2533 for(int i=0;i<nbCells;i++)
2535 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2536 ret->pushBackSilent(i);
2542 * Returns nb of cells having the geometric type 'type'.
2544 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2546 const int *ptI=_nodal_connec_index->getConstPointer();
2547 const int *pt=_nodal_connec->getConstPointer();
2548 int nbOfCells=getNumberOfCells();
2550 for(int i=0;i<nbOfCells;i++)
2551 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2557 * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2558 * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2559 * That is to say -1 separator is omitted in returned conn.
2561 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2563 const int *ptI=_nodal_connec_index->getConstPointer();
2564 const int *pt=_nodal_connec->getConstPointer();
2565 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2570 std::string MEDCouplingUMesh::simpleRepr() const
2572 static const char msg0[]="No coordinates specified !";
2573 std::ostringstream ret;
2574 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2575 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2577 double tt=getTime(tmpp1,tmpp2);
2578 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2579 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2580 ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2583 const int spaceDim=getSpaceDimension();
2584 ret << spaceDim << "\nInfo attached on space dimension : ";
2585 for(int i=0;i<spaceDim;i++)
2586 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2590 ret << msg0 << "\n";
2591 ret << "Number of nodes : ";
2593 ret << getNumberOfNodes() << "\n";
2595 ret << msg0 << "\n";
2596 ret << "Number of cells : ";
2597 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2598 ret << getNumberOfCells() << "\n";
2600 ret << "No connectivity specified !" << "\n";
2601 ret << "Cell types present : ";
2602 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2604 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2605 ret << cm.getRepr() << " ";
2611 std::string MEDCouplingUMesh::advancedRepr() const
2613 std::ostringstream ret;
2614 ret << simpleRepr();
2615 ret << "\nCoordinates array : \n___________________\n\n";
2617 _coords->reprWithoutNameStream(ret);
2619 ret << "No array set !\n";
2620 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2621 reprConnectivityOfThisLL(ret);
2626 * This method returns a C++ code that is a dump of \a this.
2627 * This method will throw if this is not fully defined.
2629 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2631 static const char coordsName[]="coords";
2632 static const char connName[]="conn";
2633 static const char connIName[]="connI";
2634 checkFullyDefined();
2635 std::ostringstream ret; ret << "// coordinates" << std::endl;
2636 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2637 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2638 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2639 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2640 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2641 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2642 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2646 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2648 std::ostringstream ret;
2649 reprConnectivityOfThisLL(ret);
2654 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2655 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2656 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2659 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2660 * 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
2661 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2663 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2665 int mdim=getMeshDimension();
2667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2668 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2670 bool needToCpyCT=true;
2673 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2681 if(!_nodal_connec_index)
2683 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2688 tmp2=_nodal_connec_index;
2691 ret->setConnectivity(tmp1,tmp2,false);
2696 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2697 ret->setCoords(coords);
2700 ret->setCoords(_coords);
2704 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2706 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2708 int nbOfCells=getNumberOfCells();
2709 const int *c=_nodal_connec->getConstPointer();
2710 const int *ci=_nodal_connec_index->getConstPointer();
2711 for(int i=0;i<nbOfCells;i++)
2713 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2714 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2715 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2720 stream << "Connectivity not defined !\n";
2723 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2725 const int *ptI=_nodal_connec_index->getConstPointer();
2726 const int *pt=_nodal_connec->getConstPointer();
2727 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2728 return ptI[cellId+1]-ptI[cellId]-1;
2730 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2734 * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2735 * This method avoids to compute explicitely submesh to get its types.
2737 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2739 checkFullyDefined();
2740 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2741 const int *conn=_nodal_connec->getConstPointer();
2742 const int *connIndex=_nodal_connec_index->getConstPointer();
2743 for(const int *w=begin;w!=end;w++)
2744 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2749 * Method reserved for advanced users having prepared their connectivity before.
2750 * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2752 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2754 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2755 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2756 if(isComputingTypes)
2762 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2763 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2765 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2766 _nodal_connec(0),_nodal_connec_index(0),
2767 _types(other._types)
2769 if(other._nodal_connec)
2770 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2771 if(other._nodal_connec_index)
2772 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2775 MEDCouplingUMesh::~MEDCouplingUMesh()
2778 _nodal_connec->decrRef();
2779 if(_nodal_connec_index)
2780 _nodal_connec_index->decrRef();
2784 * This method recomputes all cell types of 'this'.
2786 void MEDCouplingUMesh::computeTypes()
2788 if(_nodal_connec && _nodal_connec_index)
2791 const int *conn=_nodal_connec->getConstPointer();
2792 const int *connIndex=_nodal_connec_index->getConstPointer();
2793 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2794 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
2795 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2800 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2802 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2804 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2805 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2809 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2811 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2813 if(!_nodal_connec_index || !_nodal_connec)
2814 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2817 int MEDCouplingUMesh::getNumberOfCells() const
2819 if(_nodal_connec_index)
2820 return _nodal_connec_index->getNumberOfTuples()-1;
2825 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2828 int MEDCouplingUMesh::getMeshDimension() const
2831 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2836 * This method is for test reason. Normally the integer returned is not useable by user.
2838 int MEDCouplingUMesh::getMeshLength() const
2840 return _nodal_connec->getNbOfElems();
2844 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2846 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2848 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2849 tinyInfo.push_back(getMeshDimension());
2850 tinyInfo.push_back(getNumberOfCells());
2852 tinyInfo.push_back(getMeshLength());
2854 tinyInfo.push_back(-1);
2858 * First step of unserialization process.
2860 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2862 return tinyInfo[6]<=0;
2866 * Second step of serialization process.
2867 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2869 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2871 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2873 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2877 * Third and final step of serialization process.
2879 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2881 MEDCouplingPointSet::serialize(a1,a2);
2882 if(getMeshDimension()>-1)
2884 a1=DataArrayInt::New();
2885 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2886 int *ptA1=a1->getPointer();
2887 const int *conn=getNodalConnectivity()->getConstPointer();
2888 const int *index=getNodalConnectivityIndex()->getConstPointer();
2889 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2890 std::copy(conn,conn+getMeshLength(),ptA1);
2897 * Second and final unserialization process.
2898 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2900 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2902 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2903 setMeshDimension(tinyInfo[5]);
2907 const int *recvBuffer=a1->getConstPointer();
2908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
2909 myConnecIndex->alloc(tinyInfo[6]+1,1);
2910 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
2912 myConnec->alloc(tinyInfo[7],1);
2913 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2914 setConnectivity(myConnec, myConnecIndex);
2919 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2920 * CellIds are given using range specified by a start an end and step.
2922 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2924 checkFullyDefined();
2925 int ncell=getNumberOfCells();
2926 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2927 ret->_mesh_dim=_mesh_dim;
2928 ret->setCoords(_coords);
2929 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2931 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2933 const int *conn=_nodal_connec->getConstPointer();
2934 const int *connIndex=_nodal_connec_index->getConstPointer();
2935 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2937 if(work>=0 && work<ncell)
2939 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2943 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2944 throw INTERP_KERNEL::Exception(oss.str().c_str());
2947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
2948 int *newConnPtr=newConn->getPointer();
2949 std::set<INTERP_KERNEL::NormalizedCellType> types;
2951 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2953 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
2954 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
2956 ret->setConnectivity(newConn,newConnI,false);
2958 ret->copyTinyInfoFrom(this);
2963 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
2964 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2965 * The return newly allocated mesh will share the same coordinates as 'this'.
2967 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
2969 checkFullyDefined();
2970 int ncell=getNumberOfCells();
2971 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2972 ret->_mesh_dim=_mesh_dim;
2973 ret->setCoords(_coords);
2974 std::size_t nbOfElemsRet=std::distance(begin,end);
2975 int *connIndexRet=new int[nbOfElemsRet+1];
2977 const int *conn=_nodal_connec->getConstPointer();
2978 const int *connIndex=_nodal_connec_index->getConstPointer();
2980 for(const int *work=begin;work!=end;work++,newNbring++)
2982 if(*work>=0 && *work<ncell)
2983 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
2986 delete [] connIndexRet;
2987 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
2988 throw INTERP_KERNEL::Exception(oss.str().c_str());
2991 int *connRet=new int[connIndexRet[nbOfElemsRet]];
2992 int *connRetWork=connRet;
2993 std::set<INTERP_KERNEL::NormalizedCellType> types;
2994 for(const int *work=begin;work!=end;work++)
2996 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
2997 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
2999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3000 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3002 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3003 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3005 ret->copyTinyInfoFrom(this);
3010 * brief returns the volumes of the cells underlying the field \a field
3012 * For 2D geometries, the returned field contains the areas.
3013 * For 3D geometries, the returned field contains the volumes.
3015 * param field field on which cells the volumes are required
3016 * return field containing the volumes, area or length depending the meshdimension.
3018 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3020 std::string name="MeasureOfMesh_";
3022 int nbelem=getNumberOfCells();
3023 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3024 field->setName(name.c_str());
3025 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3026 array->alloc(nbelem,1);
3027 double *area_vol=array->getPointer();
3028 field->setArray(array) ; array=0;
3029 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3030 field->synchronizeTimeWithMesh();
3031 if(getMeshDimension()!=-1)
3034 INTERP_KERNEL::NormalizedCellType type;
3035 int dim_space=getSpaceDimension();
3036 const double *coords=getCoords()->getConstPointer();
3037 const int *connec=getNodalConnectivity()->getConstPointer();
3038 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3039 for(int iel=0;iel<nbelem;iel++)
3041 ipt=connec_index[iel];
3042 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3043 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);
3046 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3050 area_vol[0]=std::numeric_limits<double>::max();
3052 return field.retn();
3056 * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3057 * This method avoids to build explicitely part of this to perform the work.
3059 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3061 std::string name="PartMeasureOfMesh_";
3063 int nbelem=(int)std::distance(begin,end);
3064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3065 array->setName(name.c_str());
3066 array->alloc(nbelem,1);
3067 double *area_vol=array->getPointer();
3068 if(getMeshDimension()!=-1)
3071 INTERP_KERNEL::NormalizedCellType type;
3072 int dim_space=getSpaceDimension();
3073 const double *coords=getCoords()->getConstPointer();
3074 const int *connec=getNodalConnectivity()->getConstPointer();
3075 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3076 for(const int *iel=begin;iel!=end;iel++)
3078 ipt=connec_index[*iel];
3079 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3080 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3083 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3087 area_vol[0]=std::numeric_limits<double>::max();
3089 return array.retn();
3093 * This methods returns a field on nodes and no time. This method is usefull to check "P1*" conservative interpolators.
3094 * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3096 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3098 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3099 std::string name="MeasureOnNodeOfMesh_";
3101 int nbNodes=getNumberOfNodes();
3102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3103 double cst=1./((double)getMeshDimension()+1.);
3104 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3105 array->alloc(nbNodes,1);
3106 double *valsToFill=array->getPointer();
3107 std::fill(valsToFill,valsToFill+nbNodes,0.);
3108 const double *values=tmp->getArray()->getConstPointer();
3109 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3110 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3111 getReverseNodalConnectivity(da,daInd);
3112 const int *daPtr=da->getConstPointer();
3113 const int *daIPtr=daInd->getConstPointer();
3114 for(int i=0;i<nbNodes;i++)
3115 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3116 valsToFill[i]+=cst*values[*cell];
3118 ret->setArray(array);
3123 * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3124 * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3126 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3128 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3129 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3130 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3131 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3132 int nbOfCells=getNumberOfCells();
3133 int nbComp=getMeshDimension()+1;
3134 array->alloc(nbOfCells,nbComp);
3135 double *vals=array->getPointer();
3136 const int *connI=_nodal_connec_index->getConstPointer();
3137 const int *conn=_nodal_connec->getConstPointer();
3138 const double *coords=_coords->getConstPointer();
3139 if(getMeshDimension()==2)
3141 if(getSpaceDimension()==3)
3143 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3144 const double *locPtr=loc->getConstPointer();
3145 for(int i=0;i<nbOfCells;i++,vals+=3)
3147 int offset=connI[i];
3148 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3149 double n=INTERP_KERNEL::norm<3>(vals);
3150 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3155 for(int i=0;i<nbOfCells;i++)
3156 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3159 else//meshdimension==1
3162 for(int i=0;i<nbOfCells;i++)
3164 int offset=connI[i];
3165 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3166 double n=INTERP_KERNEL::norm<2>(tmp);
3167 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3172 ret->setArray(array);
3174 ret->synchronizeTimeWithSupport();
3179 * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3180 * This method avoids to build explicitely part of this to perform the work.
3182 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3184 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3185 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3187 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3188 std::size_t nbelems=std::distance(begin,end);
3189 int nbComp=getMeshDimension()+1;
3190 array->alloc((int)nbelems,nbComp);
3191 double *vals=array->getPointer();
3192 const int *connI=_nodal_connec_index->getConstPointer();
3193 const int *conn=_nodal_connec->getConstPointer();
3194 const double *coords=_coords->getConstPointer();
3195 if(getMeshDimension()==2)
3197 if(getSpaceDimension()==3)
3199 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3200 const double *locPtr=loc->getConstPointer();
3201 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3203 int offset=connI[*i];
3204 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3205 double n=INTERP_KERNEL::norm<3>(vals);
3206 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3211 for(std::size_t i=0;i<nbelems;i++)
3212 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3215 else//meshdimension==1
3218 for(const int *i=begin;i!=end;i++)
3220 int offset=connI[*i];
3221 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3222 double n=INTERP_KERNEL::norm<2>(tmp);
3223 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3228 ret->setArray(array);
3230 ret->synchronizeTimeWithSupport();
3235 * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3236 * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3238 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3240 if(getMeshDimension()!=1)
3241 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3242 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3243 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3244 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3245 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3246 int nbOfCells=getNumberOfCells();
3247 int spaceDim=getSpaceDimension();
3248 array->alloc(nbOfCells,spaceDim);
3249 double *pt=array->getPointer();
3250 const double *coo=getCoords()->getConstPointer();
3251 std::vector<int> conn;
3253 for(int i=0;i<nbOfCells;i++)
3256 getNodeIdsOfCell(i,conn);
3257 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3259 ret->setArray(array);
3261 ret->synchronizeTimeWithSupport();
3266 * 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.
3267 * This method returns 2 objects :
3268 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3269 * - 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
3270 * mesh the 3D cell id is 'this' it comes from.
3271 * This method works only for linear meshes (non quadratic).
3272 * 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
3273 * face. Only 'cellIds' parameter can distinguish the 2.
3274 * @param origin is the origin of the plane. It should be an array of length 3.
3275 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3276 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3277 * 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).
3279 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3281 checkFullyDefined();
3282 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3283 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3285 if(candidates->empty())
3286 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3287 std::vector<int> nodes;
3288 DataArrayInt *cellIds1D=0;
3289 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3290 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3296 revDesc2=0; revDescIndx2=0;
3297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3298 revDesc1=0; revDescIndx1=0;
3299 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3302 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3303 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3305 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3306 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3307 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3308 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3309 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3311 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3312 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3313 if(cellIds2->empty())
3314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3315 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3316 ret->setCoords(mDesc1->getCoords());
3317 ret->setConnectivity(conn,connI,true);
3318 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3323 * 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.
3324 * This method returns 2 objects :
3325 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3326 * - 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
3327 * mesh the 3DSurf cell id is 'this' it comes from.
3328 * This method works only for linear meshes (non quadratic).
3329 * 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
3330 * face. Only 'cellIds' parameter can distinguish the 2.
3331 * @param origin is the origin of the plane. It should be an array of length 3.
3332 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3333 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3334 * 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).
3336 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3338 checkFullyDefined();
3339 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3342 if(candidates->empty())
3343 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3344 std::vector<int> nodes;
3345 DataArrayInt *cellIds1D=0;
3346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3347 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3350 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3352 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3353 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3356 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3357 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3359 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3360 int ncellsSub=subMesh->getNumberOfCells();
3361 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3362 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3363 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3364 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3367 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3368 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3369 for(int i=0;i<ncellsSub;i++)
3371 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3373 if(cut3DSurf[i].first!=-2)
3375 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3376 connI->pushBackSilent(conn->getNumberOfTuples());
3377 cellIds2->pushBackSilent(i);
3381 int cellId3DSurf=cut3DSurf[i].second;
3382 int offset=nodalI[cellId3DSurf]+1;
3383 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3384 for(int j=0;j<nbOfEdges;j++)
3386 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3387 connI->pushBackSilent(conn->getNumberOfTuples());
3388 cellIds2->pushBackSilent(cellId3DSurf);
3393 if(cellIds2->empty())
3394 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3395 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3396 ret->setCoords(mDesc1->getCoords());
3397 ret->setConnectivity(conn,connI,true);
3398 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3403 * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3404 * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3405 * @param origin is the origin of the plane. It should be an array of length 3.
3406 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3408 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3410 checkFullyDefined();
3411 if(getSpaceDimension()!=3)
3412 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3413 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3415 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3417 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3418 double angle=acos(vec[2]/normm);
3419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3423 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3424 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3425 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3427 mw->getBoundingBox(bbox);
3428 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3429 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3433 getBoundingBox(bbox);
3434 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3435 cellIds=getCellsInBoundingBox(bbox,eps);
3437 return cellIds.retn();
3441 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3442 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3443 * No consideration of coordinate is done by this method.
3444 * 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)
3445 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3447 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3449 if(getMeshDimension()!=1)
3450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3451 int nbCells=getNumberOfCells();
3453 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3454 const int *connI=_nodal_connec_index->getConstPointer();
3455 const int *conn=_nodal_connec->getConstPointer();
3456 int ref=conn[connI[0]+2];
3457 for(int i=1;i<nbCells;i++)
3459 if(conn[connI[i]+1]!=ref)
3461 ref=conn[connI[i]+2];
3467 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3468 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3469 * @param pt reference point of the line
3470 * @param v normalized director vector of the line
3471 * @param eps max precision before throwing an exception
3472 * @param res output of size this->getNumberOfCells
3474 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3476 if(getMeshDimension()!=1)
3477 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3478 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3479 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3480 if(getSpaceDimension()!=3)
3481 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3482 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3483 const double *fPtr=f->getArray()->getConstPointer();
3485 for(int i=0;i<getNumberOfCells();i++)
3487 const double *tmp1=fPtr+3*i;
3488 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3489 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3490 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3491 double n1=INTERP_KERNEL::norm<3>(tmp);
3492 n1/=INTERP_KERNEL::norm<3>(tmp1);
3494 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3496 const double *coo=getCoords()->getConstPointer();
3497 for(int i=0;i<getNumberOfNodes();i++)
3499 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3500 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3501 res[i]=std::accumulate(tmp,tmp+3,0.);
3506 * 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.
3507 * \a this is expected to be a mesh so that its space dimension is equal to its
3508 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3509 * 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).
3511 * 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
3512 * 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
3513 * to the node that minimizes distance with the input point then -1 is returned in cellId.
3515 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3516 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3518 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3519 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3520 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3521 * \return the positive value of the distance.
3522 * \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
3524 * \sa DataArrayDouble::distanceToTuple
3526 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
3528 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3529 if(meshDim!=spaceDim-1)
3530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3531 if(meshDim!=2 && meshDim!=1)
3532 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3533 checkFullyDefined();
3534 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3535 { 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()); }
3537 double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
3539 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
3540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
3545 distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
3550 distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
3554 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3562 * \param [in] pt the start pointer (included) of the coordinates of the point
3563 * \param [in] cellIds
3564 * \param [in,out] ret0 the min distance between \a this and the external input point
3565 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3566 * \sa MEDCouplingUMesh::distanceToPoint
3568 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3570 const double *coords=_coords->getConstPointer();
3572 if(cellIds->empty())
3574 const int *ptr=_nodal_connec->getConstPointer();
3575 const int *ptrI=_nodal_connec_index->getConstPointer();
3576 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3578 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3580 case INTERP_KERNEL::NORM_TRI3:
3582 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
3584 { ret0=tmp; cellId=*zeCell; }
3587 case INTERP_KERNEL::NORM_QUAD4:
3588 case INTERP_KERNEL::NORM_POLYGON:
3590 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
3592 { ret0=tmp; cellId=*zeCell; }
3596 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3602 * \param [in] pt the start pointer (included) of the coordinates of the point
3603 * \param [in] cellIds
3604 * \param [in,out] ret0 the min distance between \a this and the external input point
3605 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3606 * \sa MEDCouplingUMesh::distanceToPoint
3608 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3610 const double *coords=_coords->getConstPointer();
3611 if(cellIds->empty())
3612 { cellId=-1; return; }
3613 const int *ptr=_nodal_connec->getConstPointer();
3614 const int *ptrI=_nodal_connec_index->getConstPointer();
3615 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3617 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3619 case INTERP_KERNEL::NORM_SEG2:
3621 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
3622 if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
3624 { ret0=tmp; cellId=*zeCell; }
3628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3634 * Returns a cell if any that contains the point located on 'pos' with precison eps.
3635 * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3636 * \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'
3637 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3639 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3641 std::vector<int> elts;
3642 getCellsContainingPoint(pos,eps,elts);
3645 return elts.front();
3649 * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3650 * \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'
3651 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3653 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3655 std::vector<int> eltsIndex;
3656 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3661 namespace ParaMEDMEM
3663 template<const int SPACEDIMM>
3667 static const int MY_SPACEDIM=SPACEDIMM;
3668 static const int MY_MESHDIM=8;
3669 typedef int MyConnType;
3670 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3672 // useless, but for windows compilation ...
3673 const double* getCoordinatesPtr() const { return 0; }
3674 const int* getConnectivityPtr() const { return 0; }
3675 const int* getConnectivityIndexPtr() const { return 0; }
3676 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3680 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3682 INTERP_KERNEL::Edge *ret=0;
3685 case INTERP_KERNEL::NORM_SEG2:
3687 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3690 case INTERP_KERNEL::NORM_SEG3:
3692 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3693 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3694 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3695 bool colinearity=inters.areColinears();
3696 delete e1; delete e2;
3698 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3700 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3701 mapp2[bg[2]].second=false;
3705 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3711 * 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'.
3712 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3713 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3715 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3718 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.
3719 const double *coo=mDesc->getCoords()->getConstPointer();
3720 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3721 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3723 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3724 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3725 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3727 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3728 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3730 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3731 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3733 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3734 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3736 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3738 if((*it2).second.second)
3739 mapp[(*it2).second.first]=(*it2).first;
3740 ((*it2).second.first)->decrRef();
3745 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3749 int locId=nodeId-offset2;
3750 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3754 int locId=nodeId-offset1;
3755 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3757 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3760 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3761 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3762 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3764 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3766 int eltId1=abs(*desc1)-1;
3767 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3769 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3770 if(it==mappRev.end())
3772 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3783 template<int SPACEDIM>
3784 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3785 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3787 std::vector<double> bbox;
3788 eltsIndex.resize(nbOfPoints+1);
3791 getBoundingBoxForBBTree(bbox);
3792 int nbOfCells=getNumberOfCells();
3793 const int *conn=_nodal_connec->getConstPointer();
3794 const int *connI=_nodal_connec_index->getConstPointer();
3795 double bb[2*SPACEDIM];
3796 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3797 for(int i=0;i<nbOfPoints;i++)
3799 eltsIndex[i+1]=eltsIndex[i];
3800 for(int j=0;j<SPACEDIM;j++)
3802 bb[2*j]=pos[SPACEDIM*i+j];
3803 bb[2*j+1]=pos[SPACEDIM*i+j];
3805 std::vector<int> candidates;
3806 myTree.getIntersectingElems(bb,candidates);
3807 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3809 int sz=connI[(*iter)+1]-connI[*iter]-1;
3810 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3811 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3812 coords,conn+connI[*iter]+1,sz,eps))
3815 elts.push_back(*iter);
3822 * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3823 * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3824 * in case of multi points searching.
3825 * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3826 * 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]).
3828 * \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...
3830 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3831 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3833 int spaceDim=getSpaceDimension();
3834 int mDim=getMeshDimension();
3839 const double *coords=_coords->getConstPointer();
3840 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3847 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3849 else if(spaceDim==2)
3853 const double *coords=_coords->getConstPointer();
3854 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3857 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3859 else if(spaceDim==1)
3863 const double *coords=_coords->getConstPointer();
3864 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3867 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3870 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3874 * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3875 * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3876 * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3877 * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3879 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3881 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3882 if(getMeshDimension()!=2)
3883 throw INTERP_KERNEL::Exception(msg);
3884 int spaceDim=getSpaceDimension();
3885 if(spaceDim!=2 && spaceDim!=3)
3886 throw INTERP_KERNEL::Exception(msg);
3887 const int *conn=_nodal_connec->getConstPointer();
3888 const int *connI=_nodal_connec_index->getConstPointer();
3889 int nbOfCells=getNumberOfCells();
3890 std::vector<double> cell2DinS2;
3891 for(int i=0;i<nbOfCells;i++)
3893 int offset=connI[i];
3894 int nbOfNodesForCell=connI[i+1]-offset-1;
3895 if(nbOfNodesForCell<=3)
3897 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3898 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3899 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3906 * This method is typically requested to unbutterfly 2D linear cells in \b this.
3908 * 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.
3909 * 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.
3911 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3912 * This convex envelop is computed using Jarvis march algorithm.
3913 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3914 * 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)
3915 * 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.
3917 * @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.
3919 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3921 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3922 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
3923 checkFullyDefined();
3924 const double *coords=getCoords()->getConstPointer();
3925 int nbOfCells=getNumberOfCells();
3926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3927 nodalConnecIndexOut->alloc(nbOfCells+1,1);
3928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
3929 int *workIndexOut=nodalConnecIndexOut->getPointer();
3931 const int *nodalConnecIn=_nodal_connec->getConstPointer();
3932 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3933 std::set<INTERP_KERNEL::NormalizedCellType> types;
3934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
3935 isChanged->alloc(0,1);
3936 for(int i=0;i<nbOfCells;i++,workIndexOut++)
3938 int pos=nodalConnecOut->getNumberOfTuples();
3939 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3940 isChanged->pushBackSilent(i);
3941 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
3942 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
3944 if(isChanged->empty())
3946 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
3948 return isChanged.retn();
3952 * This method is \b NOT const because it can modify 'this'.
3953 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
3954 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
3955 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
3956 * \b 1 for translation and rotation around point of 'mesh1D'.
3957 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
3959 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
3961 checkFullyDefined();
3962 mesh1D->checkFullyDefined();
3963 if(!mesh1D->isContiguous1D())
3964 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
3965 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
3966 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same dimension !");
3967 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3968 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
3969 if(mesh1D->getMeshDimension()!=1)
3970 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
3972 if(isPresenceOfQuadratic())
3974 if(mesh1D->isFullyQuadratic())
3977 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
3980 int oldNbOfNodes=getNumberOfNodes();
3981 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
3986 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
3991 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
3995 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
3997 setCoords(newCoords);
3998 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4004 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4005 * If it is not the case an exception will be thrown.
4006 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4007 * intersection of plane defined by ('origin','vec').
4008 * This method has one in/out parameter : 'cut3DCurve'.
4009 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4010 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4011 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4012 * This method will throw an exception if 'this' contains a non linear segment.
4014 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4016 checkFullyDefined();
4017 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4019 int ncells=getNumberOfCells();
4020 int nnodes=getNumberOfNodes();
4021 double vec2[3],vec3[3],vec4[3];
4022 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4024 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4025 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4026 const int *conn=_nodal_connec->getConstPointer();
4027 const int *connI=_nodal_connec_index->getConstPointer();
4028 const double *coo=_coords->getConstPointer();
4029 std::vector<double> addCoo;
4030 for(int i=0;i<ncells;i++)
4032 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4034 if(cut3DCurve[i]==-2)
4036 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4037 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];
4038 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4039 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4040 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4042 const double *st2=coo+3*st;
4043 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4044 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]));
4045 if(pos>eps && pos<1-eps)
4047 int nNode=((int)addCoo.size())/3;
4048 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4049 addCoo.insert(addCoo.end(),vec4,vec4+3);
4050 cut3DCurve[i]=nnodes+nNode;
4056 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4060 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4061 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4062 coo2->alloc(newNbOfNodes,3);
4063 double *tmp=coo2->getPointer();
4064 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4065 std::copy(addCoo.begin(),addCoo.end(),tmp);
4066 DataArrayDouble::SetArrayIn(coo2,_coords);
4071 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4072 * @param mesh1D is the input 1D mesh used for translation computation.
4073 * @return newCoords new coords filled by this method.
4075 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4077 int oldNbOfNodes=getNumberOfNodes();
4078 int nbOf1DCells=mesh1D->getNumberOfCells();
4079 int spaceDim=getSpaceDimension();
4080 DataArrayDouble *ret=DataArrayDouble::New();
4081 std::vector<bool> isQuads;
4082 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4083 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4084 double *retPtr=ret->getPointer();
4085 const double *coords=getCoords()->getConstPointer();
4086 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4088 std::vector<double> c;
4092 for(int i=0;i<nbOf1DCells;i++)
4095 mesh1D->getNodeIdsOfCell(i,v);
4097 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4098 mesh1D->getCoordinatesOfNode(v[0],c);
4099 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4100 for(int j=0;j<oldNbOfNodes;j++)
4101 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4105 mesh1D->getCoordinatesOfNode(v[1],c);
4106 mesh1D->getCoordinatesOfNode(v[0],c);
4107 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4108 for(int j=0;j<oldNbOfNodes;j++)
4109 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4112 ret->copyStringInfoFrom(*getCoords());
4117 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4118 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4119 * @return newCoords new coords filled by this method.
4121 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4123 if(mesh1D->getSpaceDimension()==2)
4124 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4125 if(mesh1D->getSpaceDimension()==3)
4126 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4127 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4131 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4132 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4133 * @return newCoords new coords filled by this method.
4135 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4138 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4139 int oldNbOfNodes=getNumberOfNodes();
4140 int nbOf1DCells=mesh1D->getNumberOfCells();
4142 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4143 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4144 int nbOfLevsInVec=nbOf1DCells+1;
4145 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4146 double *retPtr=ret->getPointer();
4147 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4148 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4149 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4150 tmp->setCoords(tmp2);
4151 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4152 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4153 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4154 for(int i=1;i<nbOfLevsInVec;i++)
4156 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4157 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4158 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4159 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4160 tmp->translate(vec);
4161 double tmp3[2],radius,alpha,alpha0;
4162 const double *p0=i+1<nbOfLevsInVec?begin:third;
4163 const double *p1=i+1<nbOfLevsInVec?end:begin;
4164 const double *p2=i+1<nbOfLevsInVec?third:end;
4165 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4166 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]);
4167 double angle=acos(cosangle/(radius*radius));
4168 tmp->rotate(end,0,angle);
4169 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4175 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4176 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4177 * @return newCoords new coords filled by this method.
4179 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4182 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4183 int oldNbOfNodes=getNumberOfNodes();
4184 int nbOf1DCells=mesh1D->getNumberOfCells();
4186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4187 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4188 int nbOfLevsInVec=nbOf1DCells+1;
4189 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4190 double *retPtr=ret->getPointer();
4191 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4192 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4193 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4194 tmp->setCoords(tmp2);
4195 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4196 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4197 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4198 for(int i=1;i<nbOfLevsInVec;i++)
4200 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4201 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4202 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4203 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4204 tmp->translate(vec);
4205 double tmp3[2],radius,alpha,alpha0;
4206 const double *p0=i+1<nbOfLevsInVec?begin:third;
4207 const double *p1=i+1<nbOfLevsInVec?end:begin;
4208 const double *p2=i+1<nbOfLevsInVec?third:end;
4209 double vecPlane[3]={
4210 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4211 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4212 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4214 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4217 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4218 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4219 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4221 double c2=cos(asin(s2));
4223 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4224 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4225 {-vec2[1]*s2, vec2[0]*s2, c2}
4227 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]};
4228 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]};
4229 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]};
4230 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4231 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]);
4232 double angle=acos(cosangle/(radius*radius));
4233 tmp->rotate(end,vecPlane,angle);
4236 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4242 * This method is private because not easy to use for end user. This method is const contrary to
4243 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4244 * the coords sorted slice by slice.
4245 * @param isQuad specifies presence of quadratic cells.
4247 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4249 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4250 int nbOf2DCells=getNumberOfCells();
4251 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4252 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4253 const int *conn=_nodal_connec->getConstPointer();
4254 const int *connI=_nodal_connec_index->getConstPointer();
4255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4256 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4257 newConnI->alloc(nbOf3DCells+1,1);
4258 int *newConnIPtr=newConnI->getPointer();
4260 std::vector<int> newc;
4261 for(int j=0;j<nbOf2DCells;j++)
4263 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4264 *newConnIPtr++=(int)newc.size();
4266 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4267 int *newConnPtr=newConn->getPointer();
4268 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4269 newConnIPtr=newConnI->getPointer();
4270 for(int iz=0;iz<nbOf1DCells;iz++)
4273 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4274 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4276 int icell=(int)(iter-newc.begin());
4277 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4280 *newConnPtr=(*iter)+iz*deltaPerLev;
4285 *newConnPtr=(*iter);
4288 ret->setConnectivity(newConn,newConnI,true);
4289 ret->setCoords(getCoords());
4294 * This method returns if 'this' is constituted by only quadratic cells.
4296 bool MEDCouplingUMesh::isFullyQuadratic() const
4298 checkFullyDefined();
4300 int nbOfCells=getNumberOfCells();
4301 for(int i=0;i<nbOfCells && ret;i++)
4303 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4304 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4305 ret=cm.isQuadratic();
4311 * This method returns if there is at least one quadratic cell.
4313 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4315 checkFullyDefined();
4317 int nbOfCells=getNumberOfCells();
4318 for(int i=0;i<nbOfCells && !ret;i++)
4320 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4321 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4322 ret=cm.isQuadratic();
4328 * This method convert quadratic cells to linear cells if any was found.
4329 * If no such cells exists 'this' remains unchanged.
4331 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4333 checkFullyDefined();
4334 int nbOfCells=getNumberOfCells();
4336 for(int i=0;i<nbOfCells;i++)
4338 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4339 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4340 if(cm.isQuadratic())
4342 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4343 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4344 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4350 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4351 newConn->alloc(getMeshLength()-delta,1);
4352 newConnI->alloc(nbOfCells+1,1);
4353 const int *icptr=_nodal_connec->getConstPointer();
4354 const int *iciptr=_nodal_connec_index->getConstPointer();
4355 int *ocptr=newConn->getPointer();
4356 int *ociptr=newConnI->getPointer();
4359 for(int i=0;i<nbOfCells;i++,ociptr++)
4361 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4362 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4363 if(!cm.isQuadratic())
4365 _types.insert(type);
4366 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4367 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4371 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4372 _types.insert(typel);
4373 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4374 int newNbOfNodes=cml.getNumberOfNodes();
4375 *ocptr++=(int)typel;
4376 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4377 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4380 setConnectivity(newConn,newConnI,false);
4384 * This method converts all linear cell in \a this to quadratic one.
4385 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4386 * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
4387 * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
4388 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4389 * end of the existing coordinates.
4391 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4392 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4393 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4395 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4397 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4399 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4401 DataArrayInt *conn=0,*connI=0;
4402 DataArrayDouble *coords=0;
4403 std::set<INTERP_KERNEL::NormalizedCellType> types;
4404 checkFullyDefined();
4405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4406 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4407 int meshDim=getMeshDimension();
4408 switch(conversionType)
4414 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4415 connSafe=conn; connISafe=connI; coordsSafe=coords;
4417 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4418 connSafe=conn; connISafe=connI; coordsSafe=coords;
4420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1] !");
4423 //return convertLinearCellsToQuadratic1();
4425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4427 setConnectivity(connSafe,connISafe,false);
4429 setCoords(coordsSafe);
4434 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4435 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4436 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4438 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4440 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4442 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4443 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4444 int nbOfCells=getNumberOfCells();
4445 int nbOfNodes=getNumberOfNodes();
4446 const int *cPtr=_nodal_connec->getConstPointer();
4447 const int *icPtr=_nodal_connec_index->getConstPointer();
4448 int lastVal=0,offset=nbOfNodes;
4449 for(int i=0;i<nbOfCells;i++,icPtr++)
4451 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4452 if(type==INTERP_KERNEL::NORM_SEG2)
4454 types.insert(INTERP_KERNEL::NORM_SEG3);
4455 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4456 newConn->pushBackValsSilent(cPtr+cPtr[0]+1,cPtr+cPtr[0]+3);
4457 newConn->pushBackSilent(offset++);
4458 newConnI->pushBackSilent(lastVal+4);
4459 ret->pushBackSilent(i);
4465 int tmp=lastVal+(icPtr[1]-icPtr[0]);
4466 newConnI->pushBackSilent(tmp);
4467 newConn->pushBackValsSilent(cPtr+cPtr[0],cPtr+cPtr[1]);
4471 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4472 conn=newConn.retn(); connI=newConnI.retn(); coords=DataArrayDouble::Aggregate(getCoords(),tmp);
4477 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4478 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4479 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4481 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New());
4484 DataArrayInt *tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
4485 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity2(desc,descI,tmp2,tmp3); tmp2->decrRef(); tmp3->decrRef();
4486 DataArrayInt *conn1D=0,*conn1DI=0;
4487 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coords,types1D); ret1D=0;
4493 * This method tessallates 'this' so that the number of cells remains the same.
4494 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4495 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4497 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4498 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4500 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4502 checkFullyDefined();
4503 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4504 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4505 double epsa=fabs(eps);
4506 if(epsa<std::numeric_limits<double>::min())
4507 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 !");
4508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4512 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4513 revDesc1=0; revDescIndx1=0;
4514 mDesc->tessellate2DCurve(eps);
4515 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4516 setCoords(mDesc->getCoords());
4520 * This method tessallates 'this' so that the number of cells remains the same.
4521 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4522 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4524 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4525 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4527 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4529 checkFullyDefined();
4530 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4532 double epsa=fabs(eps);
4533 if(epsa<std::numeric_limits<double>::min())
4534 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 !");
4535 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4536 int nbCells=getNumberOfCells();
4537 int nbNodes=getNumberOfNodes();
4538 const int *conn=_nodal_connec->getConstPointer();
4539 const int *connI=_nodal_connec_index->getConstPointer();
4540 const double *coords=_coords->getConstPointer();
4541 std::vector<double> addCoo;
4542 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
4543 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
4544 newConnI->alloc(nbCells+1,1);
4545 int *newConnIPtr=newConnI->getPointer();
4548 INTERP_KERNEL::Node *tmp2[3];
4549 std::set<INTERP_KERNEL::NormalizedCellType> types;
4550 for(int i=0;i<nbCells;i++,newConnIPtr++)
4552 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4553 if(cm.isQuadratic())
4554 {//assert(connI[i+1]-connI[i]-1==3)
4555 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4556 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4557 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4558 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4559 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4562 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4563 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4565 newConnIPtr[1]=(int)newConn.size();
4569 types.insert(INTERP_KERNEL::NORM_SEG2);
4570 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4571 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4572 newConnIPtr[1]=newConnIPtr[0]+3;
4577 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4578 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4579 newConnIPtr[1]=newConnIPtr[0]+3;
4582 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4585 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4586 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4587 newConnArr->alloc((int)newConn.size(),1);
4588 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4589 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4590 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4591 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4592 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4593 std::copy(addCoo.begin(),addCoo.end(),work);
4594 DataArrayDouble::SetArrayIn(newCoords,_coords);
4599 * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4600 * This cut into simplex is performed following the parameter \a policy. This method so typically increases the number of cells of \a this.
4601 * 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.
4602 * This method returns new2old newly allocated array that specifies a each cell of \a this after the call what was its id it comes.
4604 * The semantic of \a policy parameter :
4605 * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4606 * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4607 * - PLANAR_FACE_5 only HEXA8. All HEXA8 are split into 5 TETRA4
4608 * - PLANAR_FACE_6 only HEXA8. All HEXA8 are split into 6 TETRA4
4610 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4615 return simplexizePol0();
4617 return simplexizePol1();
4618 case (int) INTERP_KERNEL::PLANAR_FACE_5:
4619 return simplexizePlanarFace5();
4620 case (int) INTERP_KERNEL::PLANAR_FACE_6:
4621 return simplexizePlanarFace6();
4623 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)");
4627 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4629 checkFullyDefined();
4630 if(getMeshDimension()<1)
4631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4632 int nbCells=getNumberOfCells();
4633 const int *conn=_nodal_connec->getConstPointer();
4634 const int *connI=_nodal_connec_index->getConstPointer();
4635 for(int i=0;i<nbCells;i++)
4637 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4645 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4647 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4649 checkConnectivityFullyDefined();
4650 if(getMeshDimension()!=2)
4651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4652 int nbOfCells=getNumberOfCells();
4653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4654 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4655 ret->alloc(nbOfCells+nbOfCutCells,1);
4656 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4657 int *retPt=ret->getPointer();
4658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4660 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4661 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4662 int *pt=newConn->getPointer();
4663 int *ptI=newConnI->getPointer();
4665 const int *oldc=_nodal_connec->getConstPointer();
4666 const int *ci=_nodal_connec_index->getConstPointer();
4667 for(int i=0;i<nbOfCells;i++,ci++)
4669 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4671 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4672 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4673 pt=std::copy(tmp,tmp+8,pt);
4682 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4683 ptI[1]=ptI[0]+ci[1]-ci[0];
4688 _nodal_connec->decrRef();
4689 _nodal_connec=newConn.retn();
4690 _nodal_connec_index->decrRef();
4691 _nodal_connec_index=newConnI.retn();
4698 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4700 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4702 checkConnectivityFullyDefined();
4703 if(getMeshDimension()!=2)
4704 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4705 int nbOfCells=getNumberOfCells();
4706 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4707 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4708 ret->alloc(nbOfCells+nbOfCutCells,1);
4709 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4710 int *retPt=ret->getPointer();
4711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4713 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4714 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4715 int *pt=newConn->getPointer();
4716 int *ptI=newConnI->getPointer();
4718 const int *oldc=_nodal_connec->getConstPointer();
4719 const int *ci=_nodal_connec_index->getConstPointer();
4720 for(int i=0;i<nbOfCells;i++,ci++)
4722 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4724 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4725 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4726 pt=std::copy(tmp,tmp+8,pt);
4735 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4736 ptI[1]=ptI[0]+ci[1]-ci[0];
4741 _nodal_connec->decrRef();
4742 _nodal_connec=newConn.retn();
4743 _nodal_connec_index->decrRef();
4744 _nodal_connec_index=newConnI.retn();
4751 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4753 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
4755 checkConnectivityFullyDefined();
4756 if(getMeshDimension()!=3)
4757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
4758 int nbOfCells=getNumberOfCells();
4759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4760 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
4761 ret->alloc(nbOfCells+4*nbOfCutCells,1);
4762 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4763 int *retPt=ret->getPointer();
4764 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4766 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
4767 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
4768 int *pt=newConn->getPointer();
4769 int *ptI=newConnI->getPointer();
4771 const int *oldc=_nodal_connec->getConstPointer();
4772 const int *ci=_nodal_connec_index->getConstPointer();
4773 for(int i=0;i<nbOfCells;i++,ci++)
4775 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
4777 for(int j=0;j<5;j++,pt+=5,ptI++)
4779 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
4780 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];
4787 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4788 ptI[1]=ptI[0]+ci[1]-ci[0];
4793 _nodal_connec->decrRef();
4794 _nodal_connec=newConn.retn();
4795 _nodal_connec_index->decrRef();
4796 _nodal_connec_index=newConnI.retn();
4803 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4805 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
4807 checkConnectivityFullyDefined();
4808 if(getMeshDimension()!=3)
4809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
4810 int nbOfCells=getNumberOfCells();
4811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4812 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
4813 ret->alloc(nbOfCells+5*nbOfCutCells,1);
4814 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4815 int *retPt=ret->getPointer();
4816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4818 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
4819 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
4820 int *pt=newConn->getPointer();
4821 int *ptI=newConnI->getPointer();
4823 const int *oldc=_nodal_connec->getConstPointer();
4824 const int *ci=_nodal_connec_index->getConstPointer();
4825 for(int i=0;i<nbOfCells;i++,ci++)
4827 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
4829 for(int j=0;j<6;j++,pt+=5,ptI++)
4831 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
4832 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];
4839 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4840 ptI[1]=ptI[0]+ci[1]-ci[0];
4845 _nodal_connec->decrRef();
4846 _nodal_connec=newConn.retn();
4847 _nodal_connec_index->decrRef();
4848 _nodal_connec_index=newConnI.retn();
4855 * 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.
4856 * This method completly ignore coordinates.
4857 * @param nodeSubdived is the nodal connectivity of subdivision of edges
4858 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
4859 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4860 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4862 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
4864 checkFullyDefined();
4865 if(getMeshDimension()!=2)
4866 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
4867 int nbOfCells=getNumberOfCells();
4868 int *connI=_nodal_connec_index->getPointer();
4870 for(int i=0;i<nbOfCells;i++,connI++)
4872 int offset=descIndex[i];
4873 int nbOfEdges=descIndex[i+1]-offset;
4875 bool ddirect=desc[offset+nbOfEdges-1]>0;
4876 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
4877 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
4878 for(int j=0;j<nbOfEdges;j++)
4880 bool direct=desc[offset+j]>0;
4881 int edgeId=std::abs(desc[offset+j])-1;
4882 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
4884 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
4885 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
4886 int ref2=direct?id1:id2;
4889 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4890 newConnLgth+=nbOfSubNodes-1;
4895 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
4896 throw INTERP_KERNEL::Exception(oss.str().c_str());
4901 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
4904 newConnLgth++;//+1 is for cell type
4905 connI[1]=newConnLgth;
4908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4909 newConn->alloc(newConnLgth,1);
4910 int *work=newConn->getPointer();
4911 for(int i=0;i<nbOfCells;i++)
4913 *work++=INTERP_KERNEL::NORM_POLYGON;
4914 int offset=descIndex[i];
4915 int nbOfEdges=descIndex[i+1]-offset;
4916 for(int j=0;j<nbOfEdges;j++)
4918 bool direct=desc[offset+j]>0;
4919 int edgeId=std::abs(desc[offset+j])-1;
4921 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
4924 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4925 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
4926 work=std::copy(it,it+nbOfSubNodes-1,work);
4930 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
4933 _types.insert(INTERP_KERNEL::NORM_POLYGON);
4937 * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
4938 * nodal connectivity will be transform to a NORM_TRI3 cell.
4939 * This method works \b only \b on \b linear cells.
4940 * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
4941 * method could be usefull before calling this method in case of presence of several pair of nodes located on same position.
4942 * This method throws an exception if 'this' is not fully defined (connectivity).
4943 * 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.
4945 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
4947 checkFullyDefined();
4948 if(getMeshDimension()<=1)
4949 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4950 int nbOfCells=getNumberOfCells();
4953 int initMeshLgth=getMeshLength();
4954 int *conn=_nodal_connec->getPointer();
4955 int *index=_nodal_connec_index->getPointer();
4959 for(int i=0;i<nbOfCells;i++)
4961 lgthOfCurCell=index[i+1]-posOfCurCell;
4962 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4964 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4965 conn+newPos+1,newLgth);
4966 conn[newPos]=newType;
4968 posOfCurCell=index[i+1];
4971 if(newPos!=initMeshLgth)
4972 _nodal_connec->reAlloc(newPos);
4977 * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
4978 * The 'vec' vector has to have a non nul norm.
4979 * If not 'cells' parameter will be appended with cellIds of incorrect cells.
4980 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
4982 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
4984 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4985 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4986 int nbOfCells=getNumberOfCells();
4987 const int *conn=_nodal_connec->getConstPointer();
4988 const int *connI=_nodal_connec_index->getConstPointer();
4989 const double *coordsPtr=_coords->getConstPointer();
4990 for(int i=0;i<nbOfCells;i++)
4992 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4993 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4995 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4996 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5003 * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5004 * The 'vec' vector has to have a non nul norm.
5005 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5007 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5009 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5010 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5011 int nbOfCells=getNumberOfCells();
5012 int *conn=_nodal_connec->getPointer();
5013 const int *connI=_nodal_connec_index->getConstPointer();
5014 const double *coordsPtr=_coords->getConstPointer();
5015 bool isModified=false;
5016 for(int i=0;i<nbOfCells;i++)
5018 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5019 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5021 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5022 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5025 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5026 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5027 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5032 _nodal_connec->declareAsNew();
5037 * This method checks that all polyhedrons cells have correctly oriented faces.
5038 * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
5039 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
5041 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5043 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5044 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5045 int nbOfCells=getNumberOfCells();
5046 const int *conn=_nodal_connec->getConstPointer();
5047 const int *connI=_nodal_connec_index->getConstPointer();
5048 const double *coordsPtr=_coords->getConstPointer();
5049 for(int i=0;i<nbOfCells;i++)
5051 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5052 if(type==INTERP_KERNEL::NORM_POLYHED)
5054 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5061 * This method tries to orient correctly polhedrons cells.
5063 * \throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
5064 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5066 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5068 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5069 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5070 int nbOfCells=getNumberOfCells();
5071 int *conn=_nodal_connec->getPointer();
5072 const int *connI=_nodal_connec_index->getConstPointer();
5073 const double *coordsPtr=_coords->getConstPointer();
5074 for(int i=0;i<nbOfCells;i++)
5076 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5077 if(type==INTERP_KERNEL::NORM_POLYHED)
5081 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5082 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5084 catch(INTERP_KERNEL::Exception& e)
5086 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5087 throw INTERP_KERNEL::Exception(oss.str().c_str());
5095 * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
5096 * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
5097 * 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).
5098 * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
5100 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5101 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5103 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5105 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5106 if(getMeshDimension()!=3)
5107 throw INTERP_KERNEL::Exception(msg);
5108 int spaceDim=getSpaceDimension();
5110 throw INTERP_KERNEL::Exception(msg);
5112 int nbOfCells=getNumberOfCells();
5113 int *conn=_nodal_connec->getPointer();
5114 const int *connI=_nodal_connec_index->getConstPointer();
5115 const double *coo=getCoords()->getConstPointer();
5116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5117 for(int i=0;i<nbOfCells;i++)
5119 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5120 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5122 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5124 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5125 cells->pushBackSilent(i);
5129 return cells.retn();
5133 * This method is a faster method to correct orientation of all 3D cells in \a this.
5134 * 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.
5135 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5137 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5138 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5140 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5142 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5143 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5144 int nbOfCells=getNumberOfCells();
5145 int *conn=_nodal_connec->getPointer();
5146 const int *connI=_nodal_connec_index->getConstPointer();
5147 const double *coordsPtr=_coords->getConstPointer();
5148 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5149 for(int i=0;i<nbOfCells;i++)
5151 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5154 case INTERP_KERNEL::NORM_TETRA4:
5156 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5158 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5159 ret->pushBackSilent(i);
5163 case INTERP_KERNEL::NORM_PYRA5:
5165 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5167 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5168 ret->pushBackSilent(i);
5172 case INTERP_KERNEL::NORM_PENTA6:
5173 case INTERP_KERNEL::NORM_HEXA8:
5174 case INTERP_KERNEL::NORM_HEXGP12:
5176 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5178 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5179 ret->pushBackSilent(i);
5183 case INTERP_KERNEL::NORM_POLYHED:
5185 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5187 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5188 ret->pushBackSilent(i);
5193 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 !");
5201 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5202 * If it is not the case an exception will be thrown.
5203 * This method is fast because the first cell of 'this' is used to compute the plane.
5204 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5205 * @param pos output of size at least 3 used to store a point owned of searched plane.
5207 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5209 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5210 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5211 const int *conn=_nodal_connec->getConstPointer();
5212 const int *connI=_nodal_connec_index->getConstPointer();
5213 const double *coordsPtr=_coords->getConstPointer();
5214 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5215 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5219 * The returned newly created field has to be managed by the caller.
5220 * 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.
5221 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5222 * If a cell has an another type an exception will be thrown.
5224 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5227 int spaceDim=getSpaceDimension();
5228 int meshDim=getMeshDimension();
5229 if(spaceDim!=2 && spaceDim!=3)
5230 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5231 if(meshDim!=2 && meshDim!=3)
5232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5233 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5235 int nbOfCells=getNumberOfCells();
5236 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5237 arr->alloc(nbOfCells,1);
5238 double *pt=arr->getPointer();
5239 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5240 const int *conn=_nodal_connec->getConstPointer();
5241 const int *connI=_nodal_connec_index->getConstPointer();
5242 const double *coo=_coords->getConstPointer();
5244 for(int i=0;i<nbOfCells;i++,pt++)
5246 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5249 case INTERP_KERNEL::NORM_TRI3:
5251 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5252 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5255 case INTERP_KERNEL::NORM_QUAD4:
5257 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5258 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5261 case INTERP_KERNEL::NORM_TETRA4:
5263 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5264 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5270 conn+=connI[i+1]-connI[i];
5272 ret->setName("EdgeRatio");
5273 ret->synchronizeTimeWithSupport();
5278 * The returned newly created field has to be managed by the caller.
5279 * 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.
5280 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5281 * If a cell has an another type an exception will be thrown.
5283 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5286 int spaceDim=getSpaceDimension();
5287 int meshDim=getMeshDimension();
5288 if(spaceDim!=2 && spaceDim!=3)
5289 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5290 if(meshDim!=2 && meshDim!=3)
5291 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5292 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5294 int nbOfCells=getNumberOfCells();
5295 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5296 arr->alloc(nbOfCells,1);
5297 double *pt=arr->getPointer();
5298 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5299 const int *conn=_nodal_connec->getConstPointer();
5300 const int *connI=_nodal_connec_index->getConstPointer();
5301 const double *coo=_coords->getConstPointer();
5303 for(int i=0;i<nbOfCells;i++,pt++)
5305 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5308 case INTERP_KERNEL::NORM_TRI3:
5310 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5311 *pt=INTERP_KERNEL::triAspectRatio(tmp);
5314 case INTERP_KERNEL::NORM_QUAD4:
5316 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5317 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5320 case INTERP_KERNEL::NORM_TETRA4:
5322 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5323 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5327 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5329 conn+=connI[i+1]-connI[i];
5331 ret->setName("AspectRatio");
5332 ret->synchronizeTimeWithSupport();
5337 * The returned newly created field has to be managed by the caller.
5338 * 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.
5339 * This method for the moment only deals with NORM_QUAD4 geometric type.
5340 * If a cell has an another type an exception will be thrown.
5342 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
5345 int spaceDim=getSpaceDimension();
5346 int meshDim=getMeshDimension();
5348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5353 int nbOfCells=getNumberOfCells();
5354 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5355 arr->alloc(nbOfCells,1);
5356 double *pt=arr->getPointer();
5357 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5358 const int *conn=_nodal_connec->getConstPointer();
5359 const int *connI=_nodal_connec_index->getConstPointer();
5360 const double *coo=_coords->getConstPointer();
5362 for(int i=0;i<nbOfCells;i++,pt++)
5364 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5367 case INTERP_KERNEL::NORM_QUAD4:
5369 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5370 *pt=INTERP_KERNEL::quadWarp(tmp);
5374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5376 conn+=connI[i+1]-connI[i];
5378 ret->setName("Warp");
5379 ret->synchronizeTimeWithSupport();
5384 * The returned newly created field has to be managed by the caller.
5385 * 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.
5386 * This method for the moment only deals with NORM_QUAD4 geometric type.
5387 * If a cell has an another type an exception will be thrown.
5389 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5392 int spaceDim=getSpaceDimension();
5393 int meshDim=getMeshDimension();
5395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5397 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5398 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5400 int nbOfCells=getNumberOfCells();
5401 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5402 arr->alloc(nbOfCells,1);
5403 double *pt=arr->getPointer();
5404 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5405 const int *conn=_nodal_connec->getConstPointer();
5406 const int *connI=_nodal_connec_index->getConstPointer();
5407 const double *coo=_coords->getConstPointer();
5409 for(int i=0;i<nbOfCells;i++,pt++)
5411 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5414 case INTERP_KERNEL::NORM_QUAD4:
5416 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5417 *pt=INTERP_KERNEL::quadSkew(tmp);
5421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5423 conn+=connI[i+1]-connI[i];
5425 ret->setName("Skew");
5426 ret->synchronizeTimeWithSupport();
5431 * This method aggregate the bbox of each cell and put it into bbox parameter.
5432 * @param bbox out parameter of size 2*spacedim*nbOfcells.
5434 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5436 int spaceDim=getSpaceDimension();
5437 int nbOfCells=getNumberOfCells();
5438 bbox.resize(2*nbOfCells*spaceDim);
5439 for(int i=0;i<nbOfCells*spaceDim;i++)
5441 bbox[2*i]=std::numeric_limits<double>::max();
5442 bbox[2*i+1]=-std::numeric_limits<double>::max();
5444 const double *coordsPtr=_coords->getConstPointer();
5445 const int *conn=_nodal_connec->getConstPointer();
5446 const int *connI=_nodal_connec_index->getConstPointer();
5447 for(int i=0;i<nbOfCells;i++)
5449 int offset=connI[i]+1;
5450 int nbOfNodesForCell=connI[i+1]-offset;
5451 for(int j=0;j<nbOfNodesForCell;j++)
5453 int nodeId=conn[offset+j];
5455 for(int k=0;k<spaceDim;k++)
5457 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5458 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5466 namespace ParaMEDMEMImpl
5471 ConnReader(const int *c, int val):_conn(c),_val(val) { }
5472 bool operator() (const int& pos) { return _conn[pos]!=_val; }
5481 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5482 bool operator() (const int& pos) { return _conn[pos]==_val; }
5492 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5493 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5494 * 'this' is composed in cell types.
5495 * The returned array is of size 3*n where n is the number of different types present in 'this'.
5496 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
5497 * This parameter is kept only for compatibility with other methode listed above.
5499 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5501 checkConnectivityFullyDefined();
5502 const int *conn=_nodal_connec->getConstPointer();
5503 const int *connI=_nodal_connec_index->getConstPointer();
5504 const int *work=connI;
5505 int nbOfCells=getNumberOfCells();
5506 std::size_t n=getAllTypes().size();
5507 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5508 std::set<INTERP_KERNEL::NormalizedCellType> types;
5509 for(std::size_t i=0;work!=connI+nbOfCells;i++)
5511 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5512 if(types.find(typ)!=types.end())
5514 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5515 oss << " is not contiguous !";
5516 throw INTERP_KERNEL::Exception(oss.str().c_str());
5520 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5521 ret[3*i+1]=(int)std::distance(work,work2);
5528 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5529 * only for types cell, type node is not managed.
5530 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5531 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5532 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5533 * If 2 or more same geometric type is in 'code' and exception is thrown too.
5535 * This method firstly checks
5536 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5537 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5538 * an exception is thrown too.
5540 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5541 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
5542 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5544 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5547 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5548 std::size_t sz=code.size();
5551 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5552 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5554 for(std::size_t i=0;i<n;i++)
5555 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5557 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5559 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5560 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5563 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5564 if(idsPerType.empty())
5566 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5568 if(types.size()==_types.size())
5571 DataArrayInt *ret=DataArrayInt::New();
5573 int *retPtr=ret->getPointer();
5574 const int *connI=_nodal_connec_index->getConstPointer();
5575 const int *conn=_nodal_connec->getConstPointer();
5576 int nbOfCells=getNumberOfCells();
5579 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5581 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5582 int offset=(int)std::distance(connI,i);
5583 if(code[3*kk+2]==-1)
5585 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5586 std::size_t pos2=std::distance(i,j);
5587 for(std::size_t k=0;k<pos2;k++)
5588 *retPtr++=(int)k+offset;
5593 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5594 retPtr,std::bind2nd(std::plus<int>(),offset));
5601 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
5602 * 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.
5603 * 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.
5604 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
5606 * @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.
5607 * @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,
5608 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5609 * @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.
5610 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5611 * @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
5613 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5615 if(profile->getNumberOfComponents()!=1)
5616 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5617 checkConnectivityFullyDefined();
5618 const int *conn=_nodal_connec->getConstPointer();
5619 const int *connI=_nodal_connec_index->getConstPointer();
5620 int nbOfCells=getNumberOfCells();
5621 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5622 std::vector<int> typeRangeVals(1);
5623 for(const int *i=connI;i!=connI+nbOfCells;)
5625 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5626 if(std::find(types.begin(),types.end(),curType)!=types.end())
5628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5630 types.push_back(curType);
5631 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5632 typeRangeVals.push_back((int)std::distance(connI,i));
5635 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5636 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5641 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5642 code.resize(3*nbOfCastsFinal);
5643 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5644 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5645 for(int i=0;i<nbOfCastsFinal;i++)
5647 int castId=castsPresent->getIJ(i,0);
5648 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5649 idsInPflPerType2.push_back(tmp3);
5650 code[3*i]=(int)types[castId];
5651 code[3*i+1]=tmp3->getNumberOfTuples();
5652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5653 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5655 tmp4->copyStringInfoFrom(*profile);
5656 idsPerType2.push_back(tmp4);
5657 code[3*i+2]=(int)idsPerType2.size()-1;
5664 std::size_t sz2=idsInPflPerType2.size();
5665 idsInPflPerType.resize(sz2);
5666 for(std::size_t i=0;i<sz2;i++)
5668 DataArrayInt *locDa=idsInPflPerType2[i];
5670 idsInPflPerType[i]=locDa;
5672 std::size_t sz=idsPerType2.size();
5673 idsPerType.resize(sz);
5674 for(std::size_t i=0;i<sz;i++)
5676 DataArrayInt *locDa=idsPerType2[i];
5678 idsPerType[i]=locDa;
5683 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5684 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5685 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5686 * 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.
5688 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5690 checkFullyDefined();
5691 nM1LevMesh->checkFullyDefined();
5692 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5693 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5694 if(_coords!=nM1LevMesh->getCoords())
5695 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5698 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5700 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5701 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5702 tmp->setConnectivity(tmp0,tmp1);
5703 tmp->renumberCells(ret0->getConstPointer(),false);
5704 revDesc=tmp->getNodalConnectivity();
5705 revDescIndx=tmp->getNodalConnectivityIndex();
5706 DataArrayInt *ret=0;
5707 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5710 ret->getMaxValue(tmp2);
5712 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5713 throw INTERP_KERNEL::Exception(oss.str().c_str());
5718 revDescIndx->incrRef();
5721 meshnM1Old2New=ret0;
5726 * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5727 * It avoids to deal with renum in MEDLoader so it is usefull for MED file R/W with multi types.
5728 * This method returns a newly allocated array old2New.
5729 * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5731 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5733 checkConnectivityFullyDefined();
5734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5735 renumberCells(ret->getConstPointer(),false);
5740 * This methods checks that cells are sorted by their types.
5741 * This method makes asumption (no check) that connectivity is correctly set before calling.
5743 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5745 checkFullyDefined();
5746 const int *conn=_nodal_connec->getConstPointer();
5747 const int *connI=_nodal_connec_index->getConstPointer();
5748 int nbOfCells=getNumberOfCells();
5749 std::set<INTERP_KERNEL::NormalizedCellType> types;
5750 for(const int *i=connI;i!=connI+nbOfCells;)
5752 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5753 if(types.find(curType)!=types.end())
5755 types.insert(curType);
5756 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5762 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5763 * The geometric type order is specified by MED file.
5765 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5767 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
5769 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5773 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5774 * that the order is specified in array defined by [orderBg,orderEnd).
5776 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5778 checkFullyDefined();
5779 const int *conn=_nodal_connec->getConstPointer();
5780 const int *connI=_nodal_connec_index->getConstPointer();
5781 int nbOfCells=getNumberOfCells();
5783 for(const int *i=connI;i!=connI+nbOfCells;)
5785 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5786 int pos=(int)std::distance(orderBg,std::find(orderBg,orderEnd,curType));
5790 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5796 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5797 * 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
5798 * 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'.
5800 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
5802 checkConnectivityFullyDefined();
5803 int nbOfCells=getNumberOfCells();
5804 const int *conn=_nodal_connec->getConstPointer();
5805 const int *connI=_nodal_connec_index->getConstPointer();
5806 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
5807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
5808 tmpa->alloc(nbOfCells,1);
5809 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5810 tmpb->fillWithZero();
5811 int *tmp=tmpa->getPointer();
5812 int *tmp2=tmpb->getPointer();
5813 for(const int *i=connI;i!=connI+nbOfCells;i++)
5815 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5818 int pos=(int)std::distance(orderBg,where);
5820 tmp[std::distance(connI,i)]=pos;
5824 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5825 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5826 oss << " has a type " << cm.getRepr() << " not in input array of type !";
5827 throw INTERP_KERNEL::Exception(oss.str().c_str());
5830 nbPerType=tmpb.retn();
5835 * 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'.
5836 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5837 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5838 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5840 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
5842 DataArrayInt *nbPerType=0;
5843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5844 nbPerType->decrRef();
5845 return tmpa->buildPermArrPerLevel();
5849 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
5850 * The number of cells remains unchanged after the call of this method.
5851 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5852 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5854 * @return the array giving the correspondance old to new.
5856 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5858 checkFullyDefined();
5860 const int *conn=_nodal_connec->getConstPointer();
5861 const int *connI=_nodal_connec_index->getConstPointer();
5862 int nbOfCells=getNumberOfCells();
5863 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5864 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5865 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5867 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5868 types.push_back(curType);
5869 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5871 DataArrayInt *ret=DataArrayInt::New();
5872 ret->alloc(nbOfCells,1);
5873 int *retPtr=ret->getPointer();
5874 std::fill(retPtr,retPtr+nbOfCells,-1);
5876 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5878 for(const int *i=connI;i!=connI+nbOfCells;i++)
5879 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5880 retPtr[std::distance(connI,i)]=newCellId++;
5882 renumberCells(retPtr,false);
5887 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
5888 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5889 * This method makes asumption that connectivity is correctly set before calling.
5891 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5893 checkFullyDefined();
5894 const int *conn=_nodal_connec->getConstPointer();
5895 const int *connI=_nodal_connec_index->getConstPointer();
5896 int nbOfCells=getNumberOfCells();
5897 std::vector<MEDCouplingUMesh *> ret;
5898 for(const int *i=connI;i!=connI+nbOfCells;)
5900 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5901 int beginCellId=(int)std::distance(connI,i);
5902 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5903 int endCellId=(int)std::distance(connI,i);
5904 int sz=endCellId-beginCellId;
5905 int *cells=new int[sz];
5906 for(int j=0;j<sz;j++)
5907 cells[j]=beginCellId+j;
5908 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
5916 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
5917 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
5918 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
5919 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
5920 * are not used here to avoid the build of big permutation array.
5922 * \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
5923 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5924 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
5925 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
5926 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
5927 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
5928 * \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
5929 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5931 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
5932 DataArrayInt *&szOfCellGrpOfSameType,
5933 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
5935 std::vector<const MEDCouplingUMesh *> ms2;
5936 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5939 (*it)->checkConnectivityFullyDefined();
5943 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
5944 const DataArrayDouble *refCoo=ms2[0]->getCoords();
5945 int meshDim=ms2[0]->getMeshDimension();
5946 std::vector<const MEDCouplingUMesh *> m1ssm;
5947 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
5949 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
5950 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
5952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
5953 ret1->alloc(0,1); ret2->alloc(0,1);
5954 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
5956 if(meshDim!=(*it)->getMeshDimension())
5957 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
5958 if(refCoo!=(*it)->getCoords())
5959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
5960 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
5961 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
5962 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
5963 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
5965 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
5966 m1ssmSingleAuto.push_back(singleCell);
5967 m1ssmSingle.push_back(singleCell);
5968 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
5971 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
5972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
5973 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
5974 for(std::size_t i=0;i<m1ssm.size();i++)
5975 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
5976 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
5977 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
5978 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
5983 * This method returns a newly created DataArrayInt instance.
5984 * This method retrieves cell ids in [begin,end) that have the type 'type'.
5986 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
5988 checkFullyDefined();
5989 const int *conn=_nodal_connec->getConstPointer();
5990 const int *connIndex=_nodal_connec_index->getConstPointer();
5991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5992 for(const int *w=begin;w!=end;w++)
5993 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
5994 ret->pushBackSilent(*w);
5999 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6000 * are in [0:getNumberOfCells())
6002 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6004 checkFullyDefined();
6005 const int *conn=_nodal_connec->getConstPointer();
6006 const int *connI=_nodal_connec_index->getConstPointer();
6007 int nbOfCells=getNumberOfCells();
6008 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6009 int *tmp=new int[nbOfCells];
6010 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6013 for(const int *i=connI;i!=connI+nbOfCells;i++)
6014 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6015 tmp[std::distance(connI,i)]=j++;
6017 DataArrayInt *ret=DataArrayInt::New();
6018 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6019 ret->copyStringInfoFrom(*da);
6020 int *retPtr=ret->getPointer();
6021 const int *daPtr=da->getConstPointer();
6022 int nbOfElems=da->getNbOfElems();
6023 for(int k=0;k<nbOfElems;k++)
6024 retPtr[k]=tmp[daPtr[k]];
6030 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6031 * This method \b works \b for mesh sorted by type.
6032 * cells whose ids is in 'idsPerGeoType' array.
6033 * This method conserves coords and name of mesh.
6035 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6037 std::vector<int> code=getDistributionOfTypes();
6038 std::size_t nOfTypesInThis=code.size()/3;
6039 int sz=0,szOfType=0;
6040 for(std::size_t i=0;i<nOfTypesInThis;i++)
6045 szOfType=code[3*i+1];
6047 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6048 if(*work<0 || *work>=szOfType)
6050 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6051 oss << ". It should be in [0," << szOfType << ") !";
6052 throw INTERP_KERNEL::Exception(oss.str().c_str());
6054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6055 int *idsPtr=idsTokeep->getPointer();
6057 for(std::size_t i=0;i<nOfTypesInThis;i++)
6060 for(int j=0;j<code[3*i+1];j++)
6063 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6064 offset+=code[3*i+1];
6066 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6067 ret->copyTinyInfoFrom(this);
6072 * This method returns a vector of size 'this->getNumberOfCells()'.
6073 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
6075 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6077 int ncell=getNumberOfCells();
6078 std::vector<bool> ret(ncell);
6079 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6080 const int *c=getNodalConnectivity()->getConstPointer();
6081 for(int i=0;i<ncell;i++)
6083 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6084 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6085 ret[i]=cm.isQuadratic();
6091 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
6093 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6095 if(other->getType()!=UNSTRUCTURED)
6096 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6097 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6098 return MergeUMeshes(this,otherC);
6102 * Returns an array with this->getNumberOfCells() tuples and this->getSpaceDimension() dimension.
6103 * The false barycenter is computed that is to say barycenter of a cell is computed using average on each
6104 * components of coordinates of the cell.
6106 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6108 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6109 int spaceDim=getSpaceDimension();
6110 int nbOfCells=getNumberOfCells();
6111 ret->alloc(nbOfCells,spaceDim);
6112 ret->copyStringInfoFrom(*getCoords());
6113 double *ptToFill=ret->getPointer();
6114 const int *nodal=_nodal_connec->getConstPointer();
6115 const int *nodalI=_nodal_connec_index->getConstPointer();
6116 const double *coor=_coords->getConstPointer();
6117 for(int i=0;i<nbOfCells;i++)
6119 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6120 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6127 * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
6128 * 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().
6129 * No check of that will be done !
6131 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6133 DataArrayDouble *ret=DataArrayDouble::New();
6134 int spaceDim=getSpaceDimension();
6135 int nbOfTuple=(int)std::distance(begin,end);
6136 ret->alloc(nbOfTuple,spaceDim);
6137 double *ptToFill=ret->getPointer();
6138 double *tmp=new double[spaceDim];
6139 const int *nodal=_nodal_connec->getConstPointer();
6140 const int *nodalI=_nodal_connec_index->getConstPointer();
6141 const double *coor=_coords->getConstPointer();
6142 for(const int *w=begin;w!=end;w++)
6144 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6145 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6153 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6156 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
6159 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6160 da->checkAllocated();
6161 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
6163 int nbOfTuples=da->getNumberOfTuples();
6164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6166 c->alloc(2*nbOfTuples,1);
6167 cI->alloc(nbOfTuples+1,1);
6168 int *cp=c->getPointer();
6169 int *cip=cI->getPointer();
6171 for(int i=0;i<nbOfTuples;i++)
6173 *cp++=INTERP_KERNEL::NORM_POINT1;
6177 ret->setConnectivity(c,cI,true);
6182 * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
6183 * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
6185 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6187 std::vector<const MEDCouplingUMesh *> tmp(2);
6188 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6189 return MergeUMeshes(tmp);
6193 * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
6194 * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
6195 * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
6196 * cells in meshes in 'a' (in the same order too).
6198 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6200 std::size_t sz=a.size();
6202 return MergeUMeshesLL(a);
6203 for(std::size_t ii=0;ii<sz;ii++)
6206 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6207 throw INTERP_KERNEL::Exception(oss.str().c_str());
6209 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
6210 std::vector< const MEDCouplingUMesh * > aa(sz);
6212 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6214 const MEDCouplingUMesh *cur=a[i];
6215 const DataArrayDouble *coo=cur->getCoords();
6217 spaceDim=coo->getNumberOfComponents();
6220 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6221 for(std::size_t i=0;i<sz;i++)
6223 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6226 return MergeUMeshesLL(aa);
6231 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
6235 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
6236 int meshDim=(*it)->getMeshDimension();
6237 int nbOfCells=(*it)->getNumberOfCells();
6238 int meshLgth=(*it++)->getMeshLength();
6239 for(;it!=a.end();it++)
6241 if(meshDim!=(*it)->getMeshDimension())
6242 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
6243 nbOfCells+=(*it)->getNumberOfCells();
6244 meshLgth+=(*it)->getMeshLength();
6246 std::vector<const MEDCouplingPointSet *> aps(a.size());
6247 std::copy(a.begin(),a.end(),aps.begin());
6248 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
6249 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
6250 ret->setCoords(pts);
6251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6252 c->alloc(meshLgth,1);
6253 int *cPtr=c->getPointer();
6254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6255 cI->alloc(nbOfCells+1,1);
6256 int *cIPtr=cI->getPointer();
6260 for(it=a.begin();it!=a.end();it++)
6262 int curNbOfCell=(*it)->getNumberOfCells();
6263 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
6264 const int *curC=(*it)->_nodal_connec->getConstPointer();
6265 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
6266 for(int j=0;j<curNbOfCell;j++)
6268 const int *src=curC+curCI[j];
6270 for(;src!=curC+curCI[j+1];src++,cPtr++)
6278 offset+=curCI[curNbOfCell];
6279 offset2+=(*it)->getNumberOfNodes();
6282 ret->setConnectivity(c,cI,true);
6289 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6290 * 'meshes' must be a non empty vector.
6292 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6294 std::vector<const MEDCouplingUMesh *> tmp(2);
6295 tmp[0]=mesh1; tmp[1]=mesh2;
6296 return MergeUMeshesOnSameCoords(tmp);
6300 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6301 * 'meshes' must be a non empty vector.
6303 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6306 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6307 for(std::size_t ii=0;ii<meshes.size();ii++)
6310 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6311 throw INTERP_KERNEL::Exception(oss.str().c_str());
6313 const DataArrayDouble *coords=meshes.front()->getCoords();
6314 int meshDim=meshes.front()->getMeshDimension();
6315 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6317 int meshIndexLgth=0;
6318 for(;iter!=meshes.end();iter++)
6320 if(coords!=(*iter)->getCoords())
6321 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6322 if(meshDim!=(*iter)->getMeshDimension())
6323 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6324 meshLgth+=(*iter)->getMeshLength();
6325 meshIndexLgth+=(*iter)->getNumberOfCells();
6327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
6328 nodal->alloc(meshLgth,1);
6329 int *nodalPtr=nodal->getPointer();
6330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
6331 nodalIndex->alloc(meshIndexLgth+1,1);
6332 int *nodalIndexPtr=nodalIndex->getPointer();
6334 for(iter=meshes.begin();iter!=meshes.end();iter++)
6336 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
6337 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
6338 int nbOfCells=(*iter)->getNumberOfCells();
6339 int meshLgth2=(*iter)->getMeshLength();
6340 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6341 if(iter!=meshes.begin())
6342 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6344 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6347 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6348 ret->setName("merge");
6349 ret->setMeshDimension(meshDim);
6350 ret->setConnectivity(nodal,nodalIndex,true);
6351 ret->setCoords(coords);
6356 * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
6357 * 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)
6359 * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
6360 * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
6361 * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
6362 * The arrays contained in 'corr' parameter are returned with refcounter set to one.
6363 * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
6364 * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
6365 * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
6367 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6369 //All checks are delegated to MergeUMeshesOnSameCoords
6370 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6372 corr.resize(meshes.size());
6373 std::size_t nbOfMeshes=meshes.size();
6375 const int *o2nPtr=o2n->getConstPointer();
6376 for(std::size_t i=0;i<nbOfMeshes;i++)
6378 DataArrayInt *tmp=DataArrayInt::New();
6379 int curNbOfCells=meshes[i]->getNumberOfCells();
6380 tmp->alloc(curNbOfCells,1);
6381 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6382 offset+=curNbOfCells;
6383 tmp->setName(meshes[i]->getName());
6390 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6391 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6392 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6393 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6395 * This method performs nothing if size of \b meshes is in [0,1].
6396 * This method is particulary usefull in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6397 * coordinates DataArrayDouble instance.
6399 * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6401 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6403 std::size_t sz=meshes.size();
6406 std::vector< const DataArrayDouble * > coords(meshes.size());
6407 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6408 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6412 (*it)->checkConnectivityFullyDefined();
6413 const DataArrayDouble *coo=(*it)->getCoords();
6418 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6419 oss << " has no coordinate array defined !";
6420 throw INTERP_KERNEL::Exception(oss.str().c_str());
6425 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6426 oss << " is null !";
6427 throw INTERP_KERNEL::Exception(oss.str().c_str());
6430 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6431 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6432 int offset=(*it)->getNumberOfNodes();
6433 (*it++)->setCoords(res);
6434 for(;it!=meshes.end();it++)
6436 int oldNumberOfNodes=(*it)->getNumberOfNodes();
6437 (*it)->setCoords(res);
6438 (*it)->shiftNodeNumbersInConn(offset);
6439 offset+=oldNumberOfNodes;
6444 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6445 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6446 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6447 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6448 * 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.
6450 * This method performs nothing if size of \b meshes is empty.
6451 * This method is particulary usefull in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6452 * coordinates DataArrayDouble instance.
6454 * \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.
6455 * \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.
6457 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6461 std::set<const DataArrayDouble *> s;
6462 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6465 s.insert((*it)->getCoords());
6468 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 !";
6469 throw INTERP_KERNEL::Exception(oss.str().c_str());
6474 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 !";
6475 throw INTERP_KERNEL::Exception(oss.str().c_str());
6477 const DataArrayDouble *coo=*(s.begin());
6481 DataArrayInt *comm,*commI;
6482 coo->findCommonTuples(eps,-1,comm,commI);
6483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6484 int oldNbOfNodes=coo->getNumberOfTuples();
6486 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6487 if(oldNbOfNodes==newNbOfNodes)
6489 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6490 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6492 (*it)->renumberNodesInConn(o2n->getConstPointer());
6493 (*it)->setCoords(newCoords);
6498 * 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.
6499 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6500 * @param isQuad specifies the policy of connectivity.
6501 * @ret in/out parameter in which the result will be append
6503 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6505 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6506 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6507 ret.push_back(cm.getExtrudedType());
6508 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6511 case INTERP_KERNEL::NORM_POINT1:
6513 ret.push_back(connBg[1]);
6514 ret.push_back(connBg[1]+nbOfNodesPerLev);
6517 case INTERP_KERNEL::NORM_SEG2:
6519 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6520 ret.insert(ret.end(),conn,conn+4);
6523 case INTERP_KERNEL::NORM_SEG3:
6525 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6526 ret.insert(ret.end(),conn,conn+8);
6529 case INTERP_KERNEL::NORM_QUAD4:
6531 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6532 ret.insert(ret.end(),conn,conn+8);
6535 case INTERP_KERNEL::NORM_TRI3:
6537 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6538 ret.insert(ret.end(),conn,conn+6);
6541 case INTERP_KERNEL::NORM_TRI6:
6543 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,
6544 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6545 ret.insert(ret.end(),conn,conn+15);
6548 case INTERP_KERNEL::NORM_QUAD8:
6551 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6552 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6553 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6555 ret.insert(ret.end(),conn,conn+20);
6558 case INTERP_KERNEL::NORM_POLYGON:
6560 std::back_insert_iterator< std::vector<int> > ii(ret);
6561 std::copy(connBg+1,connEnd,ii);
6563 std::reverse_iterator<const int *> rConnBg(connEnd);
6564 std::reverse_iterator<const int *> rConnEnd(connBg+1);
6565 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6566 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6567 for(std::size_t i=0;i<nbOfRadFaces;i++)
6570 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6571 std::copy(conn,conn+4,ii);
6576 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6581 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6583 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6585 double v[3]={0.,0.,0.};
6586 std::size_t sz=std::distance(begin,end);
6589 for(std::size_t i=0;i<sz;i++)
6591 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];
6592 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6593 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6595 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6599 * The polyhedron is specfied by its connectivity nodes in [begin,end).
6601 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6603 std::vector<std::pair<int,int> > edges;
6604 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6605 const int *bgFace=begin;
6606 for(std::size_t i=0;i<nbOfFaces;i++)
6608 const int *endFace=std::find(bgFace+1,end,-1);
6609 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6610 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6612 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6613 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6615 edges.push_back(p1);
6619 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6623 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
6625 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6627 double vec0[3],vec1[3];
6628 std::size_t sz=std::distance(begin,end);
6630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6631 int nbOfNodes=(int)sz/2;
6632 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6633 const double *pt0=coords+3*begin[0];
6634 const double *pt1=coords+3*begin[nbOfNodes];
6635 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6636 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6639 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6641 std::size_t sz=std::distance(begin,end);
6642 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6643 std::size_t nbOfNodes(sz/2);
6644 std::copy(begin,end,(int *)tmp);
6645 for(std::size_t j=1;j<nbOfNodes;j++)
6647 begin[j]=tmp[nbOfNodes-j];
6648 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6652 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6654 std::size_t sz=std::distance(begin,end);
6656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
6657 double vec0[3],vec1[3];
6658 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6659 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];
6660 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;
6663 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
6665 std::size_t sz=std::distance(begin,end);
6667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
6669 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
6670 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
6671 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
6675 * 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)
6676 * 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
6679 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6680 * \param [in] coords the coordinates with nb of components exactly equal to 3
6681 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6682 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6683 * \param [out] res the result is put at the end of the vector without any alteration of the data.
6685 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
6687 int nbFaces=std::count(begin+1,end,-1)+1;
6688 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6689 double *vPtr=v->getPointer();
6690 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6691 double *pPtr=p->getPointer();
6692 const int *stFaceConn=begin+1;
6693 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6695 const int *endFaceConn=std::find(stFaceConn,end,-1);
6696 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
6697 stFaceConn=endFaceConn+1;
6699 pPtr=p->getPointer(); vPtr=v->getPointer();
6700 DataArrayInt *comm1=0,*commI1=0;
6701 v->findCommonTuples(eps,-1,comm1,commI1);
6702 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6703 const int *comm1Ptr=comm1->getConstPointer();
6704 const int *commI1Ptr=commI1->getConstPointer();
6705 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6706 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
6708 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
6709 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
6710 mm->finishInsertingCells();
6712 for(int i=0;i<nbOfGrps1;i++)
6714 int vecId=comm1Ptr[commI1Ptr[i]];
6715 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6716 DataArrayInt *comm2=0,*commI2=0;
6717 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
6718 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
6719 const int *comm2Ptr=comm2->getConstPointer();
6720 const int *commI2Ptr=commI2->getConstPointer();
6721 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
6722 for(int j=0;j<nbOfGrps2;j++)
6724 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
6726 res->insertAtTheEnd(begin,end);
6727 res->pushBackSilent(-1);
6731 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
6732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
6733 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6734 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
6735 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
6736 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
6737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
6738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
6739 const int *idsNodePtr=idsNode->getConstPointer();
6740 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];
6741 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
6742 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
6743 if(std::abs(norm)>eps)
6745 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
6746 mm3->rotate(center,vec,angle);
6748 mm3->changeSpaceDimension(2);
6749 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
6750 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
6751 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
6752 int nbOfCells=mm4->getNumberOfCells();
6753 for(int k=0;k<nbOfCells;k++)
6756 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
6757 res->pushBackSilent(idsNodePtr[*work]);
6758 res->pushBackSilent(-1);
6763 res->popBackSilent();
6767 * 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
6768 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
6770 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
6771 * \param [in] coords coordinates expected to have 3 components.
6772 * \param [in] begin start of the nodal connectivity of the face.
6773 * \param [in] end end of the nodal connectivity (excluded) of the face.
6774 * \param [out] v the normalized vector of size 3
6775 * \param [out] p the pos of plane
6777 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
6779 std::size_t nbPoints=std::distance(begin,end);
6781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
6784 bool refFound=false;
6785 for(;j<nbPoints-1 && !refFound;j++)
6787 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
6788 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
6789 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
6790 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
6794 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
6797 for(std::size_t i=j;i<nbPoints-1;i++)
6800 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
6801 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
6802 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
6803 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
6806 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
6807 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];
6808 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
6811 v[0]/=norm; v[1]/=norm; v[2]/=norm;
6812 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
6816 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
6820 * This method tries to obtain a well oriented polyhedron.
6821 * If the algorithm fails, an exception will be thrown.
6823 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
6825 std::list< std::pair<int,int> > edgesOK,edgesFinished;
6826 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6827 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
6829 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
6830 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6831 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
6833 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
6836 std::size_t smthChanged=0;
6837 for(std::size_t i=0;i<nbOfFaces;i++)
6839 endFace=std::find(bgFace+1,end,-1);
6840 nbOfEdgesInFace=std::distance(bgFace,endFace);
6844 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6846 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6847 std::pair<int,int> p2(p1.second,p1.first);
6848 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
6849 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
6850 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
6855 std::reverse(bgFace+1,endFace);
6856 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6858 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6859 std::pair<int,int> p2(p1.second,p1.first);
6860 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
6861 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
6862 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
6863 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
6864 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
6865 if(it!=edgesOK.end())
6868 edgesFinished.push_back(p1);
6871 edgesOK.push_back(p1);
6878 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
6880 if(!edgesOK.empty())
6881 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
6882 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
6883 {//not lucky ! The first face was not correctly oriented : reorient all faces...
6885 for(std::size_t i=0;i<nbOfFaces;i++)
6887 endFace=std::find(bgFace+1,end,-1);
6888 std::reverse(bgFace+1,endFace);
6895 * This method makes the assumption spacedimension == meshdimension == 2.
6896 * This method works only for linear cells.
6898 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
6900 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
6902 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
6903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
6904 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
6906 int nbOfNodesExpected=m->getNumberOfNodes();
6907 if(m->getNumberOfCells()!=nbOfNodesExpected)
6908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
6909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
6910 const int *n2oPtr=n2o->getConstPointer();
6911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
6912 m->getReverseNodalConnectivity(revNodal,revNodalI);
6913 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
6914 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
6915 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
6916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
6917 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
6918 if(nbOfNodesExpected<1)
6921 int prevNode=nodalPtr[nodalIPtr[0]+1];
6922 *work++=n2oPtr[prevNode];
6923 for(int i=1;i<nbOfNodesExpected;i++)
6925 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
6927 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
6928 conn.erase(prevNode);
6931 int curNode=*(conn.begin());
6932 *work++=n2oPtr[curNode];
6933 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
6934 shar.erase(prevCell);
6937 prevCell=*(shar.begin());
6941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
6944 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
6947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
6953 * This method makes the assumption spacedimension == meshdimension == 3.
6954 * This method works only for linear cells.
6956 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
6958 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
6960 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
6962 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6963 const int *conn=m->getNodalConnectivity()->getConstPointer();
6964 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
6965 int nbOfCells=m->getNumberOfCells();
6966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
6967 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
6970 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
6971 for(int i=1;i<nbOfCells;i++)
6974 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
6980 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
6981 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
6983 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
6987 for(int i=0;i<nbOfNodesInCell;i++)
6988 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
6989 else if(spaceDim==2)
6991 for(int i=0;i<nbOfNodesInCell;i++)
6993 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
6998 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7001 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7003 int nbOfCells=getNumberOfCells();
7005 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7006 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};
7007 ofs << " <" << getVTKDataSetType() << ">\n";
7008 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7009 ofs << " <PointData>\n" << pointData << std::endl;
7010 ofs << " </PointData>\n";
7011 ofs << " <CellData>\n" << cellData << std::endl;
7012 ofs << " </CellData>\n";
7013 ofs << " <Points>\n";
7014 if(getSpaceDimension()==3)
7015 _coords->writeVTK(ofs,8,"Points");
7018 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7019 coo->writeVTK(ofs,8,"Points");
7021 ofs << " </Points>\n";
7022 ofs << " <Cells>\n";
7023 const int *cPtr=_nodal_connec->getConstPointer();
7024 const int *cIPtr=_nodal_connec_index->getConstPointer();
7025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7027 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7028 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7029 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7030 int szFaceOffsets=0,szConn=0;
7031 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7034 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7037 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7038 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7042 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7043 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7044 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7045 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7046 w4=std::copy(c.begin(),c.end(),w4);
7049 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
7050 types->writeVTK(ofs,8,"UInt8","types");
7051 offsets->writeVTK(ofs,8,"Int32","offsets");
7052 if(szFaceOffsets!=0)
7053 {//presence of Polyhedra
7054 connectivity->reAlloc(szConn);
7055 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
7056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7057 w1=faces->getPointer();
7058 for(int i=0;i<nbOfCells;i++)
7059 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7061 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7063 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7064 for(int j=0;j<nbFaces;j++)
7066 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7067 *w1++=(int)std::distance(w6,w5);
7068 w1=std::copy(w6,w5,w1);
7072 faces->writeVTK(ofs,8,"Int32","faces");
7074 connectivity->writeVTK(ofs,8,"Int32","connectivity");
7075 ofs << " </Cells>\n";
7076 ofs << " </Piece>\n";
7077 ofs << " </" << getVTKDataSetType() << ">\n";
7080 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
7082 return std::string("UnstructuredGrid");
7087 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
7089 m1->checkFullyDefined();
7090 m2->checkFullyDefined();
7091 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
7092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
7093 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
7094 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
7095 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
7096 std::vector<double> addCoo,addCoordsQuadratic;
7097 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
7098 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
7099 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
7100 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
7101 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
7102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
7103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
7104 std::vector< std::vector<int> > intersectEdge2;
7105 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
7106 subDiv2.clear(); dd5=0; dd6=0;
7107 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
7108 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
7109 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
7110 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
7112 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
7113 addCooDa->alloc((int)(addCoo.size())/2,2);
7114 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
7115 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
7116 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
7117 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
7118 std::vector<const DataArrayDouble *> coordss(4);
7119 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
7120 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
7121 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
7122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
7123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
7124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
7125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
7126 ret->setConnectivity(conn,connI,true);
7127 ret->setCoords(coo);
7128 cellNb1=c1.retn(); cellNb2=c2.retn();
7134 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
7135 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
7136 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
7137 const std::vector<double>& addCoords,
7138 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
7140 static const int SPACEDIM=2;
7141 std::vector<double> bbox1,bbox2;
7142 const double *coo1=m1->getCoords()->getConstPointer();
7143 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
7144 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
7145 int offset1=m1->getNumberOfNodes();
7146 const double *coo2=m2->getCoords()->getConstPointer();
7147 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
7148 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
7149 int offset2=offset1+m2->getNumberOfNodes();
7150 int offset3=offset2+((int)addCoords.size())/2;
7151 m1->getBoundingBoxForBBTree(bbox1);
7152 m2->getBoundingBoxForBBTree(bbox2);
7153 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
7154 int ncell1=m1->getNumberOfCells();
7156 for(int i=0;i<ncell1;i++)
7158 std::vector<int> candidates2;
7159 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7160 std::map<INTERP_KERNEL::Node *,int> mapp;
7161 std::map<int,INTERP_KERNEL::Node *> mappRev;
7162 INTERP_KERNEL::QuadraticPolygon pol1;
7163 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
7164 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7165 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
7166 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
7167 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
7169 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
7170 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
7171 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
7172 for(it1.first();!it1.finished();it1.next())
7173 edges1.insert(it1.current()->getPtr());
7175 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
7176 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
7178 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7180 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
7181 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
7182 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
7183 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
7184 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
7187 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7189 pol1.initLocationsWithOther(pol2s[ii]);
7190 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
7191 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
7192 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7198 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7200 catch(INTERP_KERNEL::Exception& e)
7202 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();
7203 throw INTERP_KERNEL::Exception(oss.str().c_str());
7206 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
7207 (*it).second->decrRef();
7212 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
7215 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
7216 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
7217 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
7218 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
7219 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
7221 static const int SPACEDIM=2;
7222 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
7223 desc2=DataArrayInt::New();
7224 descIndx2=DataArrayInt::New();
7225 revDesc2=DataArrayInt::New();
7226 revDescIndx2=DataArrayInt::New();
7227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
7228 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
7229 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
7230 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
7231 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
7232 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
7233 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
7234 std::vector<double> bbox1,bbox2;
7235 m1Desc->getBoundingBoxForBBTree(bbox1);
7236 m2Desc->getBoundingBoxForBBTree(bbox2);
7237 int ncell1=m1Desc->getNumberOfCells();
7238 int ncell2=m2Desc->getNumberOfCells();
7239 intersectEdge1.resize(ncell1);
7240 colinear2.resize(ncell2);
7241 subDiv2.resize(ncell2);
7242 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
7243 std::vector<int> candidates1(1);
7244 int offset1=m1->getNumberOfNodes();
7245 int offset2=offset1+m2->getNumberOfNodes();
7246 for(int i=0;i<ncell1;i++)
7248 std::vector<int> candidates2;
7249 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7250 if(!candidates2.empty())
7252 std::map<INTERP_KERNEL::Node *,int> map1,map2;
7253 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
7255 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
7256 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
7261 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
7263 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
7264 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
7268 * This method performs the 2nd step of Partition of 2D mesh.
7269 * This method has 4 inputs :
7270 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
7271 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
7272 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
7273 * 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'
7274 * @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'
7275 * @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.
7276 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
7278 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)
7280 int offset1=m1->getNumberOfNodes();
7281 int ncell=m2->getNumberOfCells();
7282 const int *c=m2->getNodalConnectivity()->getConstPointer();
7283 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
7284 const double *coo=m2->getCoords()->getConstPointer();
7285 const double *cooBis=m1->getCoords()->getConstPointer();
7286 int offset2=offset1+m2->getNumberOfNodes();
7287 intersectEdge.resize(ncell);
7288 for(int i=0;i<ncell;i++,cI++)
7290 const std::vector<int>& divs=subDiv[i];
7291 int nnode=cI[1]-cI[0]-1;
7292 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
7293 std::map<INTERP_KERNEL::Node *, int> mapp22;
7294 for(int j=0;j<nnode;j++)
7296 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
7297 int nnid=c[(*cI)+j+1];
7298 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
7299 mapp22[nn]=nnid+offset1;
7301 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
7302 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
7303 ((*it).second.first)->decrRef();
7304 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
7305 std::map<INTERP_KERNEL::Node *,int> mapp3;
7306 for(std::size_t j=0;j<divs.size();j++)
7309 INTERP_KERNEL::Node *tmp=0;
7311 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
7313 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
7315 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
7319 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
7320 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
7327 * 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).
7328 * 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
7329 * with a plane. The result will be put in 'cut3DSuf' out parameter.
7330 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
7331 * @param nodesOnPlane, returns all the nodes that are on the plane.
7332 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
7333 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
7334 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
7335 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
7336 * @param desc is the descending connectivity 3DSurf->3DCurve
7337 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
7338 * @param cut3DSuf input/output param.
7340 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
7341 const int *nodal3DCurve, const int *nodalIndx3DCurve,
7342 const int *desc, const int *descIndx,
7343 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
7345 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
7346 int nbOf3DSurfCell=(int)cut3DSurf.size();
7347 for(int i=0;i<nbOf3DSurfCell;i++)
7349 std::vector<int> res;
7350 int offset=descIndx[i];
7351 int nbOfSeg=descIndx[i+1]-offset;
7352 for(int j=0;j<nbOfSeg;j++)
7354 int edgeId=desc[offset+j];
7355 int status=cut3DCurve[edgeId];
7359 res.push_back(status);
7362 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
7363 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
7371 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7377 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
7378 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
7381 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7385 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
7390 {// case when plane is on a multi colinear edge of a polyhedron
7391 if((int)res.size()==2*nbOfSeg)
7393 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
7396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
7403 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
7404 * 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).
7405 * 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
7406 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
7407 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
7408 * @param desc is the descending connectivity 3D->3DSurf
7409 * @param descIndx is the descending connectivity index 3D->3DSurf
7411 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
7412 const int *desc, const int *descIndx,
7413 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
7415 checkFullyDefined();
7416 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7417 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
7418 const int *nodal3D=_nodal_connec->getConstPointer();
7419 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
7420 int nbOfCells=getNumberOfCells();
7421 for(int i=0;i<nbOfCells;i++)
7423 std::map<int, std::set<int> > m;
7424 int offset=descIndx[i];
7425 int nbOfFaces=descIndx[i+1]-offset;
7428 for(int j=0;j<nbOfFaces;j++)
7430 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
7431 if(p.first!=-1 && p.second!=-1)
7435 start=p.first; end=p.second;
7436 m[p.first].insert(p.second);
7437 m[p.second].insert(p.first);
7441 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
7442 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
7443 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7444 INTERP_KERNEL::NormalizedCellType cmsId;
7445 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
7446 start=tmp[0]; end=tmp[nbOfNodesSon-1];
7447 for(unsigned k=0;k<nbOfNodesSon;k++)
7449 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
7450 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
7457 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
7461 std::map<int, std::set<int> >::const_iterator it=m.find(start);
7462 const std::set<int>& s=(*it).second;
7463 std::set<int> s2; s2.insert(prev);
7465 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
7468 int val=*s3.begin();
7469 conn.push_back(start);
7476 conn.push_back(end);
7479 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
7480 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
7481 cellIds->pushBackSilent(i);
7487 * 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
7488 * 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
7489 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7490 * 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
7491 * 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.
7493 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7495 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
7497 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7500 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7501 if(cm.getDimension()==2)
7503 const int *node=nodalConnBg+1;
7504 int startNode=*node++;
7505 double refX=coords[2*startNode];
7506 for(;node!=nodalConnEnd;node++)
7508 if(coords[2*(*node)]<refX)
7511 refX=coords[2*startNode];
7514 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7518 double angle0=-M_PI/2;
7524 while(nextNode!=startNode)
7528 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7530 if(*node!=tmpOut.back() && *node!=prevNode)
7532 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7533 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7538 res=angle0-angleM+2.*M_PI;
7547 if(nextNode!=startNode)
7549 angle0=angleNext-M_PI;
7552 prevNode=tmpOut.back();
7553 tmpOut.push_back(nextNode);
7556 std::vector<int> tmp3(2*(sz-1));
7557 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7558 std::copy(nodalConnBg+1,nodalConnEnd,it);
7559 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7561 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7564 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7566 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7571 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7572 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7577 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7580 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7584 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7585 * 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.
7587 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7588 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7589 * \param [in,out] arr array in which the remove operation will be done.
7590 * \param [in,out] arrIndx array in the remove operation will modify
7591 * \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])
7592 * \return true if \b arr and \b arrIndx have been modified, false if not.
7594 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7596 if(!arrIndx || !arr)
7597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7598 if(offsetForRemoval<0)
7599 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7600 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7601 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7602 int *arrIPtr=arrIndx->getPointer();
7605 const int *arrPtr=arr->getConstPointer();
7606 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7607 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7609 if(*arrIPtr-previousArrI>offsetForRemoval)
7611 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7613 if(s.find(*work)==s.end())
7614 arrOut.push_back(*work);
7617 previousArrI=*arrIPtr;
7618 *arrIPtr=(int)arrOut.size();
7620 if(arr->getNumberOfTuples()==(int)arrOut.size())
7622 arr->alloc((int)arrOut.size(),1);
7623 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7628 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7629 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7630 * The selection of extraction is done standardly in new2old format.
7631 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
7633 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7634 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7635 * \param [in] arrIn arr origin array from which the extraction will be done.
7636 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7637 * \param [out] arrOut the resulting array
7638 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7640 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7641 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7643 if(!arrIn || !arrIndxIn)
7644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7645 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7646 const int *arrInPtr=arrIn->getConstPointer();
7647 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7648 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7649 int maxSizeOfArr=arrIn->getNumberOfTuples();
7650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7652 arrIo->alloc((int)(sz+1),1);
7653 const int *idsIt=idsOfSelectBg;
7654 int *work=arrIo->getPointer();
7657 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7659 if(*idsIt>=0 && *idsIt<nbOfGrps)
7660 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7663 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7664 throw INTERP_KERNEL::Exception(oss.str().c_str());
7670 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7671 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7672 throw INTERP_KERNEL::Exception(oss.str().c_str());
7675 arro->alloc(lgth,1);
7676 work=arro->getPointer();
7677 idsIt=idsOfSelectBg;
7678 for(std::size_t i=0;i<sz;i++,idsIt++)
7680 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7681 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7684 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7685 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7686 throw INTERP_KERNEL::Exception(oss.str().c_str());
7690 arrIndexOut=arrIo.retn();
7694 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7695 * 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
7696 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7697 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7699 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7700 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7701 * \param [in] arrIn arr origin array from which the extraction will be done.
7702 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7703 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7704 * \param [in] srcArrIndex index array of \b srcArr
7705 * \param [out] arrOut the resulting array
7706 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7708 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7710 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7711 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7712 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7714 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7715 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7716 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7718 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7719 std::vector<bool> v(nbOfTuples,true);
7721 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7722 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7723 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7725 if(*it>=0 && *it<nbOfTuples)
7728 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7732 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7733 throw INTERP_KERNEL::Exception(oss.str().c_str());
7736 srcArrIndexPtr=srcArrIndex->getConstPointer();
7737 arrIo->alloc(nbOfTuples+1,1);
7738 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7739 const int *arrInPtr=arrIn->getConstPointer();
7740 const int *srcArrPtr=srcArr->getConstPointer();
7741 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7742 int *arroPtr=arro->getPointer();
7743 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7747 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7748 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7752 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7753 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7754 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7758 arrIndexOut=arrIo.retn();
7762 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7763 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7765 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7766 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7767 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7768 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7769 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7770 * \param [in] srcArrIndex index array of \b srcArr
7772 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7774 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7775 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7777 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7778 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7779 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7780 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7781 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7782 int *arrInOutPtr=arrInOut->getPointer();
7783 const int *srcArrPtr=srcArr->getConstPointer();
7784 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7786 if(*it>=0 && *it<nbOfTuples)
7788 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7789 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7792 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] !";
7793 throw INTERP_KERNEL::Exception(oss.str().c_str());
7798 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7799 throw INTERP_KERNEL::Exception(oss.str().c_str());
7805 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7806 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7807 * 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]].
7808 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7809 * A negative value in \b arrIn means that it is ignored.
7810 * 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.
7812 * \param [in] arrIn arr origin array from which the extraction will be done.
7813 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7814 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7815 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
7817 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
7819 int seed=0,nbOfDepthPeelingPerformed=0;
7820 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
7824 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7825 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7826 * 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]].
7827 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7828 * A negative value in \b arrIn means that it is ignored.
7829 * 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.
7830 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
7831 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
7832 * \param [in] arrIn arr origin array from which the extraction will be done.
7833 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7834 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
7835 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
7836 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7837 * \sa MEDCouplingUMesh::partitionBySpreadZone
7839 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
7841 nbOfDepthPeelingPerformed=0;
7843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
7844 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7847 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
7851 std::vector<bool> fetched(nbOfTuples,false);
7852 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
7855 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)
7857 nbOfDepthPeelingPerformed=0;
7858 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
7859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
7860 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7861 std::vector<bool> fetched2(nbOfTuples,false);
7863 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
7865 if(*seedElt>=0 && *seedElt<nbOfTuples)
7866 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
7868 { 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()); }
7870 const int *arrInPtr=arrIn->getConstPointer();
7871 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7872 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
7873 std::vector<int> idsToFetch1(seedBg,seedEnd);
7874 std::vector<int> idsToFetch2;
7875 std::vector<int> *idsToFetch=&idsToFetch1;
7876 std::vector<int> *idsToFetchOther=&idsToFetch2;
7877 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
7879 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
7880 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
7882 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
7883 std::swap(idsToFetch,idsToFetchOther);
7884 idsToFetchOther->clear();
7885 nbOfDepthPeelingPerformed++;
7887 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
7889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
7890 int *retPtr=ret->getPointer();
7891 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
7898 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7899 * 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
7900 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7901 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7903 * \param [in] start begin of set of ids of the input extraction (included)
7904 * \param [in] end end of set of ids of the input extraction (excluded)
7905 * \param [in] step step of the set of ids in range mode.
7906 * \param [in] arrIn arr origin array from which the extraction will be done.
7907 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7908 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7909 * \param [in] srcArrIndex index array of \b srcArr
7910 * \param [out] arrOut the resulting array
7911 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7913 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
7915 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7916 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7917 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7919 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
7921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7923 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7925 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7926 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7927 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
7929 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7931 if(it>=0 && it<nbOfTuples)
7932 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7935 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7936 throw INTERP_KERNEL::Exception(oss.str().c_str());
7939 srcArrIndexPtr=srcArrIndex->getConstPointer();
7940 arrIo->alloc(nbOfTuples+1,1);
7941 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7942 const int *arrInPtr=arrIn->getConstPointer();
7943 const int *srcArrPtr=srcArr->getConstPointer();
7944 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7945 int *arroPtr=arro->getPointer();
7946 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7948 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
7951 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7952 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7956 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7957 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7961 arrIndexOut=arrIo.retn();
7965 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7966 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7968 * \param [in] start begin of set of ids of the input extraction (included)
7969 * \param [in] end end of set of ids of the input extraction (excluded)
7970 * \param [in] step step of the set of ids in range mode.
7971 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7972 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7973 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7974 * \param [in] srcArrIndex index array of \b srcArr
7976 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7978 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7979 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7981 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7982 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
7983 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7984 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7985 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7986 int *arrInOutPtr=arrInOut->getPointer();
7987 const int *srcArrPtr=srcArr->getConstPointer();
7988 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
7990 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7992 if(it>=0 && it<nbOfTuples)
7994 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
7995 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
7998 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7999 throw INTERP_KERNEL::Exception(oss.str().c_str());
8004 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8005 throw INTERP_KERNEL::Exception(oss.str().c_str());
8011 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8012 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8013 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8014 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8015 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8017 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8019 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
8021 checkFullyDefined();
8022 int mdim=getMeshDimension();
8023 int spaceDim=getSpaceDimension();
8025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8026 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8027 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8028 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
8029 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8030 ret->setCoords(getCoords());
8031 ret->allocateCells((int)partition.size());
8033 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8035 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
8040 cell=tmp->buildUnionOf2DMesh();
8043 cell=tmp->buildUnionOf3DMesh();
8046 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8049 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
8052 ret->finishInsertingCells();
8057 * This method partitions \b this into contiguous zone.
8058 * This method only needs a well defined connectivity. Coordinates are not considered here.
8059 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8061 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
8064 int nbOfCellsCur=getNumberOfCells();
8065 std::vector<DataArrayInt *> ret;
8068 DataArrayInt *neigh=0,*neighI=0;
8069 computeNeighborsOfCells(neigh,neighI);
8070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8071 std::vector<bool> fetchedCells(nbOfCellsCur,false);
8072 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8074 while(seed<nbOfCellsCur)
8076 int nbOfPeelPerformed=0;
8077 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
8078 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8080 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8081 ret.push_back((*it).retn());
8085 int nbOfCellsCur=getNumberOfCells();
8086 DataArrayInt *neigh=0,*neighI=0;
8087 computeNeighborsOfCells(neigh,neighI);
8088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8089 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
8090 std::vector<DataArrayInt *> ret;
8091 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8092 while(nbOfCellsCur>0)
8094 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
8095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
8096 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
8097 ret2.push_back(tmp2); ret.push_back(tmp2);
8098 nbOfCellsCur=tmp3->getNumberOfTuples();
8101 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
8102 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
8105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
8106 neighAuto->transformWithIndArr(renum->begin(),renum->end());
8109 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
8116 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8117 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8119 * \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.
8120 * \return a newly allocated DataArrayInt to be managed by the caller.
8121 * \throw In case of \a code has not the right format (typically of size 3*n)
8123 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
8125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
8126 std::size_t nb=code.size()/3;
8127 if(code.size()%3!=0)
8128 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8129 ret->alloc((int)nb,2);
8130 int *retPtr=ret->getPointer();
8131 for(std::size_t i=0;i<nb;i++,retPtr+=2)
8133 retPtr[0]=code[3*i+2];
8134 retPtr[1]=code[3*i+2]+code[3*i+1];
8139 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8140 _own_cell(true),_cell_id(-1),_nb_cell(0)
8145 _nb_cell=mesh->getNumberOfCells();
8149 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8157 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8158 _own_cell(false),_cell_id(bg-1),
8165 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8168 if(_cell_id<_nb_cell)
8177 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8183 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8185 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8188 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8194 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8202 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8208 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8213 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8218 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8220 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8223 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8228 _nb_cell=mesh->getNumberOfCells();
8232 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8239 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8241 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
8242 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
8243 if(_cell_id<_nb_cell)
8245 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8246 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
8247 int startId=_cell_id;
8248 _cell_id+=nbOfElems;
8249 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8255 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8259 _conn=mesh->getNodalConnectivity()->getPointer();
8260 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8264 void MEDCouplingUMeshCell::next()
8266 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8271 _conn_lgth=_conn_indx[1]-_conn_indx[0];
8274 std::string MEDCouplingUMeshCell::repr() const
8276 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8278 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8280 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8284 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8287 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8289 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8290 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8292 return INTERP_KERNEL::NORM_ERROR;
8295 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8298 if(_conn_lgth!=NOTICABLE_FIRST_VAL)