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 "DirectedBoundingBox.hxx"
30 #include "InterpKernelMeshQuality.hxx"
31 #include "InterpKernelCellSimplify.hxx"
32 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
33 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
34 #include "InterpKernelAutoPtr.hxx"
35 #include "InterpKernelGeo2DNode.hxx"
36 #include "InterpKernelGeo2DEdgeLin.hxx"
37 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
38 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
47 using namespace ParaMEDMEM;
49 const char MEDCouplingUMesh::PART_OF_NAME[]="PartOf_";
51 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53 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 };
55 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 return new MEDCouplingUMesh;
60 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
63 ret->setName(meshName);
64 ret->setMeshDimension(meshDim);
68 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
73 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
75 return new MEDCouplingUMesh(*this,recDeepCpy);
78 void MEDCouplingUMesh::updateTime() const
80 MEDCouplingPointSet::updateTime();
83 updateTimeWith(*_nodal_connec);
85 if(_nodal_connec_index)
87 updateTimeWith(*_nodal_connec_index);
91 MEDCouplingUMesh::MEDCouplingUMesh():_iterator(-1),_mesh_dim(-2),
92 _nodal_connec(0),_nodal_connec_index(0)
97 * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity.
98 * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be
99 * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check
100 * that all is in order in 'this'.
102 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
105 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
106 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
108 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
110 std::ostringstream message;
111 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
112 throw INTERP_KERNEL::Exception(message.str().c_str());
117 if(_nodal_connec->getNumberOfComponents()!=1)
118 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
119 if(_nodal_connec->getInfoOnComponent(0)!="")
120 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
122 if(_nodal_connec_index)
124 if(_nodal_connec_index->getNumberOfComponents()!=1)
125 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
126 if(_nodal_connec_index->getInfoOnComponent(0)!="")
127 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
131 throw INTERP_KERNEL::Exception("It appears that finishInsertingCells method has not been invoked after a insertNextCell session !");
136 * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does.
137 * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids.
138 * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2.
140 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
145 int meshDim=getMeshDimension();
146 int nbOfNodes=getNumberOfNodes();
147 int nbOfCells=getNumberOfCells();
148 const int *ptr=_nodal_connec->getConstPointer();
149 const int *ptrI=_nodal_connec_index->getConstPointer();
150 for(int i=0;i<nbOfCells;i++)
152 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
153 if((int)cm.getDimension()!=meshDim)
155 std::ostringstream oss;
156 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
157 throw INTERP_KERNEL::Exception(oss.str().c_str());
159 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
161 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
163 std::ostringstream oss;
164 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
165 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
166 throw INTERP_KERNEL::Exception(oss.str().c_str());
168 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
173 if(nodeId>=nbOfNodes)
175 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
176 throw INTERP_KERNEL::Exception(oss.str().c_str());
181 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
182 throw INTERP_KERNEL::Exception(oss.str().c_str());
186 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
188 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
189 throw INTERP_KERNEL::Exception(oss.str().c_str());
196 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
198 checkCoherency1(eps);
201 void MEDCouplingUMesh::setMeshDimension(int meshDim)
204 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 !");
209 void MEDCouplingUMesh::allocateCells(int nbOfCells)
211 if(_nodal_connec_index)
213 _nodal_connec_index->decrRef();
217 _nodal_connec->decrRef();
220 _nodal_connec_index=DataArrayInt::New();
221 _nodal_connec_index->alloc(nbOfCells+1,1);
222 int *pt=_nodal_connec_index->getPointer();
224 _nodal_connec=DataArrayInt::New();
225 _nodal_connec->alloc(2*nbOfCells,1);
232 * Appends a cell in connectivity array.
233 * @param type type of cell to add.
234 * @param size number of nodes constituting this cell.
235 * @param nodalConnOfCell the connectivity of the cell to add.
237 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
239 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
240 if(_nodal_connec_index==0)
241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
242 if((int)cm.getDimension()==_mesh_dim)
244 int nbOfElems=_nodal_connec_index->getNbOfElems()-1;
245 if(_iterator>=nbOfElems)
246 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : allocation of cells was wide enough ! Call insertNextCell with higher value or call finishInsertingCells !");
247 int *pt=_nodal_connec_index->getPointer();
248 int idx=pt[_iterator];
250 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
252 pt[++_iterator]=idx+size+1;
256 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
257 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
258 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
259 throw INTERP_KERNEL::Exception(oss.str().c_str());
264 * Method to be called to cloture the insertion of cells using this->insertNextCell.
266 void MEDCouplingUMesh::finishInsertingCells()
268 const int *pt=_nodal_connec_index->getConstPointer();
269 int idx=pt[_iterator];
271 _nodal_connec->reAlloc(idx);
272 _nodal_connec_index->reAlloc(_iterator+1);
274 _nodal_connec->declareAsNew();
275 _nodal_connec_index->declareAsNew();
280 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
281 * Useful for python users.
283 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
285 return new MEDCouplingUMeshCellIterator(this);
289 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
290 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
291 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
292 * Useful for python users.
294 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
296 if(!checkConsecutiveCellTypes())
297 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
298 return new MEDCouplingUMeshCellByTypeEntry(this);
301 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
307 * This method is a method that compares 'this' and 'other'.
308 * This method compares \b all attributes, even names and component names.
310 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
314 std::ostringstream oss; oss.precision(15);
315 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
318 reason="mesh given in input is not castable in MEDCouplingUMesh !";
321 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
323 if(_mesh_dim!=otherC->_mesh_dim)
325 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
329 if(_types!=otherC->_types)
331 oss << "umesh geometric type mismatch :\nThis geometric types are :";
332 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
333 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
334 oss << "\nOther geometric types are :";
335 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
336 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
340 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
341 if(_nodal_connec==0 || otherC->_nodal_connec==0)
343 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
346 if(_nodal_connec!=otherC->_nodal_connec)
347 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
349 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
352 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
353 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
355 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
358 if(_nodal_connec_index!=otherC->_nodal_connec_index)
359 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
361 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
367 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
369 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
372 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
374 if(_mesh_dim!=otherC->_mesh_dim)
376 if(_types!=otherC->_types)
378 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
379 if(_nodal_connec==0 || otherC->_nodal_connec==0)
381 if(_nodal_connec!=otherC->_nodal_connec)
382 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
384 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
385 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
387 if(_nodal_connec_index!=otherC->_nodal_connec_index)
388 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
394 * 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
395 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
397 * In case of success cellCor and nodeCor are informed both.
398 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
399 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
400 * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
402 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
403 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
405 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
407 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
408 MEDCouplingMesh::checkFastEquivalWith(other,prec);
409 if(_types!=otherC->_types)
410 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
411 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
414 int oldNbOfNodes=getNumberOfNodes();
415 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
418 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
419 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
420 if(pt!=da->getConstPointer()+da->getNbOfElems())
421 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
422 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
425 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
428 da=m->zipConnectivityTraducer(cellCompPol);
429 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
430 pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
431 if(pt!=da->getConstPointer()+da->getNbOfElems())
432 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=DataArrayInt::New();
434 cellCor2->alloc(otherC->getNumberOfCells(),1);
435 std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor2->getPointer());
436 bool nident=nodeCor2->isIdentity();
437 bool cident=cellCor2->isIdentity();
438 if(!nident) { nodeCor=nodeCor2; nodeCor2->incrRef(); } else nodeCor=0;
439 if(!cident) { cellCor=cellCor2; cellCor2->incrRef(); } else cellCor=0;
443 * 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
444 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
445 * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
446 * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception !
448 * In case of success cellCor are informed both.
449 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
450 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
452 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
453 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
455 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
457 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
458 MEDCouplingMesh::checkFastEquivalWith(other,prec);
459 if(_types!=otherC->_types)
460 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
461 if(_coords!=otherC->_coords)
462 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
463 std::vector<const MEDCouplingUMesh *> ms(2);
466 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
468 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
469 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
470 if(pt!=da->getConstPointer()+da->getNbOfElems())
472 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=DataArrayInt::New();
475 cellCor2->alloc(otherC->getNumberOfCells(),1);
476 std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor2->getPointer());
477 if(!cellCor2->isIdentity()) { cellCor=cellCor2; cellCor2->incrRef(); } else cellCor=0;
481 * This method checks fastly that 'this' and 'other' are equal.
483 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
485 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
487 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
488 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
489 int nbOfCells=getNumberOfCells();
493 status&=areCellsFrom2MeshEqual(otherC,0,prec);
494 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
495 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
497 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
501 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
502 * For speed reasons no check of this will be done.
504 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
507 int nbOfNodes=getNumberOfNodes();
508 int *revNodalIndxPtr=new int[nbOfNodes+1];
509 revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
510 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
511 const int *conn=_nodal_connec->getConstPointer();
512 const int *connIndex=_nodal_connec_index->getConstPointer();
513 int nbOfCells=getNumberOfCells();
514 int nbOfEltsInRevNodal=0;
515 for(int eltId=0;eltId<nbOfCells;eltId++)
517 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
518 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
519 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
520 if(*iter>=0)//for polyhedrons
522 nbOfEltsInRevNodal++;
523 revNodalIndxPtr[(*iter)+1]++;
526 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
527 int *revNodalPtr=new int[nbOfEltsInRevNodal];
528 revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
529 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
530 for(int eltId=0;eltId<nbOfCells;eltId++)
532 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
533 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
534 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
535 if(*iter>=0)//for polyhedrons
536 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
542 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
547 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
553 if(cm.getOrientationStatus(nb,conn1,conn2))
563 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
564 * For speed reasons no check of this will be done.
565 * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
566 * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
567 * The algorithm to compute this p-1 mesh is the following :
568 * For each cell in 'this' it splits into p-1 elements.
569 * If this p-1 element does not already exists it is appended to the returned mesh
570 * If this p-1 element already exists, it is not appended.
571 * This method returns or 4 arrays plus the returned mesh.
572 * '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.
573 * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
575 * 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.
576 * 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])
578 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
579 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
581 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
583 return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
587 * WARNING this method do the assumption that connectivity lies on the coordinates set.
588 * For speed reasons no check of this will be done.
589 * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
590 * 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,
591 * 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
592 * an array in relative "FORTRAN" mode.
594 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
595 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
597 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
599 return buildDescendingConnectivityGen(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
603 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
604 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
605 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
606 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
608 * \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
609 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
610 * \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.
612 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
618 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
620 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
624 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
625 * 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,
626 * excluding a set of meshdim-1 cells in input descending connectivity.
627 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
628 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
629 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
631 * \param [in] desc descending connectivity array.
632 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
633 * \param [in] revDesc reverse descending connectivity array.
634 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
635 * \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
636 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
637 * \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.
639 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
640 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
642 if(!desc || !descIndx || !revDesc || !revDescIndx)
643 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
644 const int *descPtr=desc->getConstPointer();
645 const int *descIPtr=descIndx->getConstPointer();
646 const int *revDescPtr=revDesc->getConstPointer();
647 const int *revDescIPtr=revDescIndx->getConstPointer();
649 int nbCells=descIndx->getNumberOfTuples()-1;
650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
652 int *out1Ptr=out1->getPointer();
654 std::vector<int> out0v;
655 out0v.reserve(desc->getNumberOfTuples());
656 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
658 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
660 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
662 out0v.insert(out0v.end(),s.begin(),s.end());
664 *out1Ptr=out0v.size();
666 out0->alloc((int)out0v.size(),1);
667 std::copy(out0v.begin(),out0v.end(),out0->getPointer());
668 neighbors=out0; out0->incrRef();
669 neighborsIndx=out1; out1->incrRef();
675 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
676 * For speed reasons no check of this will be done.
678 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
680 checkConnectivityFullyDefined();
681 int nbOfCells=getNumberOfCells();
682 int nbOfNodes=getNumberOfNodes();
683 const int *conn=_nodal_connec->getConstPointer();
684 const int *connIndex=_nodal_connec_index->getConstPointer();
685 std::vector< std::vector<int> > descMeshConnB(nbOfCells);
686 std::vector< std::vector<int> > revDescMeshConnB;
687 std::vector< std::vector<int> > revNodalB(nbOfNodes);
688 std::vector<int> meshDM1Conn;
689 std::vector<int> meshDM1ConnIndex(1); meshDM1ConnIndex[0]=0;
690 std::vector<int> meshDM1Type;
691 for(int eltId=0;eltId<nbOfCells;eltId++)
693 int pos=connIndex[eltId];
694 int posP1=connIndex[eltId+1];
695 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
696 unsigned nbOfSons=cm.getNumberOfSons2(conn+pos+1,posP1-pos-1);
697 int *tmp=new int[posP1-pos];
698 for(unsigned i=0;i<nbOfSons;i++)
700 INTERP_KERNEL::NormalizedCellType cmsId;
701 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
702 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel(cmsId);
703 std::set<int> shareableCells(revNodalB[tmp[0]].begin(),revNodalB[tmp[0]].end());
704 for(unsigned j=1;j<nbOfNodesSon && !shareableCells.empty();j++)
706 std::set<int> tmp2(revNodalB[tmp[j]].begin(),revNodalB[tmp[j]].end());
708 std::set_intersection(tmp2.begin(),tmp2.end(),shareableCells.begin(),shareableCells.end(),inserter(tmp3,tmp3.begin()));
711 std::list<int> shareableCellsL(shareableCells.begin(),shareableCells.end());
712 std::set<int> ref(tmp,tmp+nbOfNodesSon);
713 for(std::list<int>::iterator iter=shareableCellsL.begin();iter!=shareableCellsL.end();)
715 if(cms.isCompatibleWith((INTERP_KERNEL::NormalizedCellType)meshDM1Type[*iter]))
717 std::set<int> ref2(meshDM1Conn.begin()+meshDM1ConnIndex[*iter],meshDM1Conn.begin()+meshDM1ConnIndex[(*iter)+1]);
721 iter=shareableCellsL.erase(iter);
724 iter=shareableCellsL.erase(iter);
726 if(shareableCellsL.empty())
728 meshDM1Conn.insert(meshDM1Conn.end(),tmp,tmp+nbOfNodesSon);
729 meshDM1ConnIndex.push_back(meshDM1ConnIndex.back()+nbOfNodesSon);
730 int cellDM1Id=(int)meshDM1Type.size();
731 meshDM1Type.push_back((int)cmsId);
732 for(unsigned k=0;k<nbOfNodesSon;k++)
733 revNodalB[tmp[k]].push_back(cellDM1Id);
734 revDescMeshConnB.resize(cellDM1Id+1);
735 revDescMeshConnB.back().push_back(eltId);
736 descMeshConnB[eltId].push_back(nbrer(cellDM1Id,0,cms,false,0,0));
740 int DM1cellId=shareableCellsL.front();
741 revDescMeshConnB[DM1cellId].push_back(eltId);
742 descMeshConnB[eltId].push_back(nbrer(DM1cellId,nbOfNodesSon,cms,true,tmp,&meshDM1Conn[meshDM1ConnIndex[DM1cellId]]));
749 std::string name="Mesh constituent of "; name+=getName();
750 MEDCouplingUMesh *ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-1);
751 ret->setCoords(getCoords());
752 int nbOfCellsInConstituent=(int)meshDM1Type.size();
753 ret->allocateCells(nbOfCellsInConstituent);
754 revDescIndx->alloc(nbOfCellsInConstituent+1,1);
755 int *tmp3=revDescIndx->getPointer(); tmp3[0]=0;
756 for(int ii=0;ii<nbOfCellsInConstituent;ii++)
758 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)meshDM1Type[ii],meshDM1ConnIndex[ii+1]-meshDM1ConnIndex[ii],&meshDM1Conn[meshDM1ConnIndex[ii]]);
759 tmp3[ii+1]=tmp3[ii]+((int)revDescMeshConnB[ii].size());
761 ret->finishInsertingCells();
762 revDesc->alloc(tmp3[nbOfCellsInConstituent],1);
763 tmp3=revDesc->getPointer();
764 for(std::vector< std::vector<int> >::const_iterator iter2=revDescMeshConnB.begin();iter2!=revDescMeshConnB.end();iter2++)
765 tmp3=std::copy((*iter2).begin(),(*iter2).end(),tmp3);
766 meshDM1Type.clear(); meshDM1ConnIndex.clear(); meshDM1Conn.clear();
767 descIndx->alloc(nbOfCells+1,1);
768 tmp3=descIndx->getPointer(); tmp3[0]=0;
769 for(int jj=0;jj<nbOfCells;jj++)
770 tmp3[jj+1]=tmp3[jj]+((int)descMeshConnB[jj].size());
771 desc->alloc(tmp3[nbOfCells],1);
772 tmp3=desc->getPointer();
773 for(std::vector< std::vector<int> >::const_iterator iter3=descMeshConnB.begin();iter3!=descMeshConnB.end();iter3++)
774 tmp3=std::copy((*iter3).begin(),(*iter3).end(),tmp3);
779 struct MEDCouplingAccVisit
781 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
782 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
783 int _new_nb_of_nodes;
790 * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
791 * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
792 * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
793 * If mesh dimension is not in [2,3] an exception is thrown.
794 * Of course pay attention that the resulting mesh is slower than previous one.
795 * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
796 * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
797 * If mesh==3, after throw the mesh is \b unconsistent !
798 * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
800 * \warning This method modifies can modify significantly the geometric type order in \a this.
801 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
803 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
806 int dim=getMeshDimension();
808 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
809 int nbOfCells=getNumberOfCells();
812 const int *connIndex=_nodal_connec_index->getConstPointer();
813 int *conn=_nodal_connec->getPointer();
814 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
816 if(*iter>=0 && *iter<nbOfCells)
818 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
820 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
822 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
826 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
827 oss << " in range [0," << nbOfCells << ") !";
828 throw INTERP_KERNEL::Exception(oss.str().c_str());
834 int *connIndex=_nodal_connec_index->getPointer();
835 int connIndexLgth=_nodal_connec_index->getNbOfElems();
836 const int *connOld=_nodal_connec->getConstPointer();
837 int connOldLgth=_nodal_connec->getNbOfElems();
838 std::vector<int> connNew(connOld,connOld+connOldLgth);
839 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
841 if(*iter>=0 && *iter<nbOfCells)
843 int pos=connIndex[*iter];
844 int posP1=connIndex[(*iter)+1];
845 int lgthOld=posP1-pos-1;
846 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
847 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
848 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
849 int *tmp=new int[nbOfFaces*lgthOld];
851 for(int j=0;j<(int)nbOfFaces;j++)
853 INTERP_KERNEL::NormalizedCellType type;
854 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
858 std::size_t newLgth=std::distance(tmp,work)-1;
859 std::size_t delta=newLgth-lgthOld;
860 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
861 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
862 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
867 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
868 oss << " in range [0," << nbOfCells << ") !";
869 throw INTERP_KERNEL::Exception(oss.str().c_str());
872 _nodal_connec->alloc((int)connNew.size(),1);
873 int *newConnPtr=_nodal_connec->getPointer();
874 std::copy(connNew.begin(),connNew.end(),newConnPtr);
880 * This method converts all cells into poly type if possible.
881 * This method is purely for userfriendliness.
882 * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
884 void MEDCouplingUMesh::convertAllToPoly()
886 int nbOfCells=getNumberOfCells();
887 std::vector<int> cellIds(nbOfCells);
888 for(int i=0;i<nbOfCells;i++)
890 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
894 * 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.
895 * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
896 * 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
897 * each 2 faces hidden in the single face of polyhedron).
898 * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
899 * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
900 * 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'
902 * This method is usefull only for users that wants to build extruded unstructured mesh.
903 * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
904 * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
906 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
909 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
911 int nbOfCells=getNumberOfCells();
912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
913 newCi->alloc(nbOfCells+1,1);
914 int *newci=newCi->getPointer();
915 const int *ci=_nodal_connec_index->getConstPointer();
916 const int *c=_nodal_connec->getConstPointer();
918 for(int i=0;i<nbOfCells;i++)
920 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
921 if(type==INTERP_KERNEL::NORM_POLYHED)
923 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
925 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
926 throw INTERP_KERNEL::Exception(oss.str().c_str());
928 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
931 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 !";
932 throw INTERP_KERNEL::Exception(oss.str().c_str());
935 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)
938 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
941 newC->alloc(newci[nbOfCells],1);
942 int *newc=newC->getPointer();
943 for(int i=0;i<nbOfCells;i++)
945 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
946 if(type==INTERP_KERNEL::NORM_POLYHED)
948 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
949 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
951 for(std::size_t j=0;j<n1;j++)
953 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
955 newc[n1+5*j+1]=c[ci[i]+1+j];
956 newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
957 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
958 newc[n1+5*j+4]=c[ci[i]+1+j+n1];
963 newc=std::copy(c+ci[i],c+ci[i+1],newc);
965 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi;
966 _nodal_connec->decrRef(); _nodal_connec=newC;
967 newC->incrRef(); newCi->incrRef();
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);
1065 const double *coordsPtr=coords->getConstPointer();
1067 int nbOfCells=getNumberOfCells();
1068 const int *conn=_nodal_connec->getConstPointer();
1069 const int *index=_nodal_connec_index->getConstPointer();
1070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1071 connINew->alloc(nbOfCells+1,1);
1072 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1073 std::vector<int> connNew;
1075 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1077 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1079 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1083 connNew.insert(connNew.end(),conn+index[i],conn+index[i+1]);
1084 *connINewPtr=(int)connNew.size();
1088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew2=DataArrayInt::New();
1089 connNew2->alloc((int)connNew.size(),1);
1090 std::copy(connNew.begin(),connNew.end(),connNew2->getPointer());
1091 setConnectivity(connNew2,connINew,false);
1096 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1097 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1098 * the format of returned DataArrayInt instance.
1100 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1101 * \sa MEDCouplingUMesh::getNodeIdsInUse
1103 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1105 checkConnectivityFullyDefined();
1107 int nbOfCells=getNumberOfCells();
1108 const int *connIndex=_nodal_connec_index->getConstPointer();
1109 const int *conn=_nodal_connec->getConstPointer();
1110 for(int i=0;i<nbOfCells;i++)
1111 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1113 retS.insert(conn[j]);
1114 DataArrayInt *ret=DataArrayInt::New();
1115 ret->alloc((int)retS.size(),1);
1116 std::copy(retS.begin(),retS.end(),ret->getPointer());
1121 * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
1122 * The returned array is newly created and should be dealt by the caller.
1123 * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
1124 * The size of returned array is the number of nodes of 'this'.
1125 * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
1126 * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
1127 * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
1129 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1132 int nbOfNodes=getNumberOfNodes();
1133 DataArrayInt *ret=DataArrayInt::New();
1134 ret->alloc(nbOfNodes,1);
1135 int *traducer=ret->getPointer();
1136 std::fill(traducer,traducer+nbOfNodes,-1);
1137 int nbOfCells=getNumberOfCells();
1138 const int *connIndex=_nodal_connec_index->getConstPointer();
1139 const int *conn=_nodal_connec->getConstPointer();
1140 for(int i=0;i<nbOfCells;i++)
1141 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1143 traducer[conn[j]]=1;
1144 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1145 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1150 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1151 * For each cell in \b this the number of nodes constituting cell is computed.
1152 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1153 * For polyhedrons, the face separation (-1) are excluded from the couting.
1155 * \return a newly allocated array
1157 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1159 checkConnectivityFullyDefined();
1160 int nbOfCells=getNumberOfCells();
1161 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1162 ret->alloc(nbOfCells,1);
1163 int *retPtr=ret->getPointer();
1164 const int *conn=getNodalConnectivity()->getConstPointer();
1165 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1166 for(int i=0;i<nbOfCells;i++,retPtr++)
1168 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1169 *retPtr=connI[i+1]-connI[i]-1;
1171 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1173 ret->incrRef(); return ret;
1177 * 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.
1178 * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
1179 * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
1180 * -1 values in returned array means that the corresponding old node is no more used.
1182 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1184 int newNbOfNodes=-1;
1185 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1186 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1191 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1192 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1194 int MEDCouplingUMesh::areCellsEqual(int cell1, int cell2, int compType) const
1199 return areCellsEqual0(cell1,cell2);
1201 return areCellsEqual1(cell1,cell2);
1203 return areCellsEqual2(cell1,cell2);
1205 return areCellsEqual7(cell1,cell2);
1207 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1 or 2.");
1211 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1213 int MEDCouplingUMesh::areCellsEqual0(int cell1, int cell2) const
1215 const int *conn=getNodalConnectivity()->getConstPointer();
1216 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1217 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1218 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1223 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1225 int MEDCouplingUMesh::areCellsEqual1(int cell1, int cell2) const
1227 const int *conn=getNodalConnectivity()->getConstPointer();
1228 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1229 int sz=connI[cell1+1]-connI[cell1];
1230 if(sz==connI[cell2+1]-connI[cell2])
1232 if(conn[connI[cell1]]==conn[connI[cell2]])
1234 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1235 unsigned dim=cm.getDimension();
1241 int *tmp=new int[sz1];
1242 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],tmp);
1243 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1244 work=std::search(tmp,tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1246 return work!=tmp+sz1?1:0;
1249 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1252 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areCellsEqual1 : not implemented yet for meshdim == 3 !");
1259 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1261 int MEDCouplingUMesh::areCellsEqual2(int cell1, int cell2) const
1263 const int *conn=getNodalConnectivity()->getConstPointer();
1264 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1265 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1267 if(conn[connI[cell1]]==conn[connI[cell2]])
1269 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1270 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1278 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1280 int MEDCouplingUMesh::areCellsEqual7(int cell1, int cell2) const
1282 const int *conn=getNodalConnectivity()->getConstPointer();
1283 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1284 int sz=connI[cell1+1]-connI[cell1];
1285 if(sz==connI[cell2+1]-connI[cell2])
1287 if(conn[connI[cell1]]==conn[connI[cell2]])
1289 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1290 unsigned dim=cm.getDimension();
1296 int *tmp=new int[sz1];
1297 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],tmp);
1298 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1299 work=std::search(tmp,tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1307 std::reverse_iterator<int *> it1(tmp+sz1);
1308 std::reverse_iterator<int *> it2(tmp);
1309 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1321 return work!=tmp+sz1?1:0;
1324 {//case of SEG2 and SEG3
1325 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1327 if(!cm.isQuadratic())
1329 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1330 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1331 if(std::equal(it1,it2,conn+connI[cell2]+1))
1337 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])
1344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areCellsEqual7 : not implemented yet for meshdim == 3 !");
1352 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1353 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1355 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1357 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1359 std::vector<int> c1,c2;
1360 getNodeIdsOfCell(cellId,c1);
1361 other->getNodeIdsOfCell(cellId,c2);
1362 std::size_t sz=c1.size();
1365 for(std::size_t i=0;i<sz;i++)
1367 std::vector<double> n1,n2;
1368 getCoordinatesOfNode(c1[0],n1);
1369 other->getCoordinatesOfNode(c2[0],n2);
1370 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1371 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1372 if(*std::max_element(n1.begin(),n1.end())>prec)
1379 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1380 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1381 * and result remains unchanged.
1382 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1383 * If in 'candidates' pool -1 value is considered as an empty value.
1384 * WARNING this method returns only ONE set of result !
1386 bool MEDCouplingUMesh::areCellsEqualInPool(const std::vector<int>& candidates, int compType, std::vector<int>& result) const
1388 std::set<int> cand(candidates.begin(),candidates.end());
1393 std::set<int>::const_iterator iter=cand.begin();
1394 int start=(*iter++);
1395 for(;iter!=cand.end();iter++)
1397 int status=areCellsEqual(start,*iter,compType);
1402 result.push_back(start);
1406 result.push_back(*iter);
1408 result.push_back(status==2?(*iter+1):-(*iter+1));
1415 * This method common cells base regarding 'compType' comparison policy described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for details.
1416 * This method returns 2 values 'res' and 'resI'.
1417 * If 'res' and 'resI' are not empty before calling this method they will be cleared before set.
1418 * The format of 'res' and 'resI' is as explained here.
1419 * resI.size()-1 is the number of set of cells equal.
1420 * The nth set is [res.begin()+resI[n];res.begin()+resI[n+1]) with 0<=n<resI.size()-1
1422 template<int SPACEDIM>
1423 void MEDCouplingUMesh::findCommonCellsBase(int compType, std::vector<int>& res, std::vector<int>& resI) const
1425 res.clear(); resI.clear();
1427 std::vector<double> bbox;
1428 int nbOfCells=getNumberOfCells();
1429 getBoundingBoxForBBTree(bbox);
1430 double bb[2*SPACEDIM];
1431 double eps=getCaracteristicDimension();
1433 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
1434 const int *conn=getNodalConnectivity()->getConstPointer();
1435 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1436 const double *coords=getCoords()->getConstPointer();
1437 std::vector<bool> isFetched(nbOfCells);
1438 for(int k=0;k<nbOfCells;k++)
1442 for(int j=0;j<SPACEDIM;j++)
1443 { bb[2*j]=std::numeric_limits<double>::max(); bb[2*j+1]=-std::numeric_limits<double>::max(); }
1444 for(const int *pt=conn+connI[k]+1;pt!=conn+connI[k+1];pt++)
1447 for(int j=0;j<SPACEDIM;j++)
1449 bb[2*j]=std::min(bb[2*j],coords[SPACEDIM*(*pt)+j]);
1450 bb[2*j+1]=std::max(bb[2*j+1],coords[SPACEDIM*(*pt)+j]);
1453 std::vector<int> candidates1;
1454 myTree.getIntersectingElems(bb,candidates1);
1455 std::vector<int> candidates;
1456 for(std::vector<int>::const_iterator iter=candidates1.begin();iter!=candidates1.end();iter++)
1457 if(!isFetched[*iter])
1458 candidates.push_back(*iter);
1459 if(areCellsEqualInPool(candidates,compType,res))
1461 int pos=resI.back();
1462 resI.push_back((int)res.size());
1463 for(std::vector<int>::const_iterator it=res.begin()+pos;it!=res.end();it++)
1464 isFetched[*it]=true;
1472 * This method could potentially modify 'this'. This method merges cells if there are cells equal in 'this'. The comparison is specified by 'compType'.
1473 * This method keeps the coordiantes of 'this'.
1475 * @param compType input specifying the technique used to compare cells each other.
1476 * - 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.
1477 * - 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)
1478 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1479 * - 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
1480 * can be used for users not sensitive to orientation of cell
1481 * @return the correspondance array old to new.
1483 * \warning This method modifies can modify significantly the geometric type order in \a this.
1484 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1486 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType) throw(INTERP_KERNEL::Exception)
1488 int spaceDim=getSpaceDimension();
1489 int nbOfCells=getNumberOfCells();
1490 std::vector<int> commonCells;
1491 std::vector<int> commonCellsI;
1496 findCommonCellsBase<3>(compType,commonCells,commonCellsI);
1501 findCommonCellsBase<2>(compType,commonCells,commonCellsI);
1506 findCommonCellsBase<1>(compType,commonCells,commonCellsI);
1510 throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3.");
1512 DataArrayInt *ret=DataArrayInt::New();
1513 ret->alloc(nbOfCells,1);
1514 int *retPtr=ret->getPointer();
1515 std::fill(retPtr,retPtr+nbOfCells,0);
1516 const std::size_t nbOfTupleSmCells=commonCellsI.size()-1;
1518 std::vector<int> cellsToKeep;
1519 for(std::size_t i=0;i<nbOfTupleSmCells;i++)
1521 for(std::vector<int>::const_iterator it=commonCells.begin()+commonCellsI[i];it!=commonCells.begin()+commonCellsI[i+1];it++)
1526 std::map<int,int> m;
1527 for(int i=0;i<nbOfCells;i++)
1533 cellsToKeep.push_back(i);
1537 std::map<int,int>::const_iterator iter=m.find(val);
1542 cellsToKeep.push_back(i);
1545 retPtr[i]=(*iter).second;
1548 MEDCouplingUMesh *self=(MEDCouplingUMesh *)buildPartOfMySelf(&cellsToKeep[0],&cellsToKeep[0]+cellsToKeep.size(),true);
1549 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1555 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1556 * 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.
1557 * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
1558 * The main difference is that this method is not expected to throw exception.
1559 * This method has two outputs :
1561 * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
1562 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1563 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1565 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1567 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1568 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType);
1569 int nbOfCells=getNumberOfCells();
1570 arr=o2n->substr(nbOfCells);
1571 arr->setName(other->getName());
1573 if(other->getNumberOfCells()==0)
1575 return arr->getMaxValue(tmp)<nbOfCells;
1579 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1580 * This method tries to determine if \b other is fully included in \b this.
1581 * The main difference is that this method is not expected to throw exception.
1582 * This method has two outputs :
1584 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1585 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1587 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1589 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1590 int spaceDim=mesh->getSpaceDimension();
1591 std::vector<int> commonCells;
1592 std::vector<int> commonCellsI;
1597 findCommonCellsBase<3>(7,commonCells,commonCellsI);
1602 findCommonCellsBase<2>(7,commonCells,commonCellsI);
1607 findCommonCellsBase<1>(7,commonCells,commonCellsI);
1611 throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3.");
1613 int thisNbCells=getNumberOfCells();
1614 int otherNbCells=other->getNumberOfCells();
1615 int nbOfCells=mesh->getNumberOfCells();
1616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1617 arr2->alloc(otherNbCells,1);
1618 arr2->fillWithZero();
1619 int *arr2Ptr=arr2->getPointer();
1620 int nbOfCommon=(int)commonCellsI.size()-1;
1621 for(int i=0;i<nbOfCommon;i++)
1623 int start=commonCells[commonCellsI[i]];
1624 if(start<thisNbCells)
1626 for(int j=commonCellsI[i]+1;j!=commonCellsI[i+1];j++)
1628 int sig=commonCells[j]>0?1:-1;
1629 int val=std::abs(commonCells[j])-1;
1630 if(val>=thisNbCells)
1631 arr2Ptr[val-thisNbCells]=sig*(start+1);
1635 arr2->setName(other->getName());
1636 if(arr2->presenceOfValue(0))
1644 * @param areNodesMerged if at least two nodes have been merged.
1645 * @return old to new node correspondance.
1647 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1649 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1651 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1656 * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
1658 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1660 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1662 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1667 * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
1668 * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
1669 * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
1670 * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
1672 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
1674 const DataArrayDouble *coords=other.getCoords();
1676 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
1678 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1679 int otherNbOfNodes=other.getNumberOfNodes();
1680 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1682 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1683 setCoords(newCoords);
1684 bool areNodesMerged;
1686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1689 setCoords(oldCoords);
1690 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1692 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1693 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1694 if(pt!=da->getConstPointer()+da->getNbOfElems())
1696 setCoords(oldCoords);
1697 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1699 setCoords(oldCoords);
1700 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1705 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1706 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1707 * cellIds is not given explicitely but by a range python like.
1709 * \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.
1710 * \return a newly allocated
1712 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1713 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1715 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1717 if(getMeshDimension()!=-1)
1719 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
1726 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1728 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1730 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1732 return const_cast<MEDCouplingUMesh *>(this);
1737 * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
1738 * @param begin begin of array containing the cell ids to keep.
1739 * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
1740 * @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.
1742 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1743 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1745 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1747 if(getMeshDimension()!=-1)
1749 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
1757 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1759 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1761 return const_cast<MEDCouplingUMesh *>(this);
1766 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1768 * 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.
1769 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1770 * The number of cells of \b this will remain the same with this method.
1772 * \param [in] begin begin of cell ids (included) of cells in this to assign
1773 * \param [in] end end of cell ids (excluded) of cells in this to assign
1774 * \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).
1775 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1777 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1779 checkConnectivityFullyDefined();
1780 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1781 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1783 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1785 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1786 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1787 throw INTERP_KERNEL::Exception(oss.str().c_str());
1789 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1790 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1792 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1793 throw INTERP_KERNEL::Exception(oss.str().c_str());
1795 int nbOfCells=getNumberOfCells();
1796 bool easyAssign=true;
1797 const int *conn=_nodal_connec->getConstPointer();
1798 const int *connI=_nodal_connec_index->getConstPointer();
1799 const int *connOther=otherOnSameCoordsThanThis._nodal_connec->getConstPointer();
1800 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1801 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1803 if(*it>=0 && *it<nbOfCells)
1805 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1809 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1810 throw INTERP_KERNEL::Exception(oss.str().c_str());
1815 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1820 DataArrayInt *arrOut=0,*arrIOut=0;
1821 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1824 setConnectivity(arrOut,arrIOut,true);
1828 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1830 checkConnectivityFullyDefined();
1831 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1832 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1834 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1836 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1837 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1838 throw INTERP_KERNEL::Exception(oss.str().c_str());
1840 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1841 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1843 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1844 throw INTERP_KERNEL::Exception(oss.str().c_str());
1846 int nbOfCells=getNumberOfCells();
1847 bool easyAssign=true;
1848 const int *conn=_nodal_connec->getConstPointer();
1849 const int *connI=_nodal_connec_index->getConstPointer();
1850 const int *connOther=otherOnSameCoordsThanThis._nodal_connec->getConstPointer();
1851 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1853 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1855 if(it>=0 && it<nbOfCells)
1857 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1861 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1862 throw INTERP_KERNEL::Exception(oss.str().c_str());
1867 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1872 DataArrayInt *arrOut=0,*arrIOut=0;
1873 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1876 setConnectivity(arrOut,arrIOut,true);
1880 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1882 std::vector<int> cellIdsKept;
1883 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
1884 DataArrayInt *ret=DataArrayInt::New();
1885 ret->alloc((int)cellIdsKept.size(),1);
1886 std::copy(cellIdsKept.begin(),cellIdsKept.end(),ret->getPointer());
1891 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1892 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
1893 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1894 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1896 * @param begin input start of array of node ids.
1897 * @param end input end of array of node ids.
1898 * @param fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
1899 * @param cellIdsKept in/out array where all candidate cell ids are put at the end.
1901 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, std::vector<int>& cellIdsKept) const
1903 std::set<int> fastFinder(begin,end);
1904 int nbOfCells=getNumberOfCells();
1905 const int *conn=getNodalConnectivity()->getConstPointer();
1906 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
1907 for(int i=0;i<nbOfCells;i++)
1909 std::set<int> connOfCell(conn+connIndex[i]+1,conn+connIndex[i+1]);
1910 connOfCell.erase(-1);//polyhedron separator
1911 int refLgth=(int)connOfCell.size();
1912 std::set<int> locMerge;
1913 std::insert_iterator< std::set<int> > it(locMerge,locMerge.begin());
1914 std::set_intersection(connOfCell.begin(),connOfCell.end(),fastFinder.begin(),fastFinder.end(),it);
1915 if(((int)locMerge.size()==refLgth && fullyIn) || (locMerge.size()!=0 && !fullyIn))
1916 cellIdsKept.push_back(i);
1921 * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
1923 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1925 std::vector<int> cellIdsKept;
1926 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1927 DataArrayInt *ret=DataArrayInt::New();
1928 ret->alloc((int)cellIdsKept.size(),1);
1929 std::copy(cellIdsKept.begin(),cellIdsKept.end(),ret->getPointer());
1930 ret->setName(getName());
1935 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1936 * The return newly allocated mesh will share the same coordinates as 'this'.
1937 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1938 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1940 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1942 std::vector<int> cellIdsKept;
1943 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1944 return buildPartOfMySelf(&cellIdsKept[0],&cellIdsKept[0]+cellIdsKept.size(),true);
1948 * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
1949 * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
1950 * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
1951 * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
1953 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1955 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
1956 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
1957 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
1958 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
1959 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
1963 * This method returns a mesh with meshDim=this->getMeshDimension()-1.
1964 * This returned mesh contains cells that are linked with one and only one cell of this.
1965 * @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.
1966 * @return mesh with ref counter equal to 1.
1968 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
1970 DataArrayInt *desc=DataArrayInt::New();
1971 DataArrayInt *descIndx=DataArrayInt::New();
1972 DataArrayInt *revDesc=DataArrayInt::New();
1973 DataArrayInt *revDescIndx=DataArrayInt::New();
1975 MEDCouplingUMesh *meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
1978 descIndx->decrRef();
1979 int nbOfCells=meshDM1->getNumberOfCells();
1980 const int *revDescIndxC=revDescIndx->getConstPointer();
1981 std::vector<int> boundaryCells;
1982 for(int i=0;i<nbOfCells;i++)
1983 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
1984 boundaryCells.push_back(i);
1985 revDescIndx->decrRef();
1986 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
1992 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
1993 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
1994 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
1996 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
1998 checkFullyDefined();
1999 DataArrayInt *desc=DataArrayInt::New();
2000 DataArrayInt *descIndx=DataArrayInt::New();
2001 DataArrayInt *revDesc=DataArrayInt::New();
2002 DataArrayInt *revDescIndx=DataArrayInt::New();
2004 MEDCouplingUMesh *meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2007 descIndx->decrRef();
2009 DataArrayInt *tmp=revDescIndx->deltaShiftIndex();
2010 DataArrayInt *faceIds=tmp->getIdsEqual(1);
2012 int nbOfFaces=faceIds->getNumberOfTuples();
2013 const int *faces=faceIds->getConstPointer();
2015 for(const int *w=faces;w!=faces+nbOfFaces;w++)
2016 ret.insert(revDesc->getIJ(revDescIndx->getIJ(*w,0),0));
2019 revDescIndx->decrRef();
2022 DataArrayInt *ret2=DataArrayInt::New();
2023 ret2->alloc((int)ret.size(),1);
2024 std::copy(ret.begin(),ret.end(),ret2->getPointer());
2025 ret2->setName("BoundaryCells");
2030 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2031 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2032 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2033 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2035 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2036 * This method method returns cells ids set s = s1 + s2 where :
2038 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2039 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2041 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2042 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2044 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2045 * \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
2046 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2048 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2050 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2052 checkConnectivityFullyDefined();
2053 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2054 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2055 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2058 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2060 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2061 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2062 DataArrayInt *idsOtherInConsti=0;
2063 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2064 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2066 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2068 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2069 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2072 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2073 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2075 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2076 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2077 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2078 neighThisPartAuto=0;
2079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2080 const int li[2]={0,1};
2081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2082 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2086 s0arr->incrRef(); cellIdsRk0=s0arr;
2087 s_renum1->incrRef(); cellIdsRk1=s_renum1;
2091 * 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
2092 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2094 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2096 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2101 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2104 revDesc=0; desc=0; descIndx=0;
2105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2107 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2111 * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2112 * The returned nodes ids are those lying on the boundary of \b this.
2114 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2116 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2117 return skin->computeFetchedNodeIds();
2120 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2123 return const_cast<MEDCouplingUMesh *>(this);
2127 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2128 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2129 * This value is asked because often known by the caller of this method.
2130 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2132 * @param newNodeNumbers array specifying the new numbering in old2New convention.
2133 * @param newNbOfNodes the new number of nodes.
2135 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2137 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2138 renumberNodesInConn(newNodeNumbers);
2142 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2143 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2144 * This value is asked because often known by the caller of this method.
2145 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2146 * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2148 * @param newNodeNumbers array specifying the new numbering.
2149 * @param newNbOfNodes the new number of nodes.
2152 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2154 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2155 renumberNodesInConn(newNodeNumbers);
2159 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2160 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2161 * 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.
2162 * 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.
2163 * 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.
2165 * \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
2166 * parameter is altered during the call.
2167 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2168 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2169 * \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.
2171 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2173 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2174 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2176 checkFullyDefined();
2177 otherDimM1OnSameCoords.checkFullyDefined();
2178 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2179 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2180 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2182 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2183 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2186 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2187 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2190 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2191 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2193 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2195 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2196 DataArrayInt *idsTmp=0;
2197 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2200 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2201 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2202 DataArrayInt *tmp0=0,*tmp1=0;
2203 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2204 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2208 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2209 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2211 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum; cellsToModifyConn0_torenum->incrRef();
2212 cellIdsNotModified=cellsToModifyConn1_torenum; cellsToModifyConn1_torenum->incrRef();
2213 nodeIdsToDuplicate=s3; s3->incrRef();
2217 * This method operates a modification of the connectivity and coords in \b this.
2218 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2219 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2220 * 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
2221 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2222 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2224 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2226 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2227 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2229 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2231 int nbOfNodes=getNumberOfNodes();
2232 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2233 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2237 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2238 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2239 * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2240 * @param [in] newNodeNumbers in old2New convention
2242 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2244 checkConnectivityFullyDefined();
2245 int *conn=getNodalConnectivity()->getPointer();
2246 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2247 int nbOfCells=getNumberOfCells();
2248 for(int i=0;i<nbOfCells;i++)
2249 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2251 int& node=conn[iconn];
2252 if(node>=0)//avoid polyhedron separator
2254 node=newNodeNumbersO2N[node];
2257 _nodal_connec->declareAsNew();
2262 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2263 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2264 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2266 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2268 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2270 checkConnectivityFullyDefined();
2271 int *conn=getNodalConnectivity()->getPointer();
2272 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2273 int nbOfCells=getNumberOfCells();
2274 for(int i=0;i<nbOfCells;i++)
2275 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2277 int& node=conn[iconn];
2278 if(node>=0)//avoid polyhedron separator
2283 _nodal_connec->declareAsNew();
2288 * This method operates a modification of the connectivity in \b this.
2289 * 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.
2290 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2291 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2292 * 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
2293 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2294 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2296 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2297 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2299 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2300 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2301 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2303 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2305 checkConnectivityFullyDefined();
2306 std::map<int,int> m;
2308 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2310 int *conn=getNodalConnectivity()->getPointer();
2311 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2312 int nbOfCells=getNumberOfCells();
2313 for(int i=0;i<nbOfCells;i++)
2314 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2316 int& node=conn[iconn];
2317 if(node>=0)//avoid polyhedron separator
2319 std::map<int,int>::iterator it=m.find(node);
2328 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2330 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2331 * After the call of this method the number of cells remains the same as before.
2333 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2334 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2335 * be strictly in [0;this->getNumberOfCells()).
2337 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2338 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2339 * should be contained in[0;this->getNumberOfCells()).
2341 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2343 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2345 checkConnectivityFullyDefined();
2346 int nbCells=getNumberOfCells();
2347 const int *array=old2NewBg;
2349 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2351 const int *conn=_nodal_connec->getConstPointer();
2352 const int *connI=_nodal_connec_index->getConstPointer();
2353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2354 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2355 newConn->copyStringInfoFrom(*_nodal_connec);
2356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2357 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2358 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2360 int *newC=newConn->getPointer();
2361 int *newCI=newConnI->getPointer();
2364 for(int i=0;i<nbCells;i++)
2366 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2367 int nbOfElts=connI[pos+1]-connI[pos];
2368 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2373 setConnectivity(newConn,newConnI);
2375 delete [] const_cast<int *>(array);
2379 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2380 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2381 * added in 'elems' parameter.
2383 void MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps, std::vector<int>& elems) const
2385 if(getMeshDimension()==-1)
2390 int dim=getSpaceDimension();
2391 double* elem_bb=new double[2*dim];
2392 const int* conn = getNodalConnectivity()->getConstPointer();
2393 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2394 const double* coords = getCoords()->getConstPointer();
2395 int nbOfCells=getNumberOfCells();
2396 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2398 for (int i=0; i<dim; i++)
2400 elem_bb[i*2]=std::numeric_limits<double>::max();
2401 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2404 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2406 int node= conn[inode];
2407 if(node>=0)//avoid polyhedron separator
2409 for (int idim=0; idim<dim; idim++)
2411 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2413 elem_bb[idim*2] = coords[node*dim+idim] ;
2415 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2417 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2422 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2424 elems.push_back(ielem);
2431 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2432 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2433 * added in 'elems' parameter.
2435 void MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps, std::vector<int>& elems)
2437 if(getMeshDimension()==-1)
2442 int dim=getSpaceDimension();
2443 double* elem_bb=new double[2*dim];
2444 const int* conn = getNodalConnectivity()->getConstPointer();
2445 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2446 const double* coords = getCoords()->getConstPointer();
2447 int nbOfCells=getNumberOfCells();
2448 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2450 for (int i=0; i<dim; i++)
2452 elem_bb[i*2]=std::numeric_limits<double>::max();
2453 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2456 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2458 int node= conn[inode];
2459 if(node>=0)//avoid polyhedron separator
2461 for (int idim=0; idim<dim; idim++)
2463 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2465 elem_bb[idim*2] = coords[node*dim+idim] ;
2467 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2469 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2474 if (intersectsBoundingBox(bbox, elem_bb, dim, eps))
2476 elems.push_back(ielem);
2483 * Returns the cell type of cell with id 'cellId'.
2485 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2487 const int *ptI=_nodal_connec_index->getConstPointer();
2488 const int *pt=_nodal_connec->getConstPointer();
2489 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2493 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2494 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2495 * The coordinates array is not considered here.
2497 * \param [in] type the geometric type
2500 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2504 checkConnectivityFullyDefined();
2505 int nbCells=getNumberOfCells();
2506 int mdim=getMeshDimension();
2507 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2508 if(mdim!=(int)cm.getDimension())
2509 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2510 const int *ptI=_nodal_connec_index->getConstPointer();
2511 const int *pt=_nodal_connec->getConstPointer();
2512 for(int i=0;i<nbCells;i++)
2514 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc((int)v.size(),1);
2518 std::copy(v.begin(),v.end(),ret->getPointer());
2524 * Returns nb of cells having the geometric type 'type'.
2526 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2528 const int *ptI=_nodal_connec_index->getConstPointer();
2529 const int *pt=_nodal_connec->getConstPointer();
2530 int nbOfCells=getNumberOfCells();
2532 for(int i=0;i<nbOfCells;i++)
2533 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2539 * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2540 * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2541 * That is to say -1 separator is omitted in returned conn.
2543 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2545 const int *ptI=_nodal_connec_index->getConstPointer();
2546 const int *pt=_nodal_connec->getConstPointer();
2547 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2552 std::string MEDCouplingUMesh::simpleRepr() const
2554 static const char msg0[]="No coordinates specified !";
2555 std::ostringstream ret;
2556 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2557 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2559 double tt=getTime(tmpp1,tmpp2);
2560 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2561 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2562 ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2565 const int spaceDim=getSpaceDimension();
2566 ret << spaceDim << "\nInfo attached on space dimension : ";
2567 for(int i=0;i<spaceDim;i++)
2568 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2572 ret << msg0 << "\n";
2573 ret << "Number of nodes : ";
2575 ret << getNumberOfNodes() << "\n";
2577 ret << msg0 << "\n";
2578 ret << "Number of cells : ";
2579 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2580 ret << getNumberOfCells() << "\n";
2582 ret << "No connectivity specified !" << "\n";
2583 ret << "Cell types present : ";
2584 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2586 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2587 ret << cm.getRepr() << " ";
2593 std::string MEDCouplingUMesh::advancedRepr() const
2595 std::ostringstream ret;
2596 ret << simpleRepr();
2597 ret << "\nCoordinates array : \n___________________\n\n";
2599 _coords->reprWithoutNameStream(ret);
2601 ret << "No array set !\n";
2602 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2603 reprConnectivityOfThisLL(ret);
2607 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2609 std::ostringstream ret;
2610 reprConnectivityOfThisLL(ret);
2615 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2616 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2617 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2620 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2621 * 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
2622 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2624 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2626 int mdim=getMeshDimension();
2628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2629 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2631 bool needToCpyCT=true;
2634 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2642 if(!_nodal_connec_index)
2644 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2649 tmp2=_nodal_connec_index;
2652 ret->setConnectivity(tmp1,tmp2,false);
2657 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2658 ret->setCoords(coords);
2661 ret->setCoords(_coords);
2666 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2668 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2670 int nbOfCells=getNumberOfCells();
2671 const int *c=_nodal_connec->getConstPointer();
2672 const int *ci=_nodal_connec_index->getConstPointer();
2673 for(int i=0;i<nbOfCells;i++)
2675 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2676 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2677 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2682 stream << "Connectivity not defined !\n";
2685 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2687 const int *ptI=_nodal_connec_index->getConstPointer();
2688 const int *pt=_nodal_connec->getConstPointer();
2689 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2690 return ptI[cellId+1]-ptI[cellId]-1;
2692 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2696 * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2697 * This method avoids to compute explicitely submesh to get its types.
2699 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2701 checkFullyDefined();
2702 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2703 const int *conn=_nodal_connec->getConstPointer();
2704 const int *connIndex=_nodal_connec_index->getConstPointer();
2705 for(const int *w=begin;w!=end;w++)
2706 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2711 * Method reserved for advanced users having prepared their connectivity before.
2712 * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2714 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2716 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2717 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2718 if(isComputingTypes)
2724 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2725 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2727 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_iterator(-1),_mesh_dim(other._mesh_dim),
2728 _nodal_connec(0),_nodal_connec_index(0),
2729 _types(other._types)
2731 if(other._nodal_connec)
2732 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2733 if(other._nodal_connec_index)
2734 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2737 MEDCouplingUMesh::~MEDCouplingUMesh()
2740 _nodal_connec->decrRef();
2741 if(_nodal_connec_index)
2742 _nodal_connec_index->decrRef();
2746 * This method recomputes all cell types of 'this'.
2748 void MEDCouplingUMesh::computeTypes()
2750 if(_nodal_connec && _nodal_connec_index)
2753 const int *conn=_nodal_connec->getConstPointer();
2754 const int *connIndex=_nodal_connec_index->getConstPointer();
2755 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2756 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
2757 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2762 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2764 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2766 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2767 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2771 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2773 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2775 if(!_nodal_connec_index || !_nodal_connec)
2776 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2779 int MEDCouplingUMesh::getNumberOfCells() const
2781 if(_nodal_connec_index)
2783 return _nodal_connec_index->getNumberOfTuples()-1;
2790 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2793 int MEDCouplingUMesh::getMeshDimension() const
2796 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2801 * This method is for test reason. Normally the integer returned is not useable by user.
2803 int MEDCouplingUMesh::getMeshLength() const
2805 return _nodal_connec->getNbOfElems();
2809 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2811 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2813 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2814 tinyInfo.push_back(getMeshDimension());
2815 tinyInfo.push_back(getNumberOfCells());
2817 tinyInfo.push_back(getMeshLength());
2819 tinyInfo.push_back(-1);
2823 * First step of unserialization process.
2825 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2827 return tinyInfo[6]<=0;
2831 * Second step of serialization process.
2832 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2834 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2836 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2838 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2842 * Third and final step of serialization process.
2844 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2846 MEDCouplingPointSet::serialize(a1,a2);
2847 if(getMeshDimension()>-1)
2849 a1=DataArrayInt::New();
2850 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2851 int *ptA1=a1->getPointer();
2852 const int *conn=getNodalConnectivity()->getConstPointer();
2853 const int *index=getNodalConnectivityIndex()->getConstPointer();
2854 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2855 std::copy(conn,conn+getMeshLength(),ptA1);
2862 * Second and final unserialization process.
2863 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2865 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2867 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2868 setMeshDimension(tinyInfo[5]);
2872 const int *recvBuffer=a1->getConstPointer();
2873 DataArrayInt* myConnecIndex=DataArrayInt::New();
2874 myConnecIndex->alloc(tinyInfo[6]+1,1);
2875 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2876 DataArrayInt* myConnec=DataArrayInt::New();
2877 myConnec->alloc(tinyInfo[7],1);
2878 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2879 setConnectivity(myConnec, myConnecIndex) ;
2880 myConnec->decrRef();
2881 myConnecIndex->decrRef();
2886 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2887 * CellIds are given using range specified by a start an end and step.
2889 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2891 checkFullyDefined();
2892 int ncell=getNumberOfCells();
2893 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2894 ret->_mesh_dim=_mesh_dim;
2895 ret->setCoords(_coords);
2896 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2898 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2900 const int *conn=_nodal_connec->getConstPointer();
2901 const int *connIndex=_nodal_connec_index->getConstPointer();
2902 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2904 if(work>=0 && work<ncell)
2906 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2910 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2911 throw INTERP_KERNEL::Exception(oss.str().c_str());
2914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
2915 int *newConnPtr=newConn->getPointer();
2916 std::set<INTERP_KERNEL::NormalizedCellType> types;
2918 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2920 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
2921 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
2923 ret->setConnectivity(newConn,newConnI,false);
2925 ret->copyTinyInfoFrom(this);
2926 std::string name(getName());
2927 std::size_t sz=strlen(PART_OF_NAME);
2928 if(name.length()>=sz)
2929 name=name.substr(0,sz);
2930 if(name!=PART_OF_NAME)
2932 std::ostringstream stream; stream << PART_OF_NAME << getName();
2933 ret->setName(stream.str().c_str());
2936 ret->setName(getName());
2942 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
2943 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2944 * The return newly allocated mesh will share the same coordinates as 'this'.
2946 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
2948 checkFullyDefined();
2949 int ncell=getNumberOfCells();
2950 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2951 ret->_mesh_dim=_mesh_dim;
2952 ret->setCoords(_coords);
2953 std::size_t nbOfElemsRet=std::distance(begin,end);
2954 int *connIndexRet=new int[nbOfElemsRet+1];
2956 const int *conn=_nodal_connec->getConstPointer();
2957 const int *connIndex=_nodal_connec_index->getConstPointer();
2959 for(const int *work=begin;work!=end;work++,newNbring++)
2961 if(*work>=0 && *work<ncell)
2962 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
2965 delete [] connIndexRet;
2966 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
2967 throw INTERP_KERNEL::Exception(oss.str().c_str());
2970 int *connRet=new int[connIndexRet[nbOfElemsRet]];
2971 int *connRetWork=connRet;
2972 std::set<INTERP_KERNEL::NormalizedCellType> types;
2973 for(const int *work=begin;work!=end;work++)
2975 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
2976 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
2978 DataArrayInt *connRetArr=DataArrayInt::New();
2979 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
2980 DataArrayInt *connIndexRetArr=DataArrayInt::New();
2981 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
2982 ret->setConnectivity(connRetArr,connIndexRetArr,false);
2984 connRetArr->decrRef();
2985 connIndexRetArr->decrRef();
2986 ret->copyTinyInfoFrom(this);
2987 std::string name(getName());
2988 std::size_t sz=strlen(PART_OF_NAME);
2989 if(name.length()>=sz)
2990 name=name.substr(0,sz);
2991 if(name!=PART_OF_NAME)
2993 std::ostringstream stream; stream << PART_OF_NAME << getName();
2994 ret->setName(stream.str().c_str());
2997 ret->setName(getName());
3003 * brief returns the volumes of the cells underlying the field \a field
3005 * For 2D geometries, the returned field contains the areas.
3006 * For 3D geometries, the returned field contains the volumes.
3008 * param field field on which cells the volumes are required
3009 * return field containing the volumes, area or length depending the meshdimension.
3011 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3013 std::string name="MeasureOfMesh_";
3015 int nbelem=getNumberOfCells();
3016 MEDCouplingFieldDouble *field=MEDCouplingFieldDouble::New(ON_CELLS);
3017 field->setName(name.c_str());
3018 DataArrayDouble* array=DataArrayDouble::New();
3019 array->alloc(nbelem,1);
3020 double *area_vol=array->getPointer();
3021 field->setArray(array) ;
3023 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3024 if(getMeshDimension()!=-1)
3027 INTERP_KERNEL::NormalizedCellType type;
3028 int dim_space=getSpaceDimension();
3029 const double *coords=getCoords()->getConstPointer();
3030 const int *connec=getNodalConnectivity()->getConstPointer();
3031 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3032 for(int iel=0;iel<nbelem;iel++)
3034 ipt=connec_index[iel];
3035 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3036 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);
3039 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3043 area_vol[0]=std::numeric_limits<double>::max();
3049 * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3050 * This method avoids to build explicitely part of this to perform the work.
3052 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3054 std::string name="PartMeasureOfMesh_";
3056 int nbelem=(int)std::distance(begin,end);
3057 DataArrayDouble* array=DataArrayDouble::New();
3058 array->setName(name.c_str());
3059 array->alloc(nbelem,1);
3060 double *area_vol=array->getPointer();
3061 if(getMeshDimension()!=-1)
3064 INTERP_KERNEL::NormalizedCellType type;
3065 int dim_space=getSpaceDimension();
3066 const double *coords=getCoords()->getConstPointer();
3067 const int *connec=getNodalConnectivity()->getConstPointer();
3068 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3069 for(const int *iel=begin;iel!=end;iel++)
3071 ipt=connec_index[*iel];
3072 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3073 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3076 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3080 area_vol[0]=std::numeric_limits<double>::max();
3086 * This methods returns a field on nodes and no time. This method is usefull to check "P1*" conservative interpolators.
3087 * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3089 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3091 MEDCouplingFieldDouble *tmp=getMeasureField(isAbs);
3092 std::string name="MeasureOnNodeOfMesh_";
3094 int nbNodes=getNumberOfNodes();
3095 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_NODES);
3096 double cst=1./((double)getMeshDimension()+1.);
3097 DataArrayDouble* array=DataArrayDouble::New();
3098 array->alloc(nbNodes,1);
3099 double *valsToFill=array->getPointer();
3100 std::fill(valsToFill,valsToFill+nbNodes,0.);
3101 const double *values=tmp->getArray()->getConstPointer();
3102 DataArrayInt *da=DataArrayInt::New();
3103 DataArrayInt *daInd=DataArrayInt::New();
3104 getReverseNodalConnectivity(da,daInd);
3105 const int *daPtr=da->getConstPointer();
3106 const int *daIPtr=daInd->getConstPointer();
3107 for(int i=0;i<nbNodes;i++)
3108 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3109 valsToFill[i]+=cst*values[*cell];
3113 ret->setArray(array);
3120 * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3121 * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3123 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3125 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3126 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3127 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
3128 DataArrayDouble *array=DataArrayDouble::New();
3129 int nbOfCells=getNumberOfCells();
3130 int nbComp=getMeshDimension()+1;
3131 array->alloc(nbOfCells,nbComp);
3132 double *vals=array->getPointer();
3133 const int *connI=_nodal_connec_index->getConstPointer();
3134 const int *conn=_nodal_connec->getConstPointer();
3135 const double *coords=_coords->getConstPointer();
3136 if(getMeshDimension()==2)
3138 if(getSpaceDimension()==3)
3140 DataArrayDouble *loc=getBarycenterAndOwner();
3141 const double *locPtr=loc->getConstPointer();
3142 for(int i=0;i<nbOfCells;i++,vals+=3)
3144 int offset=connI[i];
3145 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3146 double n=INTERP_KERNEL::norm<3>(vals);
3147 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3153 for(int i=0;i<nbOfCells;i++)
3154 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3157 else//meshdimension==1
3160 for(int i=0;i<nbOfCells;i++)
3162 int offset=connI[i];
3163 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3164 double n=INTERP_KERNEL::norm<2>(tmp);
3165 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3170 ret->setArray(array);
3177 * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3178 * This method avoids to build explicitely part of this to perform the work.
3180 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3182 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3183 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3184 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
3185 DataArrayDouble *array=DataArrayDouble::New();
3186 std::size_t nbelems=std::distance(begin,end);
3187 int nbComp=getMeshDimension()+1;
3188 array->alloc((int)nbelems,nbComp);
3189 double *vals=array->getPointer();
3190 const int *connI=_nodal_connec_index->getConstPointer();
3191 const int *conn=_nodal_connec->getConstPointer();
3192 const double *coords=_coords->getConstPointer();
3193 if(getMeshDimension()==2)
3195 if(getSpaceDimension()==3)
3197 DataArrayDouble *loc=getPartBarycenterAndOwner(begin,end);
3198 const double *locPtr=loc->getConstPointer();
3199 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3201 int offset=connI[*i];
3202 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3203 double n=INTERP_KERNEL::norm<3>(vals);
3204 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3210 for(std::size_t i=0;i<nbelems;i++)
3211 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3214 else//meshdimension==1
3217 for(const int *i=begin;i!=end;i++)
3219 int offset=connI[*i];
3220 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3221 double n=INTERP_KERNEL::norm<2>(tmp);
3222 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3227 ret->setArray(array);
3234 * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3235 * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3237 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3239 if(getMeshDimension()!=1)
3240 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3241 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3242 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3243 MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
3244 DataArrayDouble *array=DataArrayDouble::New();
3245 int nbOfCells=getNumberOfCells();
3246 int spaceDim=getSpaceDimension();
3247 array->alloc(nbOfCells,spaceDim);
3248 double *pt=array->getPointer();
3249 const double *coo=getCoords()->getConstPointer();
3250 std::vector<int> conn;
3252 for(int i=0;i<nbOfCells;i++)
3255 getNodeIdsOfCell(i,conn);
3256 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3258 ret->setArray(array);
3265 * 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.
3266 * This method returns 2 objects :
3267 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3268 * - 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
3269 * mesh the 3D cell id is 'this' it comes from.
3270 * This method works only for linear meshes (non quadratic).
3271 * 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
3272 * face. Only 'cellIds' parameter can distinguish the 2.
3273 * @param origin is the origin of the plane. It should be an array of length 3.
3274 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3275 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3276 * 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).
3278 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3280 checkFullyDefined();
3281 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3284 if(candidates->empty())
3285 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3286 std::vector<int> nodes;
3287 std::vector<int> cellIds2D,cellIds1D;
3288 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3289 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3294 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3295 revDesc2=0; revDescIndx2=0;
3296 mDesc2->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds2D);
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);
3301 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3302 for(std::vector<int>::const_iterator it=cellIds1D.begin();it!=cellIds1D.end();it++)
3304 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3305 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3306 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3307 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3308 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3309 std::vector<int> conn,connI,cellIds2;
3311 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3312 if(cellIds2.empty())
3313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3314 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3315 ret->setCoords(mDesc1->getCoords());
3316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
3317 c->alloc((int)conn.size(),1); std::copy(conn.begin(),conn.end(),c->getPointer());
3318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
3319 cI->alloc((int)connI.size(),1); std::copy(connI.begin(),connI.end(),cI->getPointer());
3320 ret->setConnectivity(c,cI,true);
3321 cellIds=candidates->selectByTupleId(&cellIds2[0],&cellIds2[0]+cellIds2.size());
3327 * 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.
3328 * This method returns 2 objects :
3329 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3330 * - 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
3331 * mesh the 3DSurf cell id is 'this' it comes from.
3332 * This method works only for linear meshes (non quadratic).
3333 * 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
3334 * face. Only 'cellIds' parameter can distinguish the 2.
3335 * @param origin is the origin of the plane. It should be an array of length 3.
3336 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3337 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3338 * 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).
3340 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3342 checkFullyDefined();
3343 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3346 if(candidates->empty())
3347 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3348 std::vector<int> nodes;
3349 std::vector<int> cellIds1D;
3350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3351 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3356 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3357 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3359 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3360 for(std::vector<int>::const_iterator it=cellIds1D.begin();it!=cellIds1D.end();it++)
3362 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3363 int ncellsSub=subMesh->getNumberOfCells();
3364 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3365 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3366 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3367 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3368 std::vector<int> conn,connI,cellIds2; connI.push_back(0);
3369 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3370 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3371 for(int i=0;i<ncellsSub;i++)
3373 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3375 if(cut3DSurf[i].first!=-2)
3377 conn.push_back((int)INTERP_KERNEL::NORM_SEG2); conn.push_back(cut3DSurf[i].first); conn.push_back(cut3DSurf[i].second);
3378 connI.push_back((int)conn.size());
3379 cellIds2.push_back(i);
3383 int cellId3DSurf=cut3DSurf[i].second;
3384 int offset=nodalI[cellId3DSurf]+1;
3385 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3386 for(int j=0;j<nbOfEdges;j++)
3388 conn.push_back((int)INTERP_KERNEL::NORM_SEG2); conn.push_back(nodal[offset+j]); conn.push_back(nodal[offset+(j+1)%nbOfEdges]);
3389 connI.push_back((int)conn.size());
3390 cellIds2.push_back(cellId3DSurf);
3395 if(cellIds2.empty())
3396 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3397 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3398 ret->setCoords(mDesc1->getCoords());
3399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
3400 c->alloc((int)conn.size(),1); std::copy(conn.begin(),conn.end(),c->getPointer());
3401 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
3402 cI->alloc((int)connI.size(),1); std::copy(connI.begin(),connI.end(),cI->getPointer());
3403 ret->setConnectivity(c,cI,true);
3404 cellIds=candidates->selectByTupleId(&cellIds2[0],&cellIds2[0]+cellIds2.size());
3410 * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3411 * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3412 * @param origin is the origin of the plane. It should be an array of length 3.
3413 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3415 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3417 checkFullyDefined();
3418 if(getSpaceDimension()!=3)
3419 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3420 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3422 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3424 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3425 double angle=acos(vec[2]/normm);
3426 std::vector<int> cellIds;
3430 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3431 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3432 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3434 mw->getBoundingBox(bbox);
3435 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3436 mw->getCellsInBoundingBox(bbox,eps,cellIds);
3440 getBoundingBox(bbox);
3441 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3442 getCellsInBoundingBox(bbox,eps,cellIds);
3444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
3445 ret->alloc((int)cellIds.size(),1);
3446 std::copy(cellIds.begin(),cellIds.end(),ret->getPointer());
3452 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3453 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3454 * No consideration of coordinate is done by this method.
3455 * 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)
3456 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3458 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3460 if(getMeshDimension()!=1)
3461 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3462 int nbCells=getNumberOfCells();
3464 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3465 const int *connI=_nodal_connec_index->getConstPointer();
3466 const int *conn=_nodal_connec->getConstPointer();
3467 int ref=conn[connI[0]+2];
3468 for(int i=1;i<nbCells;i++)
3470 if(conn[connI[i]+1]!=ref)
3472 ref=conn[connI[i]+2];
3478 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3479 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3480 * @param pt reference point of the line
3481 * @param v normalized director vector of the line
3482 * @param eps max precision before throwing an exception
3483 * @param res output of size this->getNumberOfCells
3485 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3487 if(getMeshDimension()!=1)
3488 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3489 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3490 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3491 if(getSpaceDimension()!=3)
3492 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3493 MEDCouplingFieldDouble *f=buildDirectionVectorField();
3494 const double *fPtr=f->getArray()->getConstPointer();
3496 for(int i=0;i<getNumberOfCells();i++)
3498 const double *tmp1=fPtr+3*i;
3499 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3500 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3501 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3502 double n1=INTERP_KERNEL::norm<3>(tmp);
3503 n1/=INTERP_KERNEL::norm<3>(tmp1);
3507 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3510 const double *coo=getCoords()->getConstPointer();
3511 for(int i=0;i<getNumberOfNodes();i++)
3513 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3514 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3515 res[i]=std::accumulate(tmp,tmp+3,0.);
3521 * Returns a cell if any that contains the point located on 'pos' with precison eps.
3522 * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3523 * \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'
3524 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3526 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3528 std::vector<int> elts;
3529 getCellsContainingPoint(pos,eps,elts);
3532 return elts.front();
3536 * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3537 * \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'
3538 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3540 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3542 std::vector<int> eltsIndex;
3543 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3548 namespace ParaMEDMEM
3550 template<const int SPACEDIMM>
3554 static const int MY_SPACEDIM=SPACEDIMM;
3555 static const int MY_MESHDIM=8;
3556 typedef int MyConnType;
3557 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3559 // useless, but for windows compilation ...
3560 const double* getCoordinatesPtr() const { return 0; }
3561 const int* getConnectivityPtr() const { return 0; }
3562 const int* getConnectivityIndexPtr() const { return 0; }
3563 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3567 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3569 INTERP_KERNEL::Edge *ret=0;
3572 case INTERP_KERNEL::NORM_SEG2:
3574 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3577 case INTERP_KERNEL::NORM_SEG3:
3579 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3580 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3581 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3582 bool colinearity=inters.areColinears();
3583 delete e1; delete e2;
3585 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3587 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3588 mapp2[bg[2]].second=false;
3592 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3598 * 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'.
3599 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3600 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3602 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3605 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.
3606 const double *coo=mDesc->getCoords()->getConstPointer();
3607 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3608 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3610 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3611 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3612 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3614 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3615 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3617 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3618 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3620 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3621 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3623 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3625 if((*it2).second.second)
3626 mapp[(*it2).second.first]=(*it2).first;
3627 ((*it2).second.first)->decrRef();
3632 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3636 int locId=nodeId-offset2;
3637 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3641 int locId=nodeId-offset1;
3642 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3644 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3647 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3648 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3649 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3651 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3653 int eltId1=abs(*desc1)-1;
3654 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3656 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3657 if(it==mappRev.end())
3659 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3670 template<int SPACEDIM>
3671 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3672 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3674 std::vector<double> bbox;
3675 eltsIndex.resize(nbOfPoints+1);
3678 getBoundingBoxForBBTree(bbox);
3679 int nbOfCells=getNumberOfCells();
3680 const int *conn=_nodal_connec->getConstPointer();
3681 const int *connI=_nodal_connec_index->getConstPointer();
3682 double bb[2*SPACEDIM];
3683 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3684 for(int i=0;i<nbOfPoints;i++)
3686 eltsIndex[i+1]=eltsIndex[i];
3687 for(int j=0;j<SPACEDIM;j++)
3689 bb[2*j]=pos[SPACEDIM*i+j];
3690 bb[2*j+1]=pos[SPACEDIM*i+j];
3692 std::vector<int> candidates;
3693 myTree.getIntersectingElems(bb,candidates);
3694 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3696 int sz=connI[(*iter)+1]-connI[*iter]-1;
3697 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3698 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3699 coords,conn+connI[*iter]+1,sz,eps))
3702 elts.push_back(*iter);
3709 * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3710 * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3711 * in case of multi points searching.
3712 * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3713 * 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]).
3715 * \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...
3717 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3718 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3720 int spaceDim=getSpaceDimension();
3721 int mDim=getMeshDimension();
3726 const double *coords=_coords->getConstPointer();
3727 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3734 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3736 else if(spaceDim==2)
3740 const double *coords=_coords->getConstPointer();
3741 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3744 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3746 else if(spaceDim==1)
3750 const double *coords=_coords->getConstPointer();
3751 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3754 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3757 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3761 * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3762 * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3763 * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3764 * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3766 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3768 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3769 if(getMeshDimension()!=2)
3770 throw INTERP_KERNEL::Exception(msg);
3771 int spaceDim=getSpaceDimension();
3772 if(spaceDim!=2 && spaceDim!=3)
3773 throw INTERP_KERNEL::Exception(msg);
3774 const int *conn=_nodal_connec->getConstPointer();
3775 const int *connI=_nodal_connec_index->getConstPointer();
3776 int nbOfCells=getNumberOfCells();
3777 std::vector<double> cell2DinS2;
3778 for(int i=0;i<nbOfCells;i++)
3780 int offset=connI[i];
3781 int nbOfNodesForCell=connI[i+1]-offset-1;
3782 if(nbOfNodesForCell<=3)
3784 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3785 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3786 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3793 * This method is typically requested to unbutterfly 2D linear cells in \b this.
3795 * 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.
3796 * 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.
3798 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3799 * This convex envelop is computed using Jarvis march algorithm.
3800 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3801 * 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)
3802 * 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.
3804 * @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.
3806 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3808 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3809 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
3810 checkFullyDefined();
3811 const double *coords=getCoords()->getConstPointer();
3812 int nbOfCells=getNumberOfCells();
3813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3814 nodalConnecIndexOut->alloc(nbOfCells+1,1);
3815 std::vector<int> nodalConnecOut;
3816 int *workIndexOut=nodalConnecIndexOut->getPointer();
3818 const int *nodalConnecIn=_nodal_connec->getConstPointer();
3819 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3820 std::set<INTERP_KERNEL::NormalizedCellType> types;
3821 std::vector<int> isChanged;
3822 for(int i=0;i<nbOfCells;i++,workIndexOut++)
3824 std::size_t pos=nodalConnecOut.size();
3825 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3826 isChanged.push_back(i);
3827 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut[pos]);
3828 workIndexOut[1]=(int)nodalConnecOut.size();
3830 if(isChanged.empty())
3832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut2=DataArrayInt::New();
3833 nodalConnecOut2->alloc((int)nodalConnecOut.size(),1);
3834 std::copy(nodalConnecOut.begin(),nodalConnecOut.end(),nodalConnecOut2->getPointer());
3835 setConnectivity(nodalConnecOut2,nodalConnecIndexOut,false);
3837 DataArrayInt *ret=DataArrayInt::New(); ret->alloc((int)isChanged.size(),1);
3838 std::copy(isChanged.begin(),isChanged.end(),ret->getPointer());
3843 * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
3844 * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
3845 * 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).
3846 * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
3848 void MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells(std::vector<int>& cells) throw(INTERP_KERNEL::Exception)
3850 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
3851 if(getMeshDimension()!=3)
3852 throw INTERP_KERNEL::Exception(msg);
3853 int spaceDim=getSpaceDimension();
3855 throw INTERP_KERNEL::Exception(msg);
3857 int nbOfCells=getNumberOfCells();
3858 int *conn=_nodal_connec->getPointer();
3859 const int *connI=_nodal_connec_index->getConstPointer();
3860 const double *coo=getCoords()->getConstPointer();
3861 double vec0[3],vec1[3];
3862 for(int i=0;i<nbOfCells;i++)
3864 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
3865 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
3867 INTERP_KERNEL::AutoPtr<int> tmp=new int[connI[i+1]-connI[i]-1];
3868 int nbOfNodes=cm.fillSonCellNodalConnectivity(0,conn+connI[i]+1,tmp);
3869 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(tmp,nbOfNodes,coo,vec0);
3870 const double *pt0=coo+3*conn[connI[i]+1];
3871 const double *pt1=coo+3*conn[connI[i]+nbOfNodes+1];
3872 vec1[0]=pt0[0]-pt1[0]; vec1[1]=pt0[1]-pt1[1]; vec1[2]=pt0[2]-pt1[2];
3873 double dot=vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2];
3877 std::copy(conn+connI[i]+1,conn+connI[i+1],(int *)tmp);
3878 for(int j=1;j<nbOfNodes;j++)
3880 conn[connI[i]+1+j]=tmp[nbOfNodes-j];
3881 conn[connI[i]+1+j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
3889 * This method is \b NOT const because it can modify 'this'.
3890 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
3891 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
3892 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
3893 * \b 1 for translation and rotation around point of 'mesh1D'.
3894 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
3896 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
3898 checkFullyDefined();
3899 mesh1D->checkFullyDefined();
3900 if(!mesh1D->isContiguous1D())
3901 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
3902 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
3903 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same dimension !");
3904 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3905 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
3906 if(mesh1D->getMeshDimension()!=1)
3907 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
3909 if(isPresenceOfQuadratic())
3911 if(mesh1D->isFullyQuadratic())
3914 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
3917 int oldNbOfNodes=getNumberOfNodes();
3918 DataArrayDouble *newCoords=0;
3923 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
3928 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
3932 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
3934 setCoords(newCoords);
3935 newCoords->decrRef();
3936 MEDCouplingUMesh *ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
3942 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
3943 * If it is not the case an exception will be thrown.
3944 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
3945 * intersection of plane defined by ('origin','vec').
3946 * This method has one in/out parameter : 'cut3DCurve'.
3947 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
3948 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
3949 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
3950 * This method will throw an exception if 'this' contains a non linear segment.
3952 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
3954 checkFullyDefined();
3955 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
3956 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
3957 int ncells=getNumberOfCells();
3958 int nnodes=getNumberOfNodes();
3959 double vec2[3],vec3[3],vec4[3];
3960 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3962 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3963 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
3964 const int *conn=_nodal_connec->getConstPointer();
3965 const int *connI=_nodal_connec_index->getConstPointer();
3966 const double *coo=_coords->getConstPointer();
3967 std::vector<double> addCoo;
3968 for(int i=0;i<ncells;i++)
3970 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
3972 if(cut3DCurve[i]==-2)
3974 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
3975 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];
3976 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
3977 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
3978 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
3980 const double *st2=coo+3*st;
3981 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
3982 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]));
3983 if(pos>eps && pos<1-eps)
3985 int nNode=((int)addCoo.size())/3;
3986 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
3987 addCoo.insert(addCoo.end(),vec4,vec4+3);
3988 cut3DCurve[i]=nnodes+nNode;
3994 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
3998 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
3999 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4000 coo2->alloc(newNbOfNodes,3);
4001 double *tmp=coo2->getPointer();
4002 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4003 std::copy(addCoo.begin(),addCoo.end(),tmp);
4004 DataArrayDouble::SetArrayIn(coo2,_coords);
4009 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4010 * @param mesh1D is the input 1D mesh used for translation computation.
4011 * @return newCoords new coords filled by this method.
4013 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4015 int oldNbOfNodes=getNumberOfNodes();
4016 int nbOf1DCells=mesh1D->getNumberOfCells();
4017 int spaceDim=getSpaceDimension();
4018 DataArrayDouble *ret=DataArrayDouble::New();
4019 std::vector<bool> isQuads;
4020 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4021 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4022 double *retPtr=ret->getPointer();
4023 const double *coords=getCoords()->getConstPointer();
4024 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4026 std::vector<double> c;
4030 for(int i=0;i<nbOf1DCells;i++)
4033 mesh1D->getNodeIdsOfCell(i,v);
4035 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4036 mesh1D->getCoordinatesOfNode(v[0],c);
4037 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4038 for(int j=0;j<oldNbOfNodes;j++)
4039 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4043 mesh1D->getCoordinatesOfNode(v[1],c);
4044 mesh1D->getCoordinatesOfNode(v[0],c);
4045 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4046 for(int j=0;j<oldNbOfNodes;j++)
4047 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4050 ret->copyStringInfoFrom(*getCoords());
4055 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4056 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4057 * @return newCoords new coords filled by this method.
4059 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4061 if(mesh1D->getSpaceDimension()==2)
4062 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4063 if(mesh1D->getSpaceDimension()==3)
4064 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4065 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4069 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4070 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4071 * @return newCoords new coords filled by this method.
4073 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4076 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4077 int oldNbOfNodes=getNumberOfNodes();
4078 int nbOf1DCells=mesh1D->getNumberOfCells();
4080 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4081 DataArrayDouble *ret=DataArrayDouble::New();
4082 int nbOfLevsInVec=nbOf1DCells+1;
4083 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4084 double *retPtr=ret->getPointer();
4085 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4086 MEDCouplingUMesh *tmp=MEDCouplingUMesh::New();
4087 DataArrayDouble *tmp2=getCoords()->deepCpy();
4088 tmp->setCoords(tmp2);
4090 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4091 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4092 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4093 for(int i=1;i<nbOfLevsInVec;i++)
4095 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4096 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4097 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4098 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4099 tmp->translate(vec);
4100 double tmp3[2],radius,alpha,alpha0;
4101 const double *p0=i+1<nbOfLevsInVec?begin:third;
4102 const double *p1=i+1<nbOfLevsInVec?end:begin;
4103 const double *p2=i+1<nbOfLevsInVec?third:end;
4104 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4105 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]);
4106 double angle=acos(cosangle/(radius*radius));
4107 tmp->rotate(end,0,angle);
4108 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4115 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4116 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4117 * @return newCoords new coords filled by this method.
4119 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4122 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4123 int oldNbOfNodes=getNumberOfNodes();
4124 int nbOf1DCells=mesh1D->getNumberOfCells();
4126 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4127 DataArrayDouble *ret=DataArrayDouble::New();
4128 int nbOfLevsInVec=nbOf1DCells+1;
4129 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4130 double *retPtr=ret->getPointer();
4131 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4132 MEDCouplingUMesh *tmp=MEDCouplingUMesh::New();
4133 DataArrayDouble *tmp2=getCoords()->deepCpy();
4134 tmp->setCoords(tmp2);
4136 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4137 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4138 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4139 for(int i=1;i<nbOfLevsInVec;i++)
4141 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4142 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4143 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4144 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4145 tmp->translate(vec);
4146 double tmp3[2],radius,alpha,alpha0;
4147 const double *p0=i+1<nbOfLevsInVec?begin:third;
4148 const double *p1=i+1<nbOfLevsInVec?end:begin;
4149 const double *p2=i+1<nbOfLevsInVec?third:end;
4150 double vecPlane[3]={
4151 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4152 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4153 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4155 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4158 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4159 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4160 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4162 double c2=cos(asin(s2));
4164 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4165 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4166 {-vec2[1]*s2, vec2[0]*s2, c2}
4168 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]};
4169 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]};
4170 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]};
4171 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4172 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]);
4173 double angle=acos(cosangle/(radius*radius));
4174 tmp->rotate(end,vecPlane,angle);
4177 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4184 * This method is private because not easy to use for end user. This method is const contrary to
4185 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4186 * the coords sorted slice by slice.
4187 * @param isQuad specifies presence of quadratic cells.
4189 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4191 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4192 int nbOf2DCells=getNumberOfCells();
4193 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4194 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4195 const int *conn=_nodal_connec->getConstPointer();
4196 const int *connI=_nodal_connec_index->getConstPointer();
4197 DataArrayInt *newConn=DataArrayInt::New();
4198 DataArrayInt *newConnI=DataArrayInt::New();
4199 newConnI->alloc(nbOf3DCells+1,1);
4200 int *newConnIPtr=newConnI->getPointer();
4202 std::vector<int> newc;
4203 for(int j=0;j<nbOf2DCells;j++)
4205 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4206 *newConnIPtr++=(int)newc.size();
4208 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4209 int *newConnPtr=newConn->getPointer();
4210 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4211 newConnIPtr=newConnI->getPointer();
4212 for(int iz=0;iz<nbOf1DCells;iz++)
4215 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4216 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4218 int icell=(int)(iter-newc.begin());
4219 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4222 *newConnPtr=(*iter)+iz*deltaPerLev;
4227 *newConnPtr=(*iter);
4230 ret->setConnectivity(newConn,newConnI,true);
4232 newConnI->decrRef();
4233 ret->setCoords(getCoords());
4238 * This method returns if 'this' is constituted by only quadratic cells.
4240 bool MEDCouplingUMesh::isFullyQuadratic() const
4242 checkFullyDefined();
4244 int nbOfCells=getNumberOfCells();
4245 for(int i=0;i<nbOfCells && ret;i++)
4247 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4248 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4249 ret=cm.isQuadratic();
4255 * This method returns if there is at least one quadratic cell.
4257 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4259 checkFullyDefined();
4261 int nbOfCells=getNumberOfCells();
4262 for(int i=0;i<nbOfCells && !ret;i++)
4264 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4265 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4266 ret=cm.isQuadratic();
4272 * This method convert quadratic cells to linear cells if any was found.
4273 * If no such cells exists 'this' remains unchanged.
4275 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4277 checkFullyDefined();
4278 int nbOfCells=getNumberOfCells();
4280 for(int i=0;i<nbOfCells;i++)
4282 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4283 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4284 if(cm.isQuadratic())
4286 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4287 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4288 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4295 newConn->alloc(getMeshLength()-delta,1);
4296 newConnI->alloc(nbOfCells+1,1);
4297 const int *icptr=_nodal_connec->getConstPointer();
4298 const int *iciptr=_nodal_connec_index->getConstPointer();
4299 int *ocptr=newConn->getPointer();
4300 int *ociptr=newConnI->getPointer();
4303 for(int i=0;i<nbOfCells;i++,ociptr++)
4305 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4306 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4307 if(!cm.isQuadratic())
4309 _types.insert(type);
4310 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4311 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4315 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4316 _types.insert(typel);
4317 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4318 int newNbOfNodes=cml.getNumberOfNodes();
4319 *ocptr++=(int)typel;
4320 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4321 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4324 setConnectivity(newConn,newConnI,false);
4328 * This method tessallates 'this' so that the number of cells remains the same.
4329 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4330 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4332 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4333 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4335 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4337 checkFullyDefined();
4338 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4339 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4340 double epsa=fabs(eps);
4341 if(epsa<std::numeric_limits<double>::min())
4342 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 !");
4343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4344 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4348 revDesc1=0; revDescIndx1=0;
4349 mDesc->tessellate2DCurve(eps);
4350 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4351 setCoords(mDesc->getCoords());
4355 * This method tessallates 'this' so that the number of cells remains the same.
4356 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4357 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4359 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4360 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4362 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4364 checkFullyDefined();
4365 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4366 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4367 double epsa=fabs(eps);
4368 if(epsa<std::numeric_limits<double>::min())
4369 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 !");
4370 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4371 int nbCells=getNumberOfCells();
4372 int nbNodes=getNumberOfNodes();
4373 const int *conn=_nodal_connec->getConstPointer();
4374 const int *connI=_nodal_connec_index->getConstPointer();
4375 const double *coords=_coords->getConstPointer();
4376 std::vector<double> addCoo;
4377 std::vector<int> newConn;
4378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4379 newConnI->alloc(nbCells+1,1);
4380 int *newConnIPtr=newConnI->getPointer();
4383 INTERP_KERNEL::Node *tmp2[3];
4384 std::set<INTERP_KERNEL::NormalizedCellType> types;
4385 for(int i=0;i<nbCells;i++,newConnIPtr++)
4387 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4388 if(cm.isQuadratic())
4389 {//assert(connI[i+1]-connI[i]-1==3)
4390 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4391 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4392 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4393 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4394 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4397 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4398 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4400 newConnIPtr[1]=(int)newConn.size();
4404 types.insert(INTERP_KERNEL::NORM_SEG2);
4405 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4406 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4407 newConnIPtr[1]=newConnIPtr[0]+3;
4412 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4413 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4414 newConnIPtr[1]=newConnIPtr[0]+3;
4417 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4420 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4422 newConnArr->alloc((int)newConn.size(),1);
4423 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4424 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4425 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4426 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4427 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4428 std::copy(addCoo.begin(),addCoo.end(),work);
4429 DataArrayDouble::SetArrayIn(newCoords,_coords);
4434 * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4435 * This cut into simplex is performed following the parameter 'policy'. This method so typically increases the number of cells of this.
4436 * This method returns new2old array that specifies a each cell of 'this' after the call what was its id it comes.
4438 * The semantic of 'policy' parameter :
4439 * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4440 * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4442 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4447 return simplexizePol0();
4449 return simplexizePol1();
4451 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be 0 or 1 !");
4455 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4457 checkFullyDefined();
4458 if(getMeshDimension()<1)
4459 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4460 int nbCells=getNumberOfCells();
4461 const int *conn=_nodal_connec->getConstPointer();
4462 const int *connI=_nodal_connec_index->getConstPointer();
4463 for(int i=0;i<nbCells;i++)
4465 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4473 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4475 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4477 if(getMeshDimension()!=2)
4478 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4479 int nbOfCells=getNumberOfCells();
4480 DataArrayInt *ret=DataArrayInt::New();
4481 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4482 ret->alloc(nbOfCells+nbOfCutCells,1);
4488 int *retPt=ret->getPointer();
4489 DataArrayInt *newConn=DataArrayInt::New();
4490 DataArrayInt *newConnI=DataArrayInt::New();
4491 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4492 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4493 int *pt=newConn->getPointer();
4494 int *ptI=newConnI->getPointer();
4496 const int *oldc=_nodal_connec->getConstPointer();
4497 const int *ci=_nodal_connec_index->getConstPointer();
4498 for(int i=0;i<nbOfCells;i++,ci++)
4500 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4502 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4503 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4504 pt=std::copy(tmp,tmp+8,pt);
4513 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4514 ptI[1]=ptI[0]+ci[1]-ci[0];
4519 _nodal_connec->decrRef();
4520 _nodal_connec=newConn;
4521 _nodal_connec_index->decrRef();
4522 _nodal_connec_index=newConnI;
4529 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4531 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4533 if(getMeshDimension()!=2)
4534 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4535 int nbOfCells=getNumberOfCells();
4536 DataArrayInt *ret=DataArrayInt::New();
4537 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4538 ret->alloc(nbOfCells+nbOfCutCells,1);
4544 int *retPt=ret->getPointer();
4545 DataArrayInt *newConn=DataArrayInt::New();
4546 DataArrayInt *newConnI=DataArrayInt::New();
4547 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4548 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4549 int *pt=newConn->getPointer();
4550 int *ptI=newConnI->getPointer();
4552 const int *oldc=_nodal_connec->getConstPointer();
4553 const int *ci=_nodal_connec_index->getConstPointer();
4554 for(int i=0;i<nbOfCells;i++,ci++)
4556 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4558 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4559 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4560 pt=std::copy(tmp,tmp+8,pt);
4569 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4570 ptI[1]=ptI[0]+ci[1]-ci[0];
4575 _nodal_connec->decrRef();
4576 _nodal_connec=newConn;
4577 _nodal_connec_index->decrRef();
4578 _nodal_connec_index=newConnI;
4585 * 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.
4586 * This method completly ignore coordinates.
4587 * @param nodeSubdived is the nodal connectivity of subdivision of edges
4588 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
4589 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4590 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4592 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
4594 checkFullyDefined();
4595 if(getMeshDimension()!=2)
4596 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
4597 int nbOfCells=getNumberOfCells();
4598 int *connI=_nodal_connec_index->getPointer();
4600 for(int i=0;i<nbOfCells;i++,connI++)
4602 int offset=descIndex[i];
4603 int nbOfEdges=descIndex[i+1]-offset;
4605 bool ddirect=desc[offset+nbOfEdges-1]>0;
4606 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
4607 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
4608 for(int j=0;j<nbOfEdges;j++)
4610 bool direct=desc[offset+j]>0;
4611 int edgeId=std::abs(desc[offset+j])-1;
4612 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
4614 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
4615 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
4616 int ref2=direct?id1:id2;
4619 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4620 newConnLgth+=nbOfSubNodes-1;
4625 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
4626 throw INTERP_KERNEL::Exception(oss.str().c_str());
4631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
4634 newConnLgth++;//+1 is for cell type
4635 connI[1]=newConnLgth;
4638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4639 newConn->alloc(newConnLgth,1);
4640 int *work=newConn->getPointer();
4641 for(int i=0;i<nbOfCells;i++)
4643 *work++=INTERP_KERNEL::NORM_POLYGON;
4644 int offset=descIndex[i];
4645 int nbOfEdges=descIndex[i+1]-offset;
4646 for(int j=0;j<nbOfEdges;j++)
4648 bool direct=desc[offset+j]>0;
4649 int edgeId=std::abs(desc[offset+j])-1;
4651 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
4654 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4655 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
4656 work=std::copy(it,it+nbOfSubNodes-1,work);
4660 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
4663 _types.insert(INTERP_KERNEL::NORM_POLYGON);
4667 * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
4668 * nodal connectivity will be transform to a NORM_TRI3 cell.
4669 * This method works \b only \b on \b linear cells.
4670 * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
4671 * method could be usefull before calling this method in case of presence of several pair of nodes located on same position.
4672 * This method throws an exception if 'this' is not fully defined (connectivity).
4673 * 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.
4675 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
4677 checkFullyDefined();
4678 if(getMeshDimension()<=1)
4679 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4680 int nbOfCells=getNumberOfCells();
4683 int initMeshLgth=getMeshLength();
4684 int *conn=_nodal_connec->getPointer();
4685 int *index=_nodal_connec_index->getPointer();
4689 for(int i=0;i<nbOfCells;i++)
4691 lgthOfCurCell=index[i+1]-posOfCurCell;
4692 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4694 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4695 conn+newPos+1,newLgth);
4696 conn[newPos]=newType;
4698 posOfCurCell=index[i+1];
4701 if(newPos!=initMeshLgth)
4702 _nodal_connec->reAlloc(newPos);
4707 * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
4708 * The 'vec' vector has to have a non nul norm.
4709 * If not 'cells' parameter will be appended with cellIds of incorrect cells.
4710 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
4712 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
4714 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4715 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4716 int nbOfCells=getNumberOfCells();
4717 const int *conn=_nodal_connec->getConstPointer();
4718 const int *connI=_nodal_connec_index->getConstPointer();
4719 const double *coordsPtr=_coords->getConstPointer();
4720 for(int i=0;i<nbOfCells;i++)
4722 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4723 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4725 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4726 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4733 * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
4734 * The 'vec' vector has to have a non nul norm.
4735 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
4737 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
4739 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4740 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4741 int nbOfCells=getNumberOfCells();
4742 int *conn=_nodal_connec->getPointer();
4743 const int *connI=_nodal_connec_index->getConstPointer();
4744 const double *coordsPtr=_coords->getConstPointer();
4745 bool isModified=false;
4746 for(int i=0;i<nbOfCells;i++)
4748 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4749 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4751 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4752 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4755 std::vector<int> tmp(connI[i+1]-connI[i]-2);
4756 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
4757 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
4762 _nodal_connec->declareAsNew();
4767 * This method checks that all polyhedrons cells have correctly oriented faces.
4768 * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
4769 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
4771 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
4773 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4774 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4775 int nbOfCells=getNumberOfCells();
4776 const int *conn=_nodal_connec->getConstPointer();
4777 const int *connI=_nodal_connec_index->getConstPointer();
4778 const double *coordsPtr=_coords->getConstPointer();
4779 for(int i=0;i<nbOfCells;i++)
4781 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4782 if(type==INTERP_KERNEL::NORM_POLYHED)
4784 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4791 * This method tries to orient correctly polhedrons cells.
4792 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
4794 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
4796 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4797 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4798 int nbOfCells=getNumberOfCells();
4799 int *conn=_nodal_connec->getPointer();
4800 const int *connI=_nodal_connec_index->getConstPointer();
4801 const double *coordsPtr=_coords->getConstPointer();
4802 bool isModified=false;
4803 for(int i=0;i<nbOfCells;i++)
4805 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4806 if(type==INTERP_KERNEL::NORM_POLYHED)
4807 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4809 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4814 _nodal_connec->declareAsNew();
4819 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
4820 * If it is not the case an exception will be thrown.
4821 * This method is fast because the first cell of 'this' is used to compute the plane.
4822 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
4823 * @param pos output of size at least 3 used to store a point owned of searched plane.
4825 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
4827 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4828 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
4829 const int *conn=_nodal_connec->getConstPointer();
4830 const int *connI=_nodal_connec_index->getConstPointer();
4831 const double *coordsPtr=_coords->getConstPointer();
4832 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
4833 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
4837 * The returned newly created field has to be managed by the caller.
4838 * 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.
4839 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
4840 * If a cell has an another type an exception will be thrown.
4842 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
4845 int spaceDim=getSpaceDimension();
4846 int meshDim=getMeshDimension();
4847 if(spaceDim!=2 && spaceDim!=3)
4848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
4849 if(meshDim!=2 && meshDim!=3)
4850 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
4851 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
4853 int nbOfCells=getNumberOfCells();
4854 DataArrayDouble *arr=DataArrayDouble::New();
4855 arr->alloc(nbOfCells,1);
4856 double *pt=arr->getPointer();
4857 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
4859 const int *conn=_nodal_connec->getConstPointer();
4860 const int *connI=_nodal_connec_index->getConstPointer();
4861 const double *coo=_coords->getConstPointer();
4863 for(int i=0;i<nbOfCells;i++,pt++)
4865 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
4868 case INTERP_KERNEL::NORM_TRI3:
4870 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
4871 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
4874 case INTERP_KERNEL::NORM_QUAD4:
4876 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4877 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
4880 case INTERP_KERNEL::NORM_TETRA4:
4882 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4883 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
4887 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
4889 conn+=connI[i+1]-connI[i];
4891 ret->setName("EdgeRatio");
4897 * The returned newly created field has to be managed by the caller.
4898 * 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.
4899 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
4900 * If a cell has an another type an exception will be thrown.
4902 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
4905 int spaceDim=getSpaceDimension();
4906 int meshDim=getMeshDimension();
4907 if(spaceDim!=2 && spaceDim!=3)
4908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
4909 if(meshDim!=2 && meshDim!=3)
4910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
4911 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
4913 int nbOfCells=getNumberOfCells();
4914 DataArrayDouble *arr=DataArrayDouble::New();
4915 arr->alloc(nbOfCells,1);
4916 double *pt=arr->getPointer();
4917 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
4919 const int *conn=_nodal_connec->getConstPointer();
4920 const int *connI=_nodal_connec_index->getConstPointer();
4921 const double *coo=_coords->getConstPointer();
4923 for(int i=0;i<nbOfCells;i++,pt++)
4925 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
4928 case INTERP_KERNEL::NORM_TRI3:
4930 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
4931 *pt=INTERP_KERNEL::triAspectRatio(tmp);
4934 case INTERP_KERNEL::NORM_QUAD4:
4936 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4937 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
4940 case INTERP_KERNEL::NORM_TETRA4:
4942 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4943 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
4947 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
4949 conn+=connI[i+1]-connI[i];
4951 ret->setName("AspectRatio");
4957 * The returned newly created field has to be managed by the caller.
4958 * 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.
4959 * This method for the moment only deals with NORM_QUAD4 geometric type.
4960 * If a cell has an another type an exception will be thrown.
4962 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
4965 int spaceDim=getSpaceDimension();
4966 int meshDim=getMeshDimension();
4968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
4970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
4971 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
4973 int nbOfCells=getNumberOfCells();
4974 DataArrayDouble *arr=DataArrayDouble::New();
4975 arr->alloc(nbOfCells,1);
4976 double *pt=arr->getPointer();
4977 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
4979 const int *conn=_nodal_connec->getConstPointer();
4980 const int *connI=_nodal_connec_index->getConstPointer();
4981 const double *coo=_coords->getConstPointer();
4983 for(int i=0;i<nbOfCells;i++,pt++)
4985 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
4988 case INTERP_KERNEL::NORM_QUAD4:
4990 FillInCompact3DMode(3,4,conn+1,coo,tmp);
4991 *pt=INTERP_KERNEL::quadWarp(tmp);
4995 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
4997 conn+=connI[i+1]-connI[i];
4999 ret->setName("Warp");
5005 * The returned newly created field has to be managed by the caller.
5006 * 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.
5007 * This method for the moment only deals with NORM_QUAD4 geometric type.
5008 * If a cell has an another type an exception will be thrown.
5010 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5013 int spaceDim=getSpaceDimension();
5014 int meshDim=getMeshDimension();
5016 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5019 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
5021 int nbOfCells=getNumberOfCells();
5022 DataArrayDouble *arr=DataArrayDouble::New();
5023 arr->alloc(nbOfCells,1);
5024 double *pt=arr->getPointer();
5025 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5027 const int *conn=_nodal_connec->getConstPointer();
5028 const int *connI=_nodal_connec_index->getConstPointer();
5029 const double *coo=_coords->getConstPointer();
5031 for(int i=0;i<nbOfCells;i++,pt++)
5033 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5036 case INTERP_KERNEL::NORM_QUAD4:
5038 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5039 *pt=INTERP_KERNEL::quadSkew(tmp);
5043 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5045 conn+=connI[i+1]-connI[i];
5047 ret->setName("Skew");
5053 * This method aggregate the bbox of each cell and put it into bbox parameter.
5054 * @param bbox out parameter of size 2*spacedim*nbOfcells.
5056 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5058 int spaceDim=getSpaceDimension();
5059 int nbOfCells=getNumberOfCells();
5060 bbox.resize(2*nbOfCells*spaceDim);
5061 for(int i=0;i<nbOfCells*spaceDim;i++)
5063 bbox[2*i]=std::numeric_limits<double>::max();
5064 bbox[2*i+1]=-std::numeric_limits<double>::max();
5066 const double *coordsPtr=_coords->getConstPointer();
5067 const int *conn=_nodal_connec->getConstPointer();
5068 const int *connI=_nodal_connec_index->getConstPointer();
5069 for(int i=0;i<nbOfCells;i++)
5071 int offset=connI[i]+1;
5072 int nbOfNodesForCell=connI[i+1]-offset;
5073 for(int j=0;j<nbOfNodesForCell;j++)
5075 int nodeId=conn[offset+j];
5077 for(int k=0;k<spaceDim;k++)
5079 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5080 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5088 namespace ParaMEDMEMImpl
5093 ConnReader(const int *c, int val):_conn(c),_val(val) { }
5094 bool operator() (const int& pos) { return _conn[pos]!=_val; }
5103 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5104 bool operator() (const int& pos) { return _conn[pos]==_val; }
5114 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5115 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5116 * 'this' is composed in cell types.
5117 * The returned array is of size 3*n where n is the number of different types present in 'this'.
5118 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
5119 * This parameter is kept only for compatibility with other methode listed above.
5121 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5123 checkConnectivityFullyDefined();
5124 const int *conn=_nodal_connec->getConstPointer();
5125 const int *connI=_nodal_connec_index->getConstPointer();
5126 const int *work=connI;
5127 int nbOfCells=getNumberOfCells();
5128 std::size_t n=getAllTypes().size();
5129 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5130 std::set<INTERP_KERNEL::NormalizedCellType> types;
5131 for(std::size_t i=0;work!=connI+nbOfCells;i++)
5133 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5134 if(types.find(typ)!=types.end())
5136 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5137 oss << " is not contiguous !";
5138 throw INTERP_KERNEL::Exception(oss.str().c_str());
5142 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5143 ret[3*i+1]=(int)std::distance(work,work2);
5150 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5151 * only for types cell, type node is not managed.
5152 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5153 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5154 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5155 * If 2 or more same geometric type is in 'code' and exception is thrown too.
5157 * This method firstly checks
5158 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5159 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5160 * an exception is thrown too.
5162 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5163 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
5164 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5166 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5169 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5170 std::size_t sz=code.size();
5173 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5174 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5176 for(std::size_t i=0;i<n;i++)
5177 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5179 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5181 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5182 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5186 if(idsPerType.empty())
5188 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5189 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5190 if(types.size()==_types.size())
5193 DataArrayInt *ret=DataArrayInt::New();
5195 int *retPtr=ret->getPointer();
5196 const int *connI=_nodal_connec_index->getConstPointer();
5197 const int *conn=_nodal_connec->getConstPointer();
5198 int nbOfCells=getNumberOfCells();
5201 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5203 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5204 int offset=(int)std::distance(connI,i);
5205 if(code[3*kk+2]==-1)
5207 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5208 std::size_t pos2=std::distance(i,j);
5209 for(std::size_t k=0;k<pos2;k++)
5210 *retPtr++=(int)k+offset;
5215 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5216 retPtr,std::bind2nd(std::plus<int>(),offset));
5223 * This method makes the hypothesis that 'this' is sorted by type. If not an exception will be thrown.
5224 * This method is the opposite of MEDCouplingUMesh::checkTypeConsistencyAndContig method. Given a list of cells in 'profile' it returns a list of profiles sorted by geo type.
5225 * This method has 1 input 'profile' and 2 outputs 'code' and 'idsPerType'.
5226 * @throw if 'profile' has not exactly one component. It throws too, if 'profile' contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
5228 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5230 if(profile->getNumberOfComponents()!=1)
5231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5232 checkConnectivityFullyDefined();
5233 const int *conn=_nodal_connec->getConstPointer();
5234 const int *connI=_nodal_connec_index->getConstPointer();
5235 int nbOfCells=getNumberOfCells();
5236 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5237 std::vector<int> typeRangeVals(1);
5238 for(const int *i=connI;i!=connI+nbOfCells;)
5240 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5241 if(std::find(types.begin(),types.end(),curType)!=types.end())
5243 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5245 types.push_back(curType);
5246 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5247 typeRangeVals.push_back((int)std::distance(connI,i));
5250 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5251 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5256 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5257 code.resize(3*nbOfCastsFinal);
5258 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5259 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5260 for(int i=0;i<nbOfCastsFinal;i++)
5262 int castId=castsPresent->getIJ(i,0);
5263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5264 idsInPflPerType2.push_back(tmp3);
5265 code[3*i]=(int)types[castId];
5266 code[3*i+1]=tmp3->getNumberOfTuples();
5267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5268 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5270 tmp4->copyStringInfoFrom(*profile);
5271 idsPerType2.push_back(tmp4);
5272 code[3*i+2]=(int)idsPerType2.size()-1;
5279 std::size_t sz2=idsInPflPerType2.size();
5280 idsInPflPerType.resize(sz2);
5281 for(std::size_t i=0;i<sz2;i++)
5283 DataArrayInt *locDa=idsInPflPerType2[i];
5285 idsInPflPerType[i]=locDa;
5287 std::size_t sz=idsPerType2.size();
5288 idsPerType.resize(sz);
5289 for(std::size_t i=0;i<sz;i++)
5291 DataArrayInt *locDa=idsPerType2[i];
5293 idsPerType[i]=locDa;
5298 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5299 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5300 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5301 * 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.
5303 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5305 checkFullyDefined();
5306 nM1LevMesh->checkFullyDefined();
5307 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5308 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5309 if(_coords!=nM1LevMesh->getCoords())
5310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5313 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5314 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5315 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5316 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5317 tmp->setConnectivity(tmp0,tmp1);
5318 tmp->renumberCells(ret0->getConstPointer(),false);
5319 revDesc=tmp->getNodalConnectivity();
5320 revDescIndx=tmp->getNodalConnectivityIndex();
5321 DataArrayInt *ret=0;
5322 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5325 ret->getMaxValue(tmp2);
5327 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5328 throw INTERP_KERNEL::Exception(oss.str().c_str());
5333 revDescIndx->incrRef();
5336 meshnM1Old2New=ret0;
5341 * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5342 * It avoids to deal with renum in MEDLoader so it is usefull for MED file R/W with multi types.
5343 * This method returns a newly allocated array old2New.
5344 * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5346 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5348 checkConnectivityFullyDefined();
5349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5350 renumberCells(ret->getConstPointer(),false);
5356 * This methods checks that cells are sorted by their types.
5357 * This method makes asumption (no check) that connectivity is correctly set before calling.
5359 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5361 checkFullyDefined();
5362 const int *conn=_nodal_connec->getConstPointer();
5363 const int *connI=_nodal_connec_index->getConstPointer();
5364 int nbOfCells=getNumberOfCells();
5365 std::set<INTERP_KERNEL::NormalizedCellType> types;
5366 for(const int *i=connI;i!=connI+nbOfCells;)
5368 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5369 if(types.find(curType)!=types.end())
5371 types.insert(curType);
5372 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5378 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5379 * that the order is specified in array defined by [orderBg,orderEnd).
5381 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5383 checkFullyDefined();
5384 const int *conn=_nodal_connec->getConstPointer();
5385 const int *connI=_nodal_connec_index->getConstPointer();
5386 int nbOfCells=getNumberOfCells();
5388 for(const int *i=connI;i!=connI+nbOfCells;)
5390 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5391 int pos=(int)std::distance(orderBg,std::find(orderBg,orderEnd,curType));
5395 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5401 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5402 * 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
5403 * 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'.
5405 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
5407 checkConnectivityFullyDefined();
5408 int nbOfCells=getNumberOfCells();
5409 const int *conn=_nodal_connec->getConstPointer();
5410 const int *connI=_nodal_connec_index->getConstPointer();
5411 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
5413 tmpa->alloc(nbOfCells,1);
5414 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5415 tmpb->fillWithZero();
5416 int *tmp=tmpa->getPointer();
5417 int *tmp2=tmpb->getPointer();
5418 for(const int *i=connI;i!=connI+nbOfCells;i++)
5420 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5423 int pos=(int)std::distance(orderBg,where);
5425 tmp[std::distance(connI,i)]=pos;
5429 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5430 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5431 oss << " has a type " << cm.getRepr() << " not in input array of type !";
5432 throw INTERP_KERNEL::Exception(oss.str().c_str());
5442 * 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'.
5443 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5444 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5445 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5447 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
5449 DataArrayInt *nbPerType=0;
5450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5451 nbPerType->decrRef();
5452 return tmpa->buildPermArrPerLevel();
5456 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
5457 * The number of cells remains unchanged after the call of this method.
5458 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5459 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5461 * @return the array giving the correspondance old to new.
5463 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5465 checkFullyDefined();
5467 const int *conn=_nodal_connec->getConstPointer();
5468 const int *connI=_nodal_connec_index->getConstPointer();
5469 int nbOfCells=getNumberOfCells();
5470 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5471 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5472 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5474 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5475 types.push_back(curType);
5476 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5478 DataArrayInt *ret=DataArrayInt::New();
5479 ret->alloc(nbOfCells,1);
5480 int *retPtr=ret->getPointer();
5481 std::fill(retPtr,retPtr+nbOfCells,-1);
5483 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5485 for(const int *i=connI;i!=connI+nbOfCells;i++)
5486 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5487 retPtr[std::distance(connI,i)]=newCellId++;
5489 renumberCells(retPtr,false);
5494 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
5495 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5496 * This method makes asumption that connectivity is correctly set before calling.
5498 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5500 checkFullyDefined();
5501 const int *conn=_nodal_connec->getConstPointer();
5502 const int *connI=_nodal_connec_index->getConstPointer();
5503 int nbOfCells=getNumberOfCells();
5504 std::vector<MEDCouplingUMesh *> ret;
5505 for(const int *i=connI;i!=connI+nbOfCells;)
5507 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5508 int beginCellId=(int)std::distance(connI,i);
5509 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5510 int endCellId=(int)std::distance(connI,i);
5511 int sz=endCellId-beginCellId;
5512 int *cells=new int[sz];
5513 for(int j=0;j<sz;j++)
5514 cells[j]=beginCellId+j;
5515 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
5523 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
5524 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
5525 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
5526 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
5527 * are not used here to avoid the build of big permutation array.
5529 * \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
5530 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5531 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
5532 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
5533 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
5534 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
5535 * \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
5536 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
5538 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
5539 DataArrayInt *&szOfCellGrpOfSameType,
5540 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
5542 std::vector<const MEDCouplingUMesh *> ms2;
5543 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
5546 (*it)->checkConnectivityFullyDefined();
5550 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
5551 const DataArrayDouble *refCoo=ms2[0]->getCoords();
5552 int meshDim=ms2[0]->getMeshDimension();
5553 std::vector<const MEDCouplingUMesh *> m1ssm;
5554 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
5556 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
5557 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
5559 std::vector<int> ret1Data;
5560 std::vector<int> ret2Data;
5561 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
5563 if(meshDim!=(*it)->getMeshDimension())
5564 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
5565 if(refCoo!=(*it)->getCoords())
5566 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
5567 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
5568 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
5569 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
5570 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
5572 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
5573 m1ssmSingleAuto.push_back(singleCell);
5574 m1ssmSingle.push_back(singleCell);
5575 ret1Data.push_back((*it2)->getNumberOfCells()); ret2Data.push_back(rk);
5578 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc((int)m1ssmSingle.size(),1); std::copy(ret1Data.begin(),ret1Data.end(),ret1->getPointer());
5579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=DataArrayInt::New(); ret2->alloc((int)m1ssmSingle.size(),1); std::copy(ret2Data.begin(),ret2Data.end(),ret2->getPointer());
5580 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
5581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
5582 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
5583 for(std::size_t i=0;i<m1ssm.size();i++)
5584 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
5585 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
5586 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
5587 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
5593 * This method returns a newly created DataArrayInt instance.
5594 * This method retrieves cell ids in [begin,end) that have the type 'type'.
5596 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
5598 checkFullyDefined();
5600 const int *conn=_nodal_connec->getConstPointer();
5601 const int *connIndex=_nodal_connec_index->getConstPointer();
5602 for(const int *w=begin;w!=end;w++)
5603 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
5605 DataArrayInt *ret=DataArrayInt::New();
5606 ret->alloc((int)r.size(),1);
5607 std::copy(r.begin(),r.end(),ret->getPointer());
5612 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
5613 * are in [0:getNumberOfCells())
5615 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
5617 checkFullyDefined();
5618 const int *conn=_nodal_connec->getConstPointer();
5619 const int *connI=_nodal_connec_index->getConstPointer();
5620 int nbOfCells=getNumberOfCells();
5621 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
5622 int *tmp=new int[nbOfCells];
5623 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5626 for(const int *i=connI;i!=connI+nbOfCells;i++)
5627 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5628 tmp[std::distance(connI,i)]=j++;
5630 DataArrayInt *ret=DataArrayInt::New();
5631 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
5632 ret->copyStringInfoFrom(*da);
5633 int *retPtr=ret->getPointer();
5634 const int *daPtr=da->getConstPointer();
5635 int nbOfElems=da->getNbOfElems();
5636 for(int k=0;k<nbOfElems;k++)
5637 retPtr[k]=tmp[daPtr[k]];
5643 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
5644 * cells whose ids is in 'idsPerGeoType' array.
5645 * This method conserves coords and name of mesh.
5647 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
5649 std::vector<int> idsTokeep;
5650 int nbOfCells=getNumberOfCells();
5652 for(int i=0;i<nbOfCells;i++)
5653 if(getTypeOfCell(i)!=type)
5654 idsTokeep.push_back(i);
5657 if(std::find(idsPerGeoTypeBg,idsPerGeoTypeEnd,j)!=idsPerGeoTypeEnd)
5658 idsTokeep.push_back(i);
5661 MEDCouplingPointSet *ret=buildPartOfMySelf(&idsTokeep[0],&idsTokeep[0]+idsTokeep.size(),true);
5662 MEDCouplingUMesh *ret2=dynamic_cast<MEDCouplingUMesh *>(ret);
5668 ret2->copyTinyInfoFrom(this);
5673 * This method returns a vector of size 'this->getNumberOfCells()'.
5674 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
5676 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
5678 int ncell=getNumberOfCells();
5679 std::vector<bool> ret(ncell);
5680 const int *cI=getNodalConnectivityIndex()->getConstPointer();
5681 const int *c=getNodalConnectivity()->getConstPointer();
5682 for(int i=0;i<ncell;i++)
5684 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
5685 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5686 ret[i]=cm.isQuadratic();
5692 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
5694 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
5696 if(other->getType()!=UNSTRUCTURED)
5697 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
5698 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
5699 return MergeUMeshes(this,otherC);
5703 * Returns an array with this->getNumberOfCells() tuples and this->getSpaceDimension() dimension.
5704 * The false barycenter is computed that is to say barycenter of a cell is computed using average on each
5705 * components of coordinates of the cell.
5707 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
5709 DataArrayDouble *ret=DataArrayDouble::New();
5710 int spaceDim=getSpaceDimension();
5711 int nbOfCells=getNumberOfCells();
5712 ret->alloc(nbOfCells,spaceDim);
5713 ret->copyStringInfoFrom(*getCoords());
5714 double *ptToFill=ret->getPointer();
5715 double *tmp=new double[spaceDim];
5716 const int *nodal=_nodal_connec->getConstPointer();
5717 const int *nodalI=_nodal_connec_index->getConstPointer();
5718 const double *coor=_coords->getConstPointer();
5719 for(int i=0;i<nbOfCells;i++)
5721 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
5722 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
5730 * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
5731 * 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().
5732 * No check of that will be done !
5734 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
5736 DataArrayDouble *ret=DataArrayDouble::New();
5737 int spaceDim=getSpaceDimension();
5738 int nbOfTuple=(int)std::distance(begin,end);
5739 ret->alloc(nbOfTuple,spaceDim);
5740 double *ptToFill=ret->getPointer();
5741 double *tmp=new double[spaceDim];
5742 const int *nodal=_nodal_connec->getConstPointer();
5743 const int *nodalI=_nodal_connec_index->getConstPointer();
5744 const double *coor=_coords->getConstPointer();
5745 for(const int *w=begin;w!=end;w++)
5747 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
5748 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
5756 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
5759 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
5762 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
5763 da->checkAllocated();
5764 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
5766 int nbOfTuples=da->getNumberOfTuples();
5767 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
5768 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
5769 c->alloc(2*nbOfTuples,1);
5770 cI->alloc(nbOfTuples+1,1);
5771 int *cp=c->getPointer();
5772 int *cip=cI->getPointer();
5774 for(int i=0;i<nbOfTuples;i++)
5776 *cp++=INTERP_KERNEL::NORM_POINT1;
5780 ret->setConnectivity(c,cI,true);
5786 * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
5787 * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
5789 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
5791 std::vector<const MEDCouplingUMesh *> tmp(2);
5792 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
5793 return MergeUMeshes(tmp);
5797 * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
5798 * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
5799 * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
5800 * cells in meshes in 'a' (in the same order too).
5802 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
5804 std::size_t sz=a.size();
5806 return MergeUMeshesLL(a);
5807 for(std::size_t ii=0;ii<sz;ii++)
5810 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
5811 throw INTERP_KERNEL::Exception(oss.str().c_str());
5813 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
5814 std::vector< const MEDCouplingUMesh * > aa(sz);
5816 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
5818 const MEDCouplingUMesh *cur=a[i];
5819 const DataArrayDouble *coo=cur->getCoords();
5821 spaceDim=coo->getNumberOfComponents();
5824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
5825 for(std::size_t i=0;i<sz;i++)
5827 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
5830 return MergeUMeshesLL(aa);
5835 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
5838 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
5839 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
5840 int meshDim=(*it)->getMeshDimension();
5841 int nbOfCells=(*it)->getNumberOfCells();
5842 int meshLgth=(*it++)->getMeshLength();
5843 for(;it!=a.end();it++)
5845 if(meshDim!=(*it)->getMeshDimension())
5846 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
5847 nbOfCells+=(*it)->getNumberOfCells();
5848 meshLgth+=(*it)->getMeshLength();
5850 std::vector<const MEDCouplingPointSet *> aps(a.size());
5851 std::copy(a.begin(),a.end(),aps.begin());
5852 DataArrayDouble *pts=MergeNodesArray(aps);
5853 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
5854 ret->setCoords(pts);
5856 DataArrayInt *c=DataArrayInt::New();
5857 c->alloc(meshLgth,1);
5858 int *cPtr=c->getPointer();
5859 DataArrayInt *cI=DataArrayInt::New();
5860 cI->alloc(nbOfCells+1,1);
5861 int *cIPtr=cI->getPointer();
5865 for(it=a.begin();it!=a.end();it++)
5867 int curNbOfCell=(*it)->getNumberOfCells();
5868 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
5869 const int *curC=(*it)->_nodal_connec->getConstPointer();
5870 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
5871 for(int j=0;j<curNbOfCell;j++)
5873 const int *src=curC+curCI[j];
5875 for(;src!=curC+curCI[j+1];src++,cPtr++)
5883 offset+=curCI[curNbOfCell];
5884 offset2+=(*it)->getNumberOfNodes();
5887 ret->setConnectivity(c,cI,true);
5897 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
5898 * 'meshes' must be a non empty vector.
5900 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
5902 std::vector<const MEDCouplingUMesh *> tmp(2);
5903 tmp[0]=mesh1; tmp[1]=mesh2;
5904 return MergeUMeshesOnSameCoords(tmp);
5908 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
5909 * 'meshes' must be a non empty vector.
5911 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
5914 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
5915 for(std::size_t ii=0;ii<meshes.size();ii++)
5918 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
5919 throw INTERP_KERNEL::Exception(oss.str().c_str());
5921 const DataArrayDouble *coords=meshes.front()->getCoords();
5922 int meshDim=meshes.front()->getMeshDimension();
5923 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
5925 int meshIndexLgth=0;
5926 for(;iter!=meshes.end();iter++)
5928 if(coords!=(*iter)->getCoords())
5929 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
5930 if(meshDim!=(*iter)->getMeshDimension())
5931 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
5932 meshLgth+=(*iter)->getMeshLength();
5933 meshIndexLgth+=(*iter)->getNumberOfCells();
5935 DataArrayInt *nodal=DataArrayInt::New();
5936 nodal->alloc(meshLgth,1);
5937 int *nodalPtr=nodal->getPointer();
5938 DataArrayInt *nodalIndex=DataArrayInt::New();
5939 nodalIndex->alloc(meshIndexLgth+1,1);
5940 int *nodalIndexPtr=nodalIndex->getPointer();
5942 for(iter=meshes.begin();iter!=meshes.end();iter++)
5944 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
5945 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
5946 int nbOfCells=(*iter)->getNumberOfCells();
5947 int meshLgth2=(*iter)->getMeshLength();
5948 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
5949 if(iter!=meshes.begin())
5950 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
5952 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
5955 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
5956 ret->setName("merge");
5957 ret->setMeshDimension(meshDim);
5958 ret->setConnectivity(nodal,nodalIndex,true);
5959 ret->setCoords(coords);
5960 nodalIndex->decrRef();
5966 * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
5967 * 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)
5969 * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
5970 * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
5971 * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
5972 * The arrays contained in 'corr' parameter are returned with refcounter set to one.
5973 * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
5974 * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
5975 * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
5977 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
5979 //All checks are delegated to MergeUMeshesOnSameCoords
5980 MEDCouplingUMesh *ret=MergeUMeshesOnSameCoords(meshes);
5981 DataArrayInt *o2n=ret->zipConnectivityTraducer(compType);
5982 corr.resize(meshes.size());
5983 std::size_t nbOfMeshes=meshes.size();
5985 const int *o2nPtr=o2n->getConstPointer();
5986 for(std::size_t i=0;i<nbOfMeshes;i++)
5988 DataArrayInt *tmp=DataArrayInt::New();
5989 int curNbOfCells=meshes[i]->getNumberOfCells();
5990 tmp->alloc(curNbOfCells,1);
5991 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
5992 offset+=curNbOfCells;
5993 tmp->setName(meshes[i]->getName());
6001 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6002 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6003 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6004 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6006 * This method performs nothing if size of \b meshes is in [0,1].
6007 * This method is particulary usefull in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6008 * coordinates DataArrayDouble instance.
6010 * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6012 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6014 std::size_t sz=meshes.size();
6017 std::vector< const DataArrayDouble * > coords(meshes.size());
6018 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6019 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6023 (*it)->checkConnectivityFullyDefined();
6024 const DataArrayDouble *coo=(*it)->getCoords();
6029 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6030 oss << " has no coordinate array defined !";
6031 throw INTERP_KERNEL::Exception(oss.str().c_str());
6036 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6037 oss << " is null !";
6038 throw INTERP_KERNEL::Exception(oss.str().c_str());
6041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6042 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6043 int offset=(*it)->getNumberOfNodes();
6044 (*it++)->setCoords(res);
6045 for(;it!=meshes.end();it++)
6047 int oldNumberOfNodes=(*it)->getNumberOfNodes();
6048 (*it)->setCoords(res);
6049 (*it)->shiftNodeNumbersInConn(offset);
6050 offset+=oldNumberOfNodes;
6055 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6056 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6057 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6058 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6059 * 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.
6061 * This method performs nothing if size of \b meshes is empty.
6062 * This method is particulary usefull in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6063 * coordinates DataArrayDouble instance.
6065 * \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.
6066 * \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.
6068 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6072 std::set<const DataArrayDouble *> s;
6073 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6076 s.insert((*it)->getCoords());
6079 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 !";
6080 throw INTERP_KERNEL::Exception(oss.str().c_str());
6085 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 !";
6086 throw INTERP_KERNEL::Exception(oss.str().c_str());
6088 const DataArrayDouble *coo=*(s.begin());
6092 DataArrayInt *comm,*commI;
6093 coo->findCommonTuples(eps,-1,comm,commI);
6094 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6095 int oldNbOfNodes=coo->getNumberOfTuples();
6097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm,commI,newNbOfNodes);
6098 if(oldNbOfNodes==newNbOfNodes)
6100 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6101 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6103 (*it)->renumberNodesInConn(o2n->getConstPointer());
6104 (*it)->setCoords(newCoords);
6109 * 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.
6110 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6111 * @param isQuad specifies the policy of connectivity.
6112 * @ret in/out parameter in which the result will be append
6114 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6116 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6117 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6118 ret.push_back(cm.getExtrudedType());
6119 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6122 case INTERP_KERNEL::NORM_POINT1:
6124 ret.push_back(connBg[1]);
6125 ret.push_back(connBg[1]+nbOfNodesPerLev);
6128 case INTERP_KERNEL::NORM_SEG2:
6130 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6131 ret.insert(ret.end(),conn,conn+4);
6134 case INTERP_KERNEL::NORM_SEG3:
6136 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6137 ret.insert(ret.end(),conn,conn+8);
6140 case INTERP_KERNEL::NORM_QUAD4:
6142 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6143 ret.insert(ret.end(),conn,conn+8);
6146 case INTERP_KERNEL::NORM_TRI3:
6148 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6149 ret.insert(ret.end(),conn,conn+6);
6152 case INTERP_KERNEL::NORM_TRI6:
6154 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,
6155 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6156 ret.insert(ret.end(),conn,conn+15);
6159 case INTERP_KERNEL::NORM_QUAD8:
6162 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6163 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6164 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6166 ret.insert(ret.end(),conn,conn+20);
6169 case INTERP_KERNEL::NORM_POLYGON:
6171 std::back_insert_iterator< std::vector<int> > ii(ret);
6172 std::copy(connBg+1,connEnd,ii);
6174 std::reverse_iterator<const int *> rConnBg(connEnd);
6175 std::reverse_iterator<const int *> rConnEnd(connBg+1);
6176 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6177 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6178 for(std::size_t i=0;i<nbOfRadFaces;i++)
6181 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6182 std::copy(conn,conn+4,ii);
6187 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6192 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6194 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6196 double v[3]={0.,0.,0.};
6197 std::size_t sz=std::distance(begin,end);
6200 for(std::size_t i=0;i<sz;i++)
6202 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];
6203 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6204 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6206 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6210 * The polyhedron is specfied by its connectivity nodes in [begin,end).
6212 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6214 std::vector<std::pair<int,int> > edges;
6215 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6216 const int *bgFace=begin;
6217 for(std::size_t i=0;i<nbOfFaces;i++)
6219 const int *endFace=std::find(bgFace+1,end,-1);
6220 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6221 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6223 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6224 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6226 edges.push_back(p1);
6230 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6234 * 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)
6235 * 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
6238 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6239 * \param [in] coords the coordinates with nb of components exactly equal to 3
6240 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6241 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6242 * \param [out] the result is put at the end of the vector without any alteration of the data.
6244 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, std::vector<int>& res) throw(INTERP_KERNEL::Exception)
6246 int nbFaces=std::count(begin+1,end,-1)+1;
6247 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6248 double *vPtr=v->getPointer();
6249 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6250 double *pPtr=p->getPointer();
6251 const int *stFaceConn=begin+1;
6252 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6254 const int *endFaceConn=std::find(stFaceConn,end,-1);
6255 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
6256 stFaceConn=endFaceConn+1;
6258 pPtr=p->getPointer(); vPtr=v->getPointer();
6259 DataArrayInt *comm1=0,*commI1=0;
6260 v->findCommonTuples(eps,-1,comm1,commI1);
6261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6262 const int *comm1Ptr=comm1->getConstPointer();
6263 const int *commI1Ptr=commI1->getConstPointer();
6264 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6265 res.push_back((int)INTERP_KERNEL::NORM_POLYHED);
6267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
6268 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
6269 mm->finishInsertingCells();
6271 for(int i=0;i<nbOfGrps1;i++)
6273 int vecId=comm1Ptr[commI1Ptr[i]];
6274 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6275 DataArrayInt *comm2=0,*commI2=0;
6276 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
6277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
6278 const int *comm2Ptr=comm2->getConstPointer();
6279 const int *commI2Ptr=commI2->getConstPointer();
6280 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
6281 for(int j=0;j<nbOfGrps2;j++)
6283 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
6285 res.insert(res.end(),begin,end);
6290 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
6291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
6292 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6293 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
6294 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
6295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
6296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
6297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
6298 const int *idsNodePtr=idsNode->getConstPointer();
6299 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];
6300 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
6301 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
6302 if(std::abs(norm)>eps)
6304 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
6305 mm3->rotate(center,vec,angle);
6307 mm3->changeSpaceDimension(2);
6308 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
6309 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
6310 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
6311 int nbOfCells=mm4->getNumberOfCells();
6312 for(int k=0;k<nbOfCells;k++)
6315 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
6316 res.push_back(idsNodePtr[*work]);
6326 * 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
6327 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
6329 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
6330 * \param [in] coords coordinates expected to have 3 components.
6331 * \param [in] begin start of the nodal connectivity of the face.
6332 * \param [in] end end of the nodal connectivity (excluded) of the face.
6333 * \param [out] v the normalized vector of size 3
6334 * \param [out] p the pos of plane
6336 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
6338 std::size_t nbPoints=std::distance(begin,end);
6340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
6343 bool refFound=false;
6344 for(;j<nbPoints-1 && !refFound;j++)
6346 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
6347 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
6348 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
6349 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
6353 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
6356 for(std::size_t i=j;i<nbPoints-1;i++)
6359 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
6360 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
6361 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
6362 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
6365 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
6366 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];
6367 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
6370 v[0]/=norm; v[1]/=norm; v[2]/=norm;
6371 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
6375 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
6379 * This method tries to obtain a well oriented polyhedron.
6380 * If the algorithm fails, an exception will be thrown.
6382 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
6384 std::vector<std::pair<int,int> > edges;
6385 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6387 std::vector<bool> isPerm(nbOfFaces);
6388 for(std::size_t i=0;i<nbOfFaces;i++)
6390 int *endFace=std::find(bgFace+1,end,-1);
6391 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6392 for(std::size_t l=0;l<nbOfEdgesInFace;l++)
6394 std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]);
6395 edges.push_back(p1);
6397 int *bgFace2=endFace+1;
6398 for(std::size_t k=i+1;k<nbOfFaces;k++)
6400 int *endFace2=std::find(bgFace2+1,end,-1);
6401 std::size_t nbOfEdgesInFace2=std::distance(bgFace2,endFace2);
6402 for(std::size_t j=0;j<nbOfEdgesInFace2;j++)
6404 std::pair<int,int> p2(bgFace2[j],bgFace2[(j+1)%nbOfEdgesInFace2]);
6405 if(std::find(edges.begin(),edges.end(),p2)!=edges.end())
6408 throw INTERP_KERNEL::Exception("Fail to repare polyhedron ! Polyedron looks bad !");
6409 std::vector<int> tmp(nbOfEdgesInFace2-1);
6410 std::copy(bgFace2+1,endFace2,tmp.rbegin());
6411 std::copy(tmp.begin(),tmp.end(),bgFace2+1);
6420 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
6421 {//not lucky ! The first face was not correctly oriented : reorient all faces...
6423 for(std::size_t i=0;i<nbOfFaces;i++)
6425 int *endFace=std::find(bgFace+1,end,-1);
6426 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6427 std::vector<int> tmp(nbOfEdgesInFace-1);
6428 std::copy(bgFace+1,endFace,tmp.rbegin());
6429 std::copy(tmp.begin(),tmp.end(),bgFace+1);
6436 * This method makes the assumption spacedimension == meshdimension == 2.
6437 * This method works only for linear cells.
6439 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
6441 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
6443 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
6444 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
6445 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
6447 int nbOfNodesExpected=m->getNumberOfNodes();
6448 if(m->getNumberOfCells()!=nbOfNodesExpected)
6449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
6450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
6451 const int *n2oPtr=n2o->getConstPointer();
6452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
6453 m->getReverseNodalConnectivity(revNodal,revNodalI);
6454 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
6455 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
6456 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
6457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
6458 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
6459 if(nbOfNodesExpected<1)
6460 { ret->incrRef(); return ret; }
6462 int prevNode=nodalPtr[nodalIPtr[0]+1];
6463 *work++=n2oPtr[prevNode];
6464 for(int i=1;i<nbOfNodesExpected;i++)
6466 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
6468 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
6469 conn.erase(prevNode);
6472 int curNode=*(conn.begin());
6473 *work++=n2oPtr[curNode];
6474 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
6475 shar.erase(prevCell);
6478 prevCell=*(shar.begin());
6482 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
6485 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
6488 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
6490 ret->incrRef(); return ret;
6494 * This method makes the assumption spacedimension == meshdimension == 3.
6495 * This method works only for linear cells.
6497 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
6499 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
6501 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6502 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
6503 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
6504 const int *conn=m->getNodalConnectivity()->getConstPointer();
6505 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
6506 int nbOfCells=m->getNumberOfCells();
6507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
6508 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
6510 { ret->incrRef(); return ret; }
6511 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
6512 for(int i=1;i<nbOfCells;i++)
6515 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
6522 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
6523 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
6525 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
6529 for(int i=0;i<nbOfNodesInCell;i++)
6530 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
6531 else if(spaceDim==2)
6533 for(int i=0;i<nbOfNodesInCell;i++)
6535 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
6540 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
6543 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
6545 int nbOfCells=getNumberOfCells();
6547 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
6548 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};
6549 ofs << " <" << getVTKDataSetType() << ">\n";
6550 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
6551 ofs << " <PointData>\n" << pointData << std::endl;
6552 ofs << " </PointData>\n";
6553 ofs << " <CellData>\n" << cellData << std::endl;
6554 ofs << " </CellData>\n";
6555 ofs << " <Points>\n";
6556 if(getSpaceDimension()==3)
6557 _coords->writeVTK(ofs,8,"Points");
6560 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
6561 coo->writeVTK(ofs,8,"Points");
6563 ofs << " </Points>\n";
6564 ofs << " <Cells>\n";
6565 const int *cPtr=_nodal_connec->getConstPointer();
6566 const int *cIPtr=_nodal_connec_index->getConstPointer();
6567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
6568 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
6569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
6570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
6571 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
6572 int szFaceOffsets=0,szConn=0;
6573 for(int i=0;i<nbOfCells;i++,w1++,w2++,*w3++)
6576 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
6579 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
6580 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
6584 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
6585 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
6586 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
6587 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
6588 w4=std::copy(c.begin(),c.end(),w4);
6591 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
6592 types->writeVTK(ofs,8,"UInt8","types");
6593 offsets->writeVTK(ofs,8,"Int32","offsets");
6594 if(szFaceOffsets!=0)
6595 {//presence of Polyhedra
6596 connectivity->reAlloc(szConn);
6597 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
6598 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
6599 w1=faces->getPointer();
6600 for(int i=0;i<nbOfCells;i++)
6601 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
6603 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
6605 const int *w4=cPtr+cIPtr[i]+1,*w5=0;
6606 for(int j=0;j<nbFaces;j++)
6608 w5=std::find(w4,cPtr+cIPtr[i+1],-1);
6609 *w1++=(int)std::distance(w4,w5);
6610 w1=std::copy(w4,w5,w1);
6614 faces->writeVTK(ofs,8,"Int32","faces");
6616 connectivity->writeVTK(ofs,8,"Int32","connectivity");
6617 ofs << " </Cells>\n";
6618 ofs << " </Piece>\n";
6619 ofs << " </" << getVTKDataSetType() << ">\n";
6622 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
6624 return std::string("UnstructuredGrid");
6629 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
6631 m1->checkFullyDefined();
6632 m2->checkFullyDefined();
6633 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
6634 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
6635 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
6636 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
6637 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
6638 std::vector<double> addCoo,addCoordsQuadratic;
6639 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
6640 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
6641 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
6642 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
6643 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
6644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
6645 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
6646 std::vector< std::vector<int> > intersectEdge2;
6647 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
6648 subDiv2.clear(); dd5=0; dd6=0;
6649 std::vector<int> cr,crI;
6650 std::vector<int> cNb1,cNb2;
6651 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
6652 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
6654 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
6655 addCooDa->alloc((int)(addCoo.size())/2,2);
6656 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
6657 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
6658 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
6659 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
6660 std::vector<const DataArrayDouble *> coordss(4);
6661 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
6662 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
6663 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
6664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
6665 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
6666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer()); cellNb1=c1;
6667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer()); cellNb2=c2;
6668 ret->setConnectivity(conn,connI,true);
6669 ret->setCoords(coo);
6670 ret->incrRef(); c1->incrRef(); c2->incrRef();
6676 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
6677 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
6678 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
6679 const std::vector<double>& addCoords,
6680 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
6682 static const int SPACEDIM=2;
6683 std::vector<double> bbox1,bbox2;
6684 const double *coo1=m1->getCoords()->getConstPointer();
6685 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
6686 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
6687 int offset1=m1->getNumberOfNodes();
6688 const double *coo2=m2->getCoords()->getConstPointer();
6689 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
6690 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
6691 int offset2=offset1+m2->getNumberOfNodes();
6692 int offset3=offset2+((int)addCoords.size())/2;
6693 m1->getBoundingBoxForBBTree(bbox1);
6694 m2->getBoundingBoxForBBTree(bbox2);
6695 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
6696 int ncell1=m1->getNumberOfCells();
6698 for(int i=0;i<ncell1;i++)
6700 std::vector<int> candidates2;
6701 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
6702 std::map<INTERP_KERNEL::Node *,int> mapp;
6703 std::map<int,INTERP_KERNEL::Node *> mappRev;
6704 INTERP_KERNEL::QuadraticPolygon pol1;
6705 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
6706 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6707 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
6708 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
6709 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
6710 std::vector<int> crTmp,crITmp;
6711 crITmp.push_back(crI.back());
6712 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++)
6714 INTERP_KERNEL::QuadraticPolygon pol2;
6715 pol1.initLocations();
6716 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
6717 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
6718 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
6719 pol2.buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
6720 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
6721 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
6722 pol1.buildPartitionsAbs(pol2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
6726 cr.insert(cr.end(),crTmp.begin(),crTmp.end());
6727 crI.insert(crI.end(),crITmp.begin()+1,crITmp.end());
6729 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
6730 (*it).second->decrRef();
6735 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
6738 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
6739 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
6740 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
6741 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
6742 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
6744 static const int SPACEDIM=2;
6745 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
6746 desc2=DataArrayInt::New();
6747 descIndx2=DataArrayInt::New();
6748 revDesc2=DataArrayInt::New();
6749 revDescIndx2=DataArrayInt::New();
6750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
6751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
6752 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
6753 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
6754 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
6755 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
6756 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
6757 std::vector<double> bbox1,bbox2;
6758 m1Desc->getBoundingBoxForBBTree(bbox1);
6759 m2Desc->getBoundingBoxForBBTree(bbox2);
6760 int ncell1=m1Desc->getNumberOfCells();
6761 int ncell2=m2Desc->getNumberOfCells();
6762 intersectEdge1.resize(ncell1);
6763 colinear2.resize(ncell2);
6764 subDiv2.resize(ncell2);
6765 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
6766 std::vector<int> candidates1(1);
6767 int offset1=m1->getNumberOfNodes();
6768 int offset2=offset1+m2->getNumberOfNodes();
6769 for(int i=0;i<ncell1;i++)
6771 std::vector<int> candidates2;
6772 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
6773 if(!candidates2.empty())
6775 std::map<INTERP_KERNEL::Node *,int> map1,map2;
6776 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
6778 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
6779 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
6784 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
6786 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
6787 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
6791 * This method performs the 2nd step of Partition of 2D mesh.
6792 * This method has 4 inputs :
6793 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
6794 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
6795 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
6796 * 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'
6797 * @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'
6798 * @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.
6799 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
6801 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)
6803 int offset1=m1->getNumberOfNodes();
6804 int ncell=m2->getNumberOfCells();
6805 const int *c=m2->getNodalConnectivity()->getConstPointer();
6806 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
6807 const double *coo=m2->getCoords()->getConstPointer();
6808 const double *cooBis=m1->getCoords()->getConstPointer();
6809 int offset2=offset1+m2->getNumberOfNodes();
6810 intersectEdge.resize(ncell);
6811 for(int i=0;i<ncell;i++,cI++)
6813 const std::vector<int>& divs=subDiv[i];
6814 int nnode=cI[1]-cI[0]-1;
6815 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
6816 std::map<INTERP_KERNEL::Node *, int> mapp22;
6817 for(int j=0;j<nnode;j++)
6819 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
6820 int nnid=c[(*cI)+j+1];
6821 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
6822 mapp22[nn]=nnid+offset1;
6824 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
6825 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
6826 ((*it).second.first)->decrRef();
6827 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
6828 std::map<INTERP_KERNEL::Node *,int> mapp3;
6829 for(std::size_t j=0;j<divs.size();j++)
6832 INTERP_KERNEL::Node *tmp=0;
6834 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
6836 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
6838 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
6842 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
6843 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
6850 * 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).
6851 * 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
6852 * with a plane. The result will be put in 'cut3DSuf' out parameter.
6853 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
6854 * @param nodesOnPlane, returns all the nodes that are on the plane.
6855 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
6856 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
6857 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
6858 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
6859 * @param desc is the descending connectivity 3DSurf->3DCurve
6860 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
6861 * @param cut3DSuf input/output param.
6863 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
6864 const int *nodal3DCurve, const int *nodalIndx3DCurve,
6865 const int *desc, const int *descIndx,
6866 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
6868 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
6869 int nbOf3DSurfCell=(int)cut3DSurf.size();
6870 for(int i=0;i<nbOf3DSurfCell;i++)
6872 std::vector<int> res;
6873 int offset=descIndx[i];
6874 int nbOfSeg=descIndx[i+1]-offset;
6875 for(int j=0;j<nbOfSeg;j++)
6877 int edgeId=desc[offset+j];
6878 int status=cut3DCurve[edgeId];
6882 res.push_back(status);
6885 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
6886 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
6894 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
6900 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
6901 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
6904 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
6908 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
6913 {// case when plane is on a multi colinear edge of a polyhedron
6914 if((int)res.size()==2*nbOfSeg)
6916 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
6919 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
6926 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
6927 * 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).
6928 * 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
6929 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
6930 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
6931 * @param desc is the descending connectivity 3D->3DSurf
6932 * @param descIndx is the descending connectivity index 3D->3DSurf
6934 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
6935 const int *desc, const int *descIndx,
6936 std::vector<int>& nodalRes, std::vector<int>& nodalResIndx, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
6938 checkFullyDefined();
6939 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6940 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
6941 const int *nodal3D=_nodal_connec->getConstPointer();
6942 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
6943 int nbOfCells=getNumberOfCells();
6944 for(int i=0;i<nbOfCells;i++)
6946 std::map<int, std::set<int> > m;
6947 int offset=descIndx[i];
6948 int nbOfFaces=descIndx[i+1]-offset;
6951 for(int j=0;j<nbOfFaces;j++)
6953 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
6954 if(p.first!=-1 && p.second!=-1)
6958 start=p.first; end=p.second;
6959 m[p.first].insert(p.second);
6960 m[p.second].insert(p.first);
6964 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
6965 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
6966 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6967 INTERP_KERNEL::NormalizedCellType cmsId;
6968 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
6969 start=tmp[0]; end=tmp[nbOfNodesSon-1];
6970 for(unsigned k=0;k<nbOfNodesSon;k++)
6972 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
6973 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
6980 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
6984 std::map<int, std::set<int> >::const_iterator it=m.find(start);
6985 const std::set<int>& s=(*it).second;
6986 std::set<int> s2; s2.insert(prev);
6988 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
6991 int val=*s3.begin();
6992 conn.push_back(start);
6999 conn.push_back(end);
7002 nodalRes.insert(nodalRes.end(),conn.begin(),conn.end());
7003 nodalResIndx.push_back((int)nodalRes.size());
7004 cellIds.push_back(i);
7010 * 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
7011 * 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
7012 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7013 * 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
7014 * 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.
7016 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7018 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, std::vector<int>& nodalConnecOut) throw(INTERP_KERNEL::Exception)
7020 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7023 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7024 if(cm.getDimension()==2)
7026 const int *node=nodalConnBg+1;
7027 int startNode=*node++;
7028 double refX=coords[2*startNode];
7029 for(;node!=nodalConnEnd;node++)
7031 if(coords[2*(*node)]<refX)
7034 refX=coords[2*startNode];
7037 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7041 double angle0=-M_PI/2;
7047 while(nextNode!=startNode)
7051 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7053 if(*node!=tmpOut.back() && *node!=prevNode)
7055 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7056 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7061 res=angle0-angleM+2.*M_PI;
7070 if(nextNode!=startNode)
7072 angle0=angleNext-M_PI;
7075 prevNode=tmpOut.back();
7076 tmpOut.push_back(nextNode);
7079 std::vector<int> tmp3(2*(sz-1));
7080 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7081 std::copy(nodalConnBg+1,nodalConnEnd,it);
7082 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7084 nodalConnecOut.insert(nodalConnecOut.end(),nodalConnBg,nodalConnEnd);
7087 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7089 nodalConnecOut.insert(nodalConnecOut.end(),nodalConnBg,nodalConnEnd);
7094 nodalConnecOut.push_back((int)INTERP_KERNEL::NORM_POLYGON);
7095 nodalConnecOut.insert(nodalConnecOut.end(),tmpOut.begin(),tmpOut.end());
7101 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7105 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7106 * 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.
7108 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7109 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7110 * \param [in,out] arr array in which the remove operation will be done.
7111 * \param [in,out] arrIndx array in the remove operation will modify
7112 * \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])
7113 * \return true if \b arr and \b arrIndx have been modified, false if not.
7115 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7117 if(!arrIndx || !arr)
7118 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7119 if(offsetForRemoval<0)
7120 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7121 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7122 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7123 int *arrIPtr=arrIndx->getPointer();
7126 const int *arrPtr=arr->getConstPointer();
7127 std::vector<int> arrOut;
7128 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7130 if(*arrIPtr-previousArrI>offsetForRemoval)
7132 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7134 if(s.find(*work)==s.end())
7135 arrOut.push_back(*work);
7138 previousArrI=*arrIPtr;
7139 *arrIPtr=(int)arrOut.size();
7141 if(arr->getNumberOfTuples()==(int)arrOut.size())
7143 arr->alloc((int)arrOut.size(),1);
7144 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7149 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7150 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7151 * The selection of extraction is done standardly in new2old format.
7152 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
7154 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7155 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7156 * \param [in] arrIn arr origin array from which the extraction will be done.
7157 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7158 * \param [out] arrOut the resulting array
7159 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7161 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7162 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7164 if(!arrIn || !arrIndxIn)
7165 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7166 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7167 const int *arrInPtr=arrIn->getConstPointer();
7168 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7169 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7170 int maxSizeOfArr=arrIn->getNumberOfTuples();
7171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7173 arrIo->alloc((int)(sz+1),1);
7174 const int *idsIt=idsOfSelectBg;
7175 int *work=arrIo->getPointer();
7178 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7180 if(*idsIt>=0 && *idsIt<nbOfGrps)
7181 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7184 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7185 throw INTERP_KERNEL::Exception(oss.str().c_str());
7191 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7192 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7193 throw INTERP_KERNEL::Exception(oss.str().c_str());
7196 arro->alloc(lgth,1);
7197 work=arro->getPointer();
7198 idsIt=idsOfSelectBg;
7199 for(std::size_t i=0;i<sz;i++,idsIt++)
7201 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7202 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7205 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7206 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7207 throw INTERP_KERNEL::Exception(oss.str().c_str());
7217 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7218 * 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
7219 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7220 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7222 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7223 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7224 * \param [in] arrIn arr origin array from which the extraction will be done.
7225 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7226 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7227 * \param [in] srcArrIndex index array of \b srcArr
7228 * \param [out] arrOut the resulting array
7229 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7231 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7233 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7234 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7235 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7237 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7241 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7242 std::vector<bool> v(nbOfTuples,true);
7244 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7245 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7246 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7248 if(*it>=0 && *it<nbOfTuples)
7251 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7255 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7256 throw INTERP_KERNEL::Exception(oss.str().c_str());
7259 srcArrIndexPtr=srcArrIndex->getConstPointer();
7260 arrIo->alloc(nbOfTuples+1,1);
7261 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7262 const int *arrInPtr=arrIn->getConstPointer();
7263 const int *srcArrPtr=srcArr->getConstPointer();
7264 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7265 int *arroPtr=arro->getPointer();
7266 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7270 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7271 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7275 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7276 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7277 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7280 arrOut=arro; arro->incrRef();
7281 arrIndexOut=arrIo; arrIo->incrRef();
7285 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7286 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7288 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7289 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7290 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7291 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7292 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7293 * \param [in] srcArrIndex index array of \b srcArr
7295 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7297 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7298 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7300 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7301 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7302 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7303 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7304 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7305 int *arrInOutPtr=arrInOut->getPointer();
7306 const int *srcArrPtr=srcArr->getConstPointer();
7307 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7309 if(*it>=0 && *it<nbOfTuples)
7311 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7312 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7315 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] !";
7316 throw INTERP_KERNEL::Exception(oss.str().c_str());
7321 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7322 throw INTERP_KERNEL::Exception(oss.str().c_str());
7328 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7329 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7330 * 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]].
7331 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7332 * A negative value in \b arrIn means that it is ignored.
7333 * 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.
7335 * \param [in] arrIn arr origin array from which the extraction will be done.
7336 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7337 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7339 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
7341 if(!arrIn || !arrIndxIn)
7342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7343 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7346 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
7349 const int *arrInPtr=arrIn->getConstPointer();
7350 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7352 arro->alloc(nbOfTuples,1);
7353 arro->fillWithValue(-1);
7354 int *arroPtr=arro->getPointer();
7355 std::set<int> s; s.insert(0);
7359 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7361 for(const int *work=arrInPtr+arrIndxPtr[*it];work!=arrInPtr+arrIndxPtr[*it+1];work++)
7363 if(*work>=0 && arroPtr[*work]<0)
7372 return arro->getIdsEqual(1);
7376 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7377 * 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
7378 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7379 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7381 * \param [in] start begin of set of ids of the input extraction (included)
7382 * \param [in] end end of set of ids of the input extraction (excluded)
7383 * \param [in] step step of the set of ids in range mode.
7384 * \param [in] arrIn arr origin array from which the extraction will be done.
7385 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7386 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7387 * \param [in] srcArrIndex index array of \b srcArr
7388 * \param [out] arrOut the resulting array
7389 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7391 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
7393 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7394 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7395 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7397 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
7399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7401 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7403 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7404 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7405 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
7407 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7409 if(it>=0 && it<nbOfTuples)
7410 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7413 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7414 throw INTERP_KERNEL::Exception(oss.str().c_str());
7417 srcArrIndexPtr=srcArrIndex->getConstPointer();
7418 arrIo->alloc(nbOfTuples+1,1);
7419 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7420 const int *arrInPtr=arrIn->getConstPointer();
7421 const int *srcArrPtr=srcArr->getConstPointer();
7422 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7423 int *arroPtr=arro->getPointer();
7424 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7426 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
7429 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7430 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7434 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7435 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7438 arrOut=arro; arro->incrRef();
7439 arrIndexOut=arrIo; arrIo->incrRef();
7443 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7444 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7446 * \param [in] start begin of set of ids of the input extraction (included)
7447 * \param [in] end end of set of ids of the input extraction (excluded)
7448 * \param [in] step step of the set of ids in range mode.
7449 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7450 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7451 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7452 * \param [in] srcArrIndex index array of \b srcArr
7454 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7456 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7457 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7459 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
7461 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7462 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7463 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7464 int *arrInOutPtr=arrInOut->getPointer();
7465 const int *srcArrPtr=srcArr->getConstPointer();
7466 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
7468 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7470 if(it>=0 && it<nbOfTuples)
7472 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
7473 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
7476 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7477 throw INTERP_KERNEL::Exception(oss.str().c_str());
7482 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7483 throw INTERP_KERNEL::Exception(oss.str().c_str());
7489 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
7490 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
7491 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
7492 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
7493 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
7495 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
7497 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
7499 checkFullyDefined();
7500 int mdim=getMeshDimension();
7501 int spaceDim=getSpaceDimension();
7503 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
7504 int nbCells=getNumberOfCells();
7505 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
7506 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
7507 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
7508 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
7509 ret->setCoords(getCoords());
7510 ret->allocateCells((int)partition.size());
7512 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
7514 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
7515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
7519 cell=tmp->buildUnionOf2DMesh();
7522 cell=tmp->buildUnionOf3DMesh();
7525 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
7528 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
7531 ret->finishInsertingCells();
7532 ret->incrRef(); return ret;
7536 * This method partitions \b this into contiguous zone.
7537 * This method only needs a well defined connectivity. Coordinates are not considered here.
7538 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
7540 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
7542 int nbOfCellsCur=getNumberOfCells();
7543 DataArrayInt *neigh=0,*neighI=0;
7544 computeNeighborsOfCells(neigh,neighI);
7545 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
7546 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
7547 std::vector<DataArrayInt *> ret;
7548 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
7549 while(nbOfCellsCur>0)
7551 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
7552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
7553 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
7554 ret2.push_back(tmp2); ret.push_back(tmp2);
7555 nbOfCellsCur=tmp3->getNumberOfTuples();
7558 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
7559 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
7562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
7563 neighAuto->transformWithIndArr(renum->begin(),renum->end());
7566 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
7572 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
7573 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
7575 * \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.
7576 * \return a newly allocated DataArrayInt to be managed by the caller.
7577 * \throw In case of \a code has not the right format (typically of size 3*n)
7579 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
7581 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
7582 std::size_t nb=code.size()/3;
7583 if(code.size()%3!=0)
7584 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
7585 ret->alloc((int)nb,2);
7586 int *retPtr=ret->getPointer();
7587 for(std::size_t i=0;i<nb;i++,retPtr+=2)
7589 retPtr[0]=code[3*i+2];
7590 retPtr[1]=code[3*i+2]+code[3*i+1];
7596 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
7597 _own_cell(true),_cell_id(-1),_nb_cell(0)
7602 _nb_cell=mesh->getNumberOfCells();
7606 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
7614 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
7615 _own_cell(false),_cell_id(bg-1),
7622 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
7625 if(_cell_id<_nb_cell)
7634 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
7640 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
7642 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
7645 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
7651 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
7659 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
7665 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
7670 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
7675 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
7677 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
7680 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
7685 _nb_cell=mesh->getNumberOfCells();
7689 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
7696 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
7698 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
7699 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
7700 if(_cell_id<_nb_cell)
7702 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
7703 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
7704 int startId=_cell_id;
7705 _cell_id+=nbOfElems;
7706 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
7712 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
7716 _conn=mesh->getNodalConnectivity()->getPointer();
7717 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
7721 void MEDCouplingUMeshCell::next()
7723 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
7728 _conn_lgth=_conn_indx[1]-_conn_indx[0];
7731 std::string MEDCouplingUMeshCell::repr() const
7733 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
7735 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
7737 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
7741 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
7744 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
7746 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
7747 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
7749 return INTERP_KERNEL::NORM_ERROR;
7752 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
7755 if(_conn_lgth!=NOTICABLE_FIRST_VAL)