1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
29 #include "SplitterTetra.hxx"
30 #include "DirectedBoundingBox.hxx"
31 #include "InterpKernelMeshQuality.hxx"
32 #include "InterpKernelCellSimplify.hxx"
33 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
34 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
35 #include "InterpKernelAutoPtr.hxx"
36 #include "InterpKernelGeo2DNode.hxx"
37 #include "InterpKernelGeo2DEdgeLin.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
48 using namespace ParaMEDMEM;
50 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
54 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 return new MEDCouplingUMesh;
59 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
62 ret->setName(meshName);
63 ret->setMeshDimension(meshDim);
67 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
72 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
74 return new MEDCouplingUMesh(*this,recDeepCpy);
77 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
81 ret+=_nodal_connec->getHeapMemorySize();
82 if(_nodal_connec_index)
83 ret+=_nodal_connec_index->getHeapMemorySize();
84 return MEDCouplingPointSet::getHeapMemorySize()+ret;
87 void MEDCouplingUMesh::updateTime() const
89 MEDCouplingPointSet::updateTime();
92 updateTimeWith(*_nodal_connec);
94 if(_nodal_connec_index)
96 updateTimeWith(*_nodal_connec_index);
100 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
105 * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity.
106 * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be
107 * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check
108 * that all is in order in 'this'.
110 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
113 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
115 MEDCouplingPointSet::checkCoherency();
116 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
118 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
120 std::ostringstream message;
121 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
122 throw INTERP_KERNEL::Exception(message.str().c_str());
127 if(_nodal_connec->getNumberOfComponents()!=1)
128 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
129 if(_nodal_connec->getInfoOnComponent(0)!="")
130 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
132 if(_nodal_connec_index)
134 if(_nodal_connec_index->getNumberOfComponents()!=1)
135 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
136 if(_nodal_connec_index->getInfoOnComponent(0)!="")
137 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
142 * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does.
143 * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids.
144 * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2.
146 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
151 int meshDim=getMeshDimension();
152 int nbOfNodes=getNumberOfNodes();
153 int nbOfCells=getNumberOfCells();
154 const int *ptr=_nodal_connec->getConstPointer();
155 const int *ptrI=_nodal_connec_index->getConstPointer();
156 for(int i=0;i<nbOfCells;i++)
158 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
159 if((int)cm.getDimension()!=meshDim)
161 std::ostringstream oss;
162 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
163 throw INTERP_KERNEL::Exception(oss.str().c_str());
165 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
167 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
169 std::ostringstream oss;
170 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
171 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
172 throw INTERP_KERNEL::Exception(oss.str().c_str());
174 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
179 if(nodeId>=nbOfNodes)
181 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
182 throw INTERP_KERNEL::Exception(oss.str().c_str());
187 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
188 throw INTERP_KERNEL::Exception(oss.str().c_str());
192 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
194 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
195 throw INTERP_KERNEL::Exception(oss.str().c_str());
202 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
204 checkCoherency1(eps);
207 void MEDCouplingUMesh::setMeshDimension(int meshDim)
209 if(meshDim<-1 || meshDim>3)
210 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
215 void MEDCouplingUMesh::allocateCells(int nbOfCells)
217 if(_nodal_connec_index)
219 _nodal_connec_index->decrRef();
223 _nodal_connec->decrRef();
225 _nodal_connec_index=DataArrayInt::New();
226 _nodal_connec_index->reserve(nbOfCells+1);
227 _nodal_connec_index->pushBackSilent(0);
228 _nodal_connec=DataArrayInt::New();
229 _nodal_connec->reserve(2*nbOfCells);
235 * Appends a cell in connectivity array.
236 * @param type type of cell to add.
237 * @param size number of nodes constituting this cell.
238 * @param nodalConnOfCell the connectivity of the cell to add.
240 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
242 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
243 if(_nodal_connec_index==0)
244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
245 if((int)cm.getDimension()==_mesh_dim)
248 if(size!=(int)cm.getNumberOfNodes())
250 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
251 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 int idx=_nodal_connec_index->back();
256 _nodal_connec_index->pushBackSilent(val);
257 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
262 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
263 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
264 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
270 * Method to be called to cloture the insertion of cells using this->insertNextCell.
272 void MEDCouplingUMesh::finishInsertingCells()
274 _nodal_connec->pack();
275 _nodal_connec_index->pack();
276 _nodal_connec->declareAsNew();
277 _nodal_connec_index->declareAsNew();
282 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
283 * Useful for python users.
285 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
287 return new MEDCouplingUMeshCellIterator(this);
291 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
292 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
293 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
294 * Useful for python users.
296 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
298 if(!checkConsecutiveCellTypes())
299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
300 return new MEDCouplingUMeshCellByTypeEntry(this);
303 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
309 * This method is a method that compares 'this' and 'other'.
310 * This method compares \b all attributes, even names and component names.
312 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
316 std::ostringstream oss; oss.precision(15);
317 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
320 reason="mesh given in input is not castable in MEDCouplingUMesh !";
323 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
325 if(_mesh_dim!=otherC->_mesh_dim)
327 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
331 if(_types!=otherC->_types)
333 oss << "umesh geometric type mismatch :\nThis geometric types are :";
334 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
335 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
336 oss << "\nOther geometric types are :";
337 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
338 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
342 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
343 if(_nodal_connec==0 || otherC->_nodal_connec==0)
345 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
348 if(_nodal_connec!=otherC->_nodal_connec)
349 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
351 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
354 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
355 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
357 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
360 if(_nodal_connec_index!=otherC->_nodal_connec_index)
361 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
363 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
369 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
371 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
374 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
376 if(_mesh_dim!=otherC->_mesh_dim)
378 if(_types!=otherC->_types)
380 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
381 if(_nodal_connec==0 || otherC->_nodal_connec==0)
383 if(_nodal_connec!=otherC->_nodal_connec)
384 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
386 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
387 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
389 if(_nodal_connec_index!=otherC->_nodal_connec_index)
390 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
396 * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
397 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
399 * In case of success cellCor and nodeCor are informed both.
400 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
401 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
402 * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
404 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
405 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
407 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
409 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
410 MEDCouplingMesh::checkFastEquivalWith(other,prec);
411 if(_types!=otherC->_types)
412 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
413 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
416 int oldNbOfNodes=getNumberOfNodes();
417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
420 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
421 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
422 if(pt!=da->getConstPointer()+da->getNbOfElems())
423 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
424 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
427 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
430 da=m->zipConnectivityTraducer(cellCompPol);
431 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
432 pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
433 if(pt!=da->getConstPointer()+da->getNbOfElems())
434 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
436 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
437 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
441 * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
442 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
443 * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
444 * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception !
446 * In case of success cellCor are informed both.
447 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
448 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
450 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
451 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
453 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
455 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
456 MEDCouplingMesh::checkFastEquivalWith(other,prec);
457 if(_types!=otherC->_types)
458 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
459 if(_coords!=otherC->_coords)
460 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
461 std::vector<const MEDCouplingUMesh *> ms(2);
464 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
466 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
467 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
468 if(pt!=da->getConstPointer()+da->getNbOfElems())
470 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
473 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
477 * This method checks fastly that 'this' and 'other' are equal.
479 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
481 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
483 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
484 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
485 int nbOfCells=getNumberOfCells();
489 status&=areCellsFrom2MeshEqual(otherC,0,prec);
490 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
491 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
493 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
497 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
498 * For speed reasons no check of this will be done.
500 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
503 int nbOfNodes=getNumberOfNodes();
504 int *revNodalIndxPtr=new int[nbOfNodes+1];
505 revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
506 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
507 const int *conn=_nodal_connec->getConstPointer();
508 const int *connIndex=_nodal_connec_index->getConstPointer();
509 int nbOfCells=getNumberOfCells();
510 int nbOfEltsInRevNodal=0;
511 for(int eltId=0;eltId<nbOfCells;eltId++)
513 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
514 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
515 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
516 if(*iter>=0)//for polyhedrons
518 nbOfEltsInRevNodal++;
519 revNodalIndxPtr[(*iter)+1]++;
522 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
523 int *revNodalPtr=new int[nbOfEltsInRevNodal];
524 revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
525 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
526 for(int eltId=0;eltId<nbOfCells;eltId++)
528 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
529 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
530 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
531 if(*iter>=0)//for polyhedrons
532 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
538 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
543 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
549 if(cm.getOrientationStatus(nb,conn1,conn2))
556 class MinusOneSonsGenerator
559 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
560 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
561 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
562 static const int DELTA=1;
564 const INTERP_KERNEL::CellModel& _cm;
567 class MinusOneSonsGeneratorBiQuadratic
570 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
571 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
572 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
573 static const int DELTA=1;
575 const INTERP_KERNEL::CellModel& _cm;
578 class MinusTwoSonsGenerator
581 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
582 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
583 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
584 static const int DELTA=2;
586 const INTERP_KERNEL::CellModel& _cm;
592 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
593 * For speed reasons no check of this will be done.
594 * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
595 * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
596 * The algorithm to compute this p-1 mesh is the following :
597 * For each cell in 'this' it splits into p-1 elements.
598 * If this p-1 element does not already exists it is appended to the returned mesh
599 * If this p-1 element already exists, it is not appended.
600 * This method returns or 4 arrays plus the returned mesh.
601 * 'desc' and 'descIndx' are the descending connectivity. These 2 arrays tell for each cell in 'this', to wich p-1 dimension cell in returned mesh it refers.
602 * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
604 * Reversely 'revDesc' and 'revDescIndx' are the reverse descending connectivity. These 2 arrays tell for each cell in returned mesh, to wich cell in 'this' it refers.
605 * For a cell with a cellid d in returned p-1 mesh it is shared by the following cells in 'this' [revDesc+revDescIndx[d],revDesc+revDescIndx[d+1])
607 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
608 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
610 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
612 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
616 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
617 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
618 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
619 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
620 * \sa MEDCouplingUMesh::buildDescendingConnectivity
622 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
625 if(getMeshDimension()!=3)
626 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
627 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
631 * WARNING this method do the assumption that connectivity lies on the coordinates set.
632 * For speed reasons no check of this will be done.
633 * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
634 * This method is more precise because it returns in descending connectivity giving the direction. If value is positive the n-1 dim element is taken in the same direction,
635 * if it is in the opposite direction it is retrieved negative. So the problem is for elemt #0 in C convention. That's why this method is the only one that retrieves
636 * an array in relative "FORTRAN" mode.
638 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
639 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
641 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
643 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
647 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
648 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
649 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
650 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
652 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
653 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
654 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
656 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
660 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
664 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
668 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
669 * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
670 * excluding a set of meshdim-1 cells in input descending connectivity.
671 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
672 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
673 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
675 * \param [in] desc descending connectivity array.
676 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
677 * \param [in] revDesc reverse descending connectivity array.
678 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
679 * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
680 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
681 * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
683 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
684 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
686 if(!desc || !descIndx || !revDesc || !revDescIndx)
687 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
688 const int *descPtr=desc->getConstPointer();
689 const int *descIPtr=descIndx->getConstPointer();
690 const int *revDescPtr=revDesc->getConstPointer();
691 const int *revDescIPtr=revDescIndx->getConstPointer();
693 int nbCells=descIndx->getNumberOfTuples()-1;
694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
695 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
696 int *out1Ptr=out1->getPointer();
698 out0->reserve(desc->getNumberOfTuples());
699 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
701 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
703 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
705 out0->insertAtTheEnd(s.begin(),s.end());
707 *out1Ptr=out0->getNumberOfTuples();
709 neighbors=out0.retn();
710 neighborsIndx=out1.retn();
716 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
717 * For speed reasons no check of this will be done.
719 template<class SonsGenerator>
720 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
722 if(!desc || !descIndx || !revDesc || !revDescIndx)
723 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
724 checkConnectivityFullyDefined();
725 int nbOfCells=getNumberOfCells();
726 int nbOfNodes=getNumberOfNodes();
727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
728 int *revNodalIndxPtr=revNodalIndx->getPointer();
729 const int *conn=_nodal_connec->getConstPointer();
730 const int *connIndex=_nodal_connec_index->getConstPointer();
731 std::string name="Mesh constituent of "; name+=getName();
732 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
733 ret->setCoords(getCoords());
734 ret->allocateCells(2*nbOfCells);
735 descIndx->alloc(nbOfCells+1,1);
736 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
737 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
738 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
740 int pos=connIndex[eltId];
741 int posP1=connIndex[eltId+1];
742 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
743 SonsGenerator sg(cm);
744 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
745 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
746 for(unsigned i=0;i<nbOfSons;i++)
748 INTERP_KERNEL::NormalizedCellType cmsId;
749 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
750 for(unsigned k=0;k<nbOfNodesSon;k++)
752 revNodalIndxPtr[tmp[k]+1]++;
753 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
754 revDesc2->pushBackSilent(eltId);
756 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
758 int nbOfCellsM1=ret->getNumberOfCells();
759 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
761 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
762 int *revNodalPtr=revNodal->getPointer();
763 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
764 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
765 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
767 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
768 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
769 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
770 if(*iter>=0)//for polyhedrons
771 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
774 DataArrayInt *commonCells=0,*commonCellsI=0;
775 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
777 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
778 int newNbOfCellsM1=-1;
779 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
780 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
781 std::vector<bool> isImpacted(nbOfCellsM1,false);
782 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
783 for(int work2=work[0];work2!=work[1];work2++)
784 isImpacted[commonCellsPtr[work2]]=true;
785 const int *o2nM1Ptr=o2nM1->getConstPointer();
786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
787 const int *n2oM1Ptr=n2oM1->getConstPointer();
788 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
789 ret2->copyTinyInfoFrom(this);
790 desc->alloc(descIndx->back(),1);
791 int *descPtr=desc->getPointer();
792 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
793 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
796 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
799 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
801 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
802 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
805 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
808 revDesc->reserve(newNbOfCellsM1);
809 revDescIndx->alloc(newNbOfCellsM1+1,1);
810 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
811 const int *revDesc2Ptr=revDesc2->getConstPointer();
812 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
814 int oldCellIdM1=n2oM1Ptr[i];
815 if(!isImpacted[oldCellIdM1])
817 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
818 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
822 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
823 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
824 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
832 struct MEDCouplingAccVisit
834 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
835 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
836 int _new_nb_of_nodes;
843 * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
844 * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
845 * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
846 * If mesh dimension is not in [2,3] an exception is thrown.
847 * Of course pay attention that the resulting mesh is slower than previous one.
848 * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
849 * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
850 * If mesh==3, after throw the mesh is \b unconsistent !
851 * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
853 * \warning This method modifies can modify significantly the geometric type order in \a this.
854 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
856 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
859 int dim=getMeshDimension();
861 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
862 int nbOfCells=getNumberOfCells();
865 const int *connIndex=_nodal_connec_index->getConstPointer();
866 int *conn=_nodal_connec->getPointer();
867 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
869 if(*iter>=0 && *iter<nbOfCells)
871 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
873 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
875 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
879 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
880 oss << " in range [0," << nbOfCells << ") !";
881 throw INTERP_KERNEL::Exception(oss.str().c_str());
887 int *connIndex=_nodal_connec_index->getPointer();
888 int connIndexLgth=_nodal_connec_index->getNbOfElems();
889 const int *connOld=_nodal_connec->getConstPointer();
890 int connOldLgth=_nodal_connec->getNbOfElems();
891 std::vector<int> connNew(connOld,connOld+connOldLgth);
892 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
894 if(*iter>=0 && *iter<nbOfCells)
896 int pos=connIndex[*iter];
897 int posP1=connIndex[(*iter)+1];
898 int lgthOld=posP1-pos-1;
899 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
900 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
901 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
902 int *tmp=new int[nbOfFaces*lgthOld];
904 for(int j=0;j<(int)nbOfFaces;j++)
906 INTERP_KERNEL::NormalizedCellType type;
907 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
911 std::size_t newLgth=std::distance(tmp,work)-1;
912 std::size_t delta=newLgth-lgthOld;
913 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
914 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
915 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
920 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
921 oss << " in range [0," << nbOfCells << ") !";
922 throw INTERP_KERNEL::Exception(oss.str().c_str());
925 _nodal_connec->alloc((int)connNew.size(),1);
926 int *newConnPtr=_nodal_connec->getPointer();
927 std::copy(connNew.begin(),connNew.end(),newConnPtr);
933 * This method converts all cells into poly type if possible.
934 * This method is purely for userfriendliness.
935 * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
937 void MEDCouplingUMesh::convertAllToPoly()
939 int nbOfCells=getNumberOfCells();
940 std::vector<int> cellIds(nbOfCells);
941 for(int i=0;i<nbOfCells;i++)
943 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
947 * This method expects that 'this' has a spacedim equal to 3 and a mesh dimension equal to 3 too, if not an exception will be thrown.
948 * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
949 * For such polyhedra, they are expected to have only 1 face (containing 2 faces in opposition), having 2*n number of nodes (n nodes on
950 * each 2 faces hidden in the single face of polyhedron).
951 * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
952 * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
953 * In case of presence of polyhedron that has not the extruded aspect (2 faces with the same number of nodes) an exception is thrown and 'this'
955 * This method is useful only for users that wants to build extruded unstructured mesh.
956 * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
957 * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
959 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
962 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
963 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
964 int nbOfCells=getNumberOfCells();
965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
966 newCi->alloc(nbOfCells+1,1);
967 int *newci=newCi->getPointer();
968 const int *ci=_nodal_connec_index->getConstPointer();
969 const int *c=_nodal_connec->getConstPointer();
971 for(int i=0;i<nbOfCells;i++)
973 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
974 if(type==INTERP_KERNEL::NORM_POLYHED)
976 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
978 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
979 throw INTERP_KERNEL::Exception(oss.str().c_str());
981 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
984 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
985 throw INTERP_KERNEL::Exception(oss.str().c_str());
988 newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
991 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
994 newC->alloc(newci[nbOfCells],1);
995 int *newc=newC->getPointer();
996 for(int i=0;i<nbOfCells;i++)
998 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
999 if(type==INTERP_KERNEL::NORM_POLYHED)
1001 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1002 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1004 for(std::size_t j=0;j<n1;j++)
1006 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1008 newc[n1+5*j+1]=c[ci[i]+1+j];
1009 newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
1010 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1011 newc[n1+5*j+4]=c[ci[i]+1+j+n1];
1016 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1018 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1019 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1023 * This method is the opposite of ParaMEDMEM::MEDCouplingUMesh::convertToPolyTypes method.
1024 * The aim is to take all polygons or polyhedrons cell and to try to traduce them into classical cells.
1026 * \return If true at least one cell has been unpolyzed.
1027 \n If false has been returned the nodal connectivity of \a this has **not** been altered and \a this has remains unchanged.
1029 * \warning This method modifies can modify significantly the geometric type order in \a this.
1030 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1032 bool MEDCouplingUMesh::unPolyze()
1034 checkFullyDefined();
1035 int mdim=getMeshDimension();
1037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1040 int nbOfCells=getNumberOfCells();
1043 int initMeshLgth=getMeshLength();
1044 int *conn=_nodal_connec->getPointer();
1045 int *index=_nodal_connec_index->getPointer();
1050 for(int i=0;i<nbOfCells;i++)
1052 lgthOfCurCell=index[i+1]-posOfCurCell;
1053 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1054 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1055 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1059 switch(cm.getDimension())
1063 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1064 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1065 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1070 int nbOfFaces,lgthOfPolyhConn;
1071 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1072 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1077 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1081 ret=ret || (newType!=type);
1082 conn[newPos]=newType;
1084 posOfCurCell=index[i+1];
1089 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1090 newPos+=lgthOfCurCell;
1091 posOfCurCell+=lgthOfCurCell;
1095 if(newPos!=initMeshLgth)
1096 _nodal_connec->reAlloc(newPos);
1103 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1104 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1105 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1107 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal
1110 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1112 checkFullyDefined();
1113 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1115 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1116 coords->recenterForMaxPrecision(eps);
1118 int nbOfCells=getNumberOfCells();
1119 const int *conn=_nodal_connec->getConstPointer();
1120 const int *index=_nodal_connec_index->getConstPointer();
1121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1122 connINew->alloc(nbOfCells+1,1);
1123 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1126 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1128 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1130 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1134 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1135 *connINewPtr=connNew->getNumberOfTuples();
1138 setConnectivity(connNew,connINew,false);
1142 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1143 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1144 * the format of returned DataArrayInt instance.
1146 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1147 * \sa MEDCouplingUMesh::getNodeIdsInUse
1149 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1151 checkConnectivityFullyDefined();
1152 int nbOfCells=getNumberOfCells();
1153 const int *connIndex=_nodal_connec_index->getConstPointer();
1154 const int *conn=_nodal_connec->getConstPointer();
1155 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1156 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1157 std::vector<bool> retS(maxElt,false);
1158 for(int i=0;i<nbOfCells;i++)
1159 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1163 for(int i=0;i<maxElt;i++)
1166 DataArrayInt *ret=DataArrayInt::New();
1168 int *retPtr=ret->getPointer();
1169 for(int i=0;i<maxElt;i++)
1176 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1177 * \sa MEDCouplingUMesh::getNodeIdsInUse
1179 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1181 int nbOfNodes=(int)nodeIdsInUse.size();
1182 int nbOfCells=getNumberOfCells();
1183 const int *connIndex=_nodal_connec_index->getConstPointer();
1184 const int *conn=_nodal_connec->getConstPointer();
1185 for(int i=0;i<nbOfCells;i++)
1186 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1189 if(conn[j]<nbOfNodes)
1190 nodeIdsInUse[conn[j]]=true;
1193 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1194 throw INTERP_KERNEL::Exception(oss.str().c_str());
1200 * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
1201 * The returned array is newly created and should be dealt by the caller.
1202 * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
1203 * The size of returned array is the number of nodes of 'this'.
1204 * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
1205 * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
1206 * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
1207 * \throw if a cell contains in its nodal connectivity a node id >= nb of nodes an exception will be thrown.
1208 * \sa MEDCouplingUMesh::computeNodeIdsAlg
1210 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1213 int nbOfNodes=getNumberOfNodes();
1214 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1215 ret->alloc(nbOfNodes,1);
1216 int *traducer=ret->getPointer();
1217 std::fill(traducer,traducer+nbOfNodes,-1);
1218 int nbOfCells=getNumberOfCells();
1219 const int *connIndex=_nodal_connec_index->getConstPointer();
1220 const int *conn=_nodal_connec->getConstPointer();
1221 for(int i=0;i<nbOfCells;i++)
1222 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1225 if(conn[j]<nbOfNodes)
1226 traducer[conn[j]]=1;
1229 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1230 throw INTERP_KERNEL::Exception(oss.str().c_str());
1233 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1234 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1239 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1240 * For each cell in \b this the number of nodes constituting cell is computed.
1241 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1242 * For polyhedrons, the face separation (-1) are excluded from the couting.
1244 * \return a newly allocated array
1246 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1248 checkConnectivityFullyDefined();
1249 int nbOfCells=getNumberOfCells();
1250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1251 ret->alloc(nbOfCells,1);
1252 int *retPtr=ret->getPointer();
1253 const int *conn=getNodalConnectivity()->getConstPointer();
1254 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1255 for(int i=0;i<nbOfCells;i++,retPtr++)
1257 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1258 *retPtr=connI[i+1]-connI[i]-1;
1260 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1266 * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
1267 * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
1268 * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
1269 * -1 values in returned array means that the corresponding old node is no more used.
1271 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1273 int newNbOfNodes=-1;
1274 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1275 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1280 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1281 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1283 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1288 return AreCellsEqual0(conn,connI,cell1,cell2);
1290 return AreCellsEqual1(conn,connI,cell1,cell2);
1292 return AreCellsEqual2(conn,connI,cell1,cell2);
1294 return AreCellsEqual3(conn,connI,cell1,cell2);
1296 return AreCellsEqual7(conn,connI,cell1,cell2);
1298 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1302 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1304 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1306 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1307 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1312 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1314 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1316 int sz=connI[cell1+1]-connI[cell1];
1317 if(sz==connI[cell2+1]-connI[cell2])
1319 if(conn[connI[cell1]]==conn[connI[cell2]])
1321 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1322 unsigned dim=cm.getDimension();
1328 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1329 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1330 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1331 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1332 return work!=tmp+sz1?1:0;
1335 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1345 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1347 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1349 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1351 if(conn[connI[cell1]]==conn[connI[cell2]])
1353 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1354 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1362 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1364 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1366 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1368 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1369 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1376 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1378 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1380 int sz=connI[cell1+1]-connI[cell1];
1381 if(sz==connI[cell2+1]-connI[cell2])
1383 if(conn[connI[cell1]]==conn[connI[cell2]])
1385 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1386 unsigned dim=cm.getDimension();
1392 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1393 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1394 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1395 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1400 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1401 std::reverse_iterator<int *> it2((int *)tmp);
1402 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1408 return work!=tmp+sz1?1:0;
1411 {//case of SEG2 and SEG3
1412 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1414 if(!cm.isQuadratic())
1416 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1417 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1418 if(std::equal(it1,it2,conn+connI[cell2]+1))
1424 if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1431 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1439 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1440 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1442 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1444 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1446 std::vector<int> c1,c2;
1447 getNodeIdsOfCell(cellId,c1);
1448 other->getNodeIdsOfCell(cellId,c2);
1449 std::size_t sz=c1.size();
1452 for(std::size_t i=0;i<sz;i++)
1454 std::vector<double> n1,n2;
1455 getCoordinatesOfNode(c1[0],n1);
1456 other->getCoordinatesOfNode(c2[0],n2);
1457 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1458 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1459 if(*std::max_element(n1.begin(),n1.end())>prec)
1466 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1467 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1468 * and result remains unchanged.
1469 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1470 * If in 'candidates' pool -1 value is considered as an empty value.
1471 * WARNING this method returns only ONE set of result !
1473 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1475 if(candidates.size()<1)
1478 std::vector<int>::const_iterator iter=candidates.begin();
1479 int start=(*iter++);
1480 for(;iter!=candidates.end();iter++)
1482 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1487 result->pushBackSilent(start);
1491 result->pushBackSilent(*iter);
1493 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1500 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1501 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1503 * \param [in] compType input specifying the technique used to compare cells each other.
1504 * - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1505 * - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1506 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1507 * - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1508 * can be used for users not sensitive to orientation of cell
1509 * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1510 * \param [out] commonCells
1511 * \param [out] commonCellsI
1512 * \return the correspondance array old to new in a newly allocated array.
1515 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1517 checkConnectivityFullyDefined();
1518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1519 getReverseNodalConnectivity(revNodal,revNodalI);
1520 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1523 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1524 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1526 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1527 int nbOfCells=nodalI->getNumberOfTuples()-1;
1528 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1529 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1530 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1531 std::vector<bool> isFetched(nbOfCells,false);
1534 for(int i=0;i<nbOfCells;i++)
1538 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1539 std::vector<int> v,v2;
1540 if(connOfNode!=connPtr+connIPtr[i+1])
1542 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1543 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1546 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1550 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1551 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1552 v2.resize(std::distance(v2.begin(),it));
1556 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1558 int pos=commonCellsI->back();
1559 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1560 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1561 isFetched[*it]=true;
1569 for(int i=startCellId;i<nbOfCells;i++)
1573 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1574 std::vector<int> v,v2;
1575 if(connOfNode!=connPtr+connIPtr[i+1])
1577 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1580 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1584 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1585 v2.resize(std::distance(v2.begin(),it));
1589 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1591 int pos=commonCellsI->back();
1592 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1593 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1594 isFetched[*it]=true;
1600 commonCellsArr=commonCells.retn();
1601 commonCellsIArr=commonCellsI.retn();
1605 * This method could potentially modify \a this. This method merges cells if there are cells equal in \a this. The comparison is specified by \a compType.
1606 * This method keeps the coordiantes of \a this.
1608 * \param [in] compType input specifying the technique used to compare cells each other.
1609 * - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1610 * - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1611 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1612 * - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1613 * can be used for users not sensitive to orientation of cell
1614 * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned
1615 * \return the correspondance array old to new in a newly allocated array.
1617 * \warning This method modifies can modify significantly the geometric type order in \a this.
1618 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1620 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1622 DataArrayInt *commonCells=0,*commonCellsI=0;
1623 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1625 int newNbOfCells=-1;
1626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1627 commonCellsI->end(),newNbOfCells);
1628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1629 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1630 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1635 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1636 * This method tries to determine if 'other' is fully included in 'this'. To compute that, this method works with connectivity as MEDCouplingUMesh::zipConnectivityTraducer method does.
1637 * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
1638 * The main difference is that this method is not expected to throw exception.
1639 * This method has two outputs :
1641 * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
1642 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1643 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1645 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1647 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1648 int nbOfCells=getNumberOfCells();
1649 static const int possibleCompType[]={0,1,2};
1650 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1652 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1653 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1655 throw INTERP_KERNEL::Exception(oss.str().c_str());
1657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1658 arr=o2n->substr(nbOfCells);
1659 arr->setName(other->getName());
1661 if(other->getNumberOfCells()==0)
1663 return arr->getMaxValue(tmp)<nbOfCells;
1667 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1668 * This method tries to determine if \b other is fully included in \b this.
1669 * The main difference is that this method is not expected to throw exception.
1670 * This method has two outputs :
1672 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1673 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1675 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1677 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1678 DataArrayInt *commonCells=0,*commonCellsI=0;
1679 int thisNbCells=getNumberOfCells();
1680 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1682 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1683 int otherNbCells=other->getNumberOfCells();
1684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1685 arr2->alloc(otherNbCells,1);
1686 arr2->fillWithZero();
1687 int *arr2Ptr=arr2->getPointer();
1688 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1689 for(int i=0;i<nbOfCommon;i++)
1691 int start=commonCellsPtr[commonCellsIPtr[i]];
1692 if(start<thisNbCells)
1694 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1696 int sig=commonCellsPtr[j]>0?1:-1;
1697 int val=std::abs(commonCellsPtr[j])-1;
1698 if(val>=thisNbCells)
1699 arr2Ptr[val-thisNbCells]=sig*(start+1);
1703 arr2->setName(other->getName());
1704 if(arr2->presenceOfValue(0))
1711 * @param areNodesMerged if at least two nodes have been merged.
1712 * @return old to new node correspondance.
1714 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1716 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1718 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1723 * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
1725 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1727 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1729 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1734 * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
1735 * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
1736 * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
1737 * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
1739 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
1741 const DataArrayDouble *coords=other.getCoords();
1743 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
1745 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1746 int otherNbOfNodes=other.getNumberOfNodes();
1747 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1749 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1750 setCoords(newCoords);
1751 bool areNodesMerged;
1753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1756 setCoords(oldCoords);
1757 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1759 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1760 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1761 if(pt!=da->getConstPointer()+da->getNbOfElems())
1763 setCoords(oldCoords);
1764 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1766 setCoords(oldCoords);
1767 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1772 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1773 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1774 * cellIds is not given explicitely but by a range python like.
1776 * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1777 * \return a newly allocated
1779 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1780 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1782 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1784 if(getMeshDimension()!=-1)
1786 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
1793 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1795 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1797 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1799 return const_cast<MEDCouplingUMesh *>(this);
1804 * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
1805 * @param begin begin of array containing the cell ids to keep.
1806 * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
1807 * @param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1809 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1810 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1812 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1814 if(getMeshDimension()!=-1)
1816 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
1824 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1826 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1828 return const_cast<MEDCouplingUMesh *>(this);
1833 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1835 * This method allows to partially modify some cells in \b this (whose list is specified by [\b cellIdsBg, \b cellIdsEnd) ) with cells coming in \b otherOnSameCoordsThanThis.
1836 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1837 * The number of cells of \b this will remain the same with this method.
1839 * \param [in] begin begin of cell ids (included) of cells in this to assign
1840 * \param [in] end end of cell ids (excluded) of cells in this to assign
1841 * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd).
1842 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1844 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1846 checkConnectivityFullyDefined();
1847 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1848 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1850 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1852 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1853 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1854 throw INTERP_KERNEL::Exception(oss.str().c_str());
1856 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1857 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1859 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1860 throw INTERP_KERNEL::Exception(oss.str().c_str());
1862 int nbOfCells=getNumberOfCells();
1863 bool easyAssign=true;
1864 const int *connI=_nodal_connec_index->getConstPointer();
1865 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1866 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1868 if(*it>=0 && *it<nbOfCells)
1870 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1874 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1875 throw INTERP_KERNEL::Exception(oss.str().c_str());
1880 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1885 DataArrayInt *arrOut=0,*arrIOut=0;
1886 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1889 setConnectivity(arrOut,arrIOut,true);
1893 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1895 checkConnectivityFullyDefined();
1896 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1897 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1898 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1899 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1901 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1902 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1903 throw INTERP_KERNEL::Exception(oss.str().c_str());
1905 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1906 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1908 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1909 throw INTERP_KERNEL::Exception(oss.str().c_str());
1911 int nbOfCells=getNumberOfCells();
1912 bool easyAssign=true;
1913 const int *connI=_nodal_connec_index->getConstPointer();
1914 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1916 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1918 if(it>=0 && it<nbOfCells)
1920 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1924 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1925 throw INTERP_KERNEL::Exception(oss.str().c_str());
1930 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1935 DataArrayInt *arrOut=0,*arrIOut=0;
1936 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1939 setConnectivity(arrOut,arrIOut,true);
1943 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1945 DataArrayInt *cellIdsKept=0;
1946 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
1947 cellIdsKept->setName(getName());
1952 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1953 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
1954 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1955 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1957 * \param [in] begin input start of array of node ids.
1958 * \param [in] end input end of array of node ids.
1959 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
1960 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
1962 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
1964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
1965 checkConnectivityFullyDefined();
1967 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
1968 std::vector<bool> fastFinder(sz,false);
1969 for(const int *work=begin;work!=end;work++)
1970 if(*work>=0 && *work<sz)
1971 fastFinder[*work]=true;
1972 int nbOfCells=getNumberOfCells();
1973 const int *conn=getNodalConnectivity()->getConstPointer();
1974 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
1975 for(int i=0;i<nbOfCells;i++)
1977 int ref=0,nbOfHit=0;
1978 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
1982 if(fastFinder[*work2])
1985 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
1986 cellIdsKept->pushBackSilent(i);
1988 cellIdsKeptArr=cellIdsKept.retn();
1992 * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
1994 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1996 DataArrayInt *cellIdsKept=0;
1997 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1998 cellIdsKept->setName(getName());
2003 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2004 * The return newly allocated mesh will share the same coordinates as 'this'.
2005 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2006 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2008 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2010 DataArrayInt *cellIdsKept=0;
2011 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2013 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2017 * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
2018 * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
2019 * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
2020 * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
2022 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2025 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2026 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2027 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2028 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2032 * This method returns a mesh with meshDim=this->getMeshDimension()-1.
2033 * This returned mesh contains cells that are linked with one and only one cell of this.
2034 * @param keepCoords specifies if ParaMEDMEM::MEDCouplingUMesh::zipCoords is called on returned mesh before being returned. If true zipCoords is \b NOT called, if false, zipCoords is called.
2035 * @return mesh with ref counter equal to 1.
2037 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2039 DataArrayInt *desc=DataArrayInt::New();
2040 DataArrayInt *descIndx=DataArrayInt::New();
2041 DataArrayInt *revDesc=DataArrayInt::New();
2042 DataArrayInt *revDescIndx=DataArrayInt::New();
2044 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2047 descIndx->decrRef();
2048 int nbOfCells=meshDM1->getNumberOfCells();
2049 const int *revDescIndxC=revDescIndx->getConstPointer();
2050 std::vector<int> boundaryCells;
2051 for(int i=0;i<nbOfCells;i++)
2052 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2053 boundaryCells.push_back(i);
2054 revDescIndx->decrRef();
2055 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2060 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2061 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2062 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2064 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2066 checkFullyDefined();
2067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2072 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2073 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2075 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2077 const int *revDescPtr=revDesc->getConstPointer();
2078 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2079 int nbOfCells=getNumberOfCells();
2080 std::vector<bool> ret1(nbOfCells,false);
2082 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2083 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2084 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2086 DataArrayInt *ret2=DataArrayInt::New();
2088 int *ret2Ptr=ret2->getPointer();
2090 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2093 ret2->setName("BoundaryCells");
2098 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2099 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2100 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2101 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2103 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2104 * This method method returns cells ids set s = s1 + s2 where :
2106 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2107 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2109 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2110 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2112 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2113 * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2114 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2116 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2118 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2119 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2120 checkConnectivityFullyDefined();
2121 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2122 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2123 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2126 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2128 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2129 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2130 DataArrayInt *idsOtherInConsti=0;
2131 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2136 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2137 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2139 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2140 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2141 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2143 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2144 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2145 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2146 neighThisPartAuto=0;
2147 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2148 const int li[2]={0,1};
2149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2150 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2151 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2154 cellIdsRk0=s0arr.retn();
2155 cellIdsRk1=s_renum1.retn();
2159 * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2160 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2162 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2164 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2167 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2171 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2172 revDesc=0; desc=0; descIndx=0;
2173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2175 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2179 * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2180 * The returned nodes ids are those lying on the boundary of \b this.
2182 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2184 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2185 return skin->computeFetchedNodeIds();
2188 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2191 return const_cast<MEDCouplingUMesh *>(this);
2195 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2196 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2197 * This value is asked because often known by the caller of this method.
2198 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2200 * @param newNodeNumbers array specifying the new numbering in old2New convention.
2201 * @param newNbOfNodes the new number of nodes.
2203 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2205 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2206 renumberNodesInConn(newNodeNumbers);
2210 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2211 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2212 * This value is asked because often known by the caller of this method.
2213 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2214 * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2216 * @param newNodeNumbers array specifying the new numbering.
2217 * @param newNbOfNodes the new number of nodes.
2220 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2222 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2223 renumberNodesInConn(newNodeNumbers);
2227 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2228 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2229 * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2230 * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2231 * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2233 * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2234 * parameter is altered during the call.
2235 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2236 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2237 * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2239 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2241 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2242 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2244 checkFullyDefined();
2245 otherDimM1OnSameCoords.checkFullyDefined();
2246 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2247 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2248 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2249 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2250 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2251 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2254 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2255 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2256 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2259 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2261 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2263 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2264 DataArrayInt *idsTmp=0;
2265 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2266 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2269 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2270 DataArrayInt *tmp0=0,*tmp1=0;
2271 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2276 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2277 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2279 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2280 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2281 nodeIdsToDuplicate=s3.retn();
2285 * This method operates a modification of the connectivity and coords in \b this.
2286 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2287 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2288 * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2289 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2290 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2292 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2294 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2295 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2297 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2299 int nbOfNodes=getNumberOfNodes();
2300 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2301 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2305 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2306 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2307 * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2308 * @param [in] newNodeNumbers in old2New convention
2310 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2312 checkConnectivityFullyDefined();
2313 int *conn=getNodalConnectivity()->getPointer();
2314 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2315 int nbOfCells=getNumberOfCells();
2316 for(int i=0;i<nbOfCells;i++)
2317 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2319 int& node=conn[iconn];
2320 if(node>=0)//avoid polyhedron separator
2322 node=newNodeNumbersO2N[node];
2325 _nodal_connec->declareAsNew();
2330 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2331 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2332 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2334 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2336 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2338 checkConnectivityFullyDefined();
2339 int *conn=getNodalConnectivity()->getPointer();
2340 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2341 int nbOfCells=getNumberOfCells();
2342 for(int i=0;i<nbOfCells;i++)
2343 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2345 int& node=conn[iconn];
2346 if(node>=0)//avoid polyhedron separator
2351 _nodal_connec->declareAsNew();
2356 * This method operates a modification of the connectivity in \b this.
2357 * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2358 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2359 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2360 * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2361 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2362 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2364 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2365 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2367 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2368 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2369 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2371 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2373 checkConnectivityFullyDefined();
2374 std::map<int,int> m;
2376 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2378 int *conn=getNodalConnectivity()->getPointer();
2379 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2380 int nbOfCells=getNumberOfCells();
2381 for(int i=0;i<nbOfCells;i++)
2382 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2384 int& node=conn[iconn];
2385 if(node>=0)//avoid polyhedron separator
2387 std::map<int,int>::iterator it=m.find(node);
2396 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2398 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2399 * After the call of this method the number of cells remains the same as before.
2401 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2402 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2403 * be strictly in [0;this->getNumberOfCells()).
2405 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2406 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2407 * should be contained in[0;this->getNumberOfCells()).
2409 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2411 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2413 checkConnectivityFullyDefined();
2414 int nbCells=getNumberOfCells();
2415 const int *array=old2NewBg;
2417 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2419 const int *conn=_nodal_connec->getConstPointer();
2420 const int *connI=_nodal_connec_index->getConstPointer();
2421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2422 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2423 newConn->copyStringInfoFrom(*_nodal_connec);
2424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2425 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2426 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2428 int *newC=newConn->getPointer();
2429 int *newCI=newConnI->getPointer();
2432 for(int i=0;i<nbCells;i++)
2434 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2435 int nbOfElts=connI[pos+1]-connI[pos];
2436 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2441 setConnectivity(newConn,newConnI);
2443 delete [] const_cast<int *>(array);
2447 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2448 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2449 * added in 'elems' parameter.
2451 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2454 if(getMeshDimension()==-1)
2456 elems->pushBackSilent(0);
2457 return elems.retn();
2459 int dim=getSpaceDimension();
2460 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2461 const int* conn = getNodalConnectivity()->getConstPointer();
2462 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2463 const double* coords = getCoords()->getConstPointer();
2464 int nbOfCells=getNumberOfCells();
2465 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2467 for (int i=0; i<dim; i++)
2469 elem_bb[i*2]=std::numeric_limits<double>::max();
2470 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2473 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2475 int node= conn[inode];
2476 if(node>=0)//avoid polyhedron separator
2478 for (int idim=0; idim<dim; idim++)
2480 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2482 elem_bb[idim*2] = coords[node*dim+idim] ;
2484 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2486 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2491 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2492 elems->pushBackSilent(ielem);
2494 return elems.retn();
2498 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2499 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2500 * added in 'elems' parameter.
2502 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2504 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2505 if(getMeshDimension()==-1)
2507 elems->pushBackSilent(0);
2508 return elems.retn();
2510 int dim=getSpaceDimension();
2511 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2512 const int* conn = getNodalConnectivity()->getConstPointer();
2513 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2514 const double* coords = getCoords()->getConstPointer();
2515 int nbOfCells=getNumberOfCells();
2516 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2518 for (int i=0; i<dim; i++)
2520 elem_bb[i*2]=std::numeric_limits<double>::max();
2521 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2524 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2526 int node= conn[inode];
2527 if(node>=0)//avoid polyhedron separator
2529 for (int idim=0; idim<dim; idim++)
2531 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2533 elem_bb[idim*2] = coords[node*dim+idim] ;
2535 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2537 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2542 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2543 elems->pushBackSilent(ielem);
2545 return elems.retn();
2549 * Returns the cell type of cell with id 'cellId'.
2551 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2553 const int *ptI=_nodal_connec_index->getConstPointer();
2554 const int *pt=_nodal_connec->getConstPointer();
2555 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2556 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2559 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2560 throw INTERP_KERNEL::Exception(oss.str().c_str());
2565 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2566 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2567 * The coordinates array is not considered here.
2569 * \param [in] type the geometric type
2570 * \return cell ids in this having geometric type \a type.
2572 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2577 checkConnectivityFullyDefined();
2578 int nbCells=getNumberOfCells();
2579 int mdim=getMeshDimension();
2580 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2581 if(mdim!=(int)cm.getDimension())
2582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2583 const int *ptI=_nodal_connec_index->getConstPointer();
2584 const int *pt=_nodal_connec->getConstPointer();
2585 for(int i=0;i<nbCells;i++)
2587 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2588 ret->pushBackSilent(i);
2594 * Returns nb of cells having the geometric type 'type'.
2596 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2598 const int *ptI=_nodal_connec_index->getConstPointer();
2599 const int *pt=_nodal_connec->getConstPointer();
2600 int nbOfCells=getNumberOfCells();
2602 for(int i=0;i<nbOfCells;i++)
2603 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2609 * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2610 * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2611 * That is to say -1 separator is omitted in returned conn.
2613 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2615 const int *ptI=_nodal_connec_index->getConstPointer();
2616 const int *pt=_nodal_connec->getConstPointer();
2617 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2622 std::string MEDCouplingUMesh::simpleRepr() const
2624 static const char msg0[]="No coordinates specified !";
2625 std::ostringstream ret;
2626 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2627 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2629 double tt=getTime(tmpp1,tmpp2);
2630 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2631 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2632 ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2635 const int spaceDim=getSpaceDimension();
2636 ret << spaceDim << "\nInfo attached on space dimension : ";
2637 for(int i=0;i<spaceDim;i++)
2638 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2642 ret << msg0 << "\n";
2643 ret << "Number of nodes : ";
2645 ret << getNumberOfNodes() << "\n";
2647 ret << msg0 << "\n";
2648 ret << "Number of cells : ";
2649 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2650 ret << getNumberOfCells() << "\n";
2652 ret << "No connectivity specified !" << "\n";
2653 ret << "Cell types present : ";
2654 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2656 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2657 ret << cm.getRepr() << " ";
2663 std::string MEDCouplingUMesh::advancedRepr() const
2665 std::ostringstream ret;
2666 ret << simpleRepr();
2667 ret << "\nCoordinates array : \n___________________\n\n";
2669 _coords->reprWithoutNameStream(ret);
2671 ret << "No array set !\n";
2672 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2673 reprConnectivityOfThisLL(ret);
2678 * This method returns a C++ code that is a dump of \a this.
2679 * This method will throw if this is not fully defined.
2681 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2683 static const char coordsName[]="coords";
2684 static const char connName[]="conn";
2685 static const char connIName[]="connI";
2686 checkFullyDefined();
2687 std::ostringstream ret; ret << "// coordinates" << std::endl;
2688 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2689 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2690 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2691 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2692 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2693 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2694 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2698 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2700 std::ostringstream ret;
2701 reprConnectivityOfThisLL(ret);
2706 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2707 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2708 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2711 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2712 * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
2713 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2715 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2717 int mdim=getMeshDimension();
2719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2720 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2722 bool needToCpyCT=true;
2725 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2733 if(!_nodal_connec_index)
2735 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2740 tmp2=_nodal_connec_index;
2743 ret->setConnectivity(tmp1,tmp2,false);
2748 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2749 ret->setCoords(coords);
2752 ret->setCoords(_coords);
2756 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2758 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2760 int nbOfCells=getNumberOfCells();
2761 const int *c=_nodal_connec->getConstPointer();
2762 const int *ci=_nodal_connec_index->getConstPointer();
2763 for(int i=0;i<nbOfCells;i++)
2765 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2766 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2767 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2772 stream << "Connectivity not defined !\n";
2775 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2777 const int *ptI=_nodal_connec_index->getConstPointer();
2778 const int *pt=_nodal_connec->getConstPointer();
2779 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2780 return ptI[cellId+1]-ptI[cellId]-1;
2782 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2786 * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2787 * This method avoids to compute explicitely submesh to get its types.
2789 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2791 checkFullyDefined();
2792 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2793 const int *conn=_nodal_connec->getConstPointer();
2794 const int *connIndex=_nodal_connec_index->getConstPointer();
2795 for(const int *w=begin;w!=end;w++)
2796 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2801 * Method reserved for advanced users having prepared their connectivity before.
2802 * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2804 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2806 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2807 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2808 if(isComputingTypes)
2814 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2815 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2817 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2818 _nodal_connec(0),_nodal_connec_index(0),
2819 _types(other._types)
2821 if(other._nodal_connec)
2822 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2823 if(other._nodal_connec_index)
2824 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2827 MEDCouplingUMesh::~MEDCouplingUMesh()
2830 _nodal_connec->decrRef();
2831 if(_nodal_connec_index)
2832 _nodal_connec_index->decrRef();
2836 * This method recomputes all cell types of 'this'.
2838 void MEDCouplingUMesh::computeTypes()
2840 if(_nodal_connec && _nodal_connec_index)
2843 const int *conn=_nodal_connec->getConstPointer();
2844 const int *connIndex=_nodal_connec_index->getConstPointer();
2845 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2847 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2848 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2853 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2855 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2857 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2858 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2862 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2864 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2866 if(!_nodal_connec_index || !_nodal_connec)
2867 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2870 int MEDCouplingUMesh::getNumberOfCells() const
2872 if(_nodal_connec_index)
2873 return _nodal_connec_index->getNumberOfTuples()-1;
2878 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2881 int MEDCouplingUMesh::getMeshDimension() const
2884 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2889 * This method is for test reason. Normally the integer returned is not useable by user.
2891 int MEDCouplingUMesh::getMeshLength() const
2893 return _nodal_connec->getNbOfElems();
2897 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2899 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2901 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2902 tinyInfo.push_back(getMeshDimension());
2903 tinyInfo.push_back(getNumberOfCells());
2905 tinyInfo.push_back(getMeshLength());
2907 tinyInfo.push_back(-1);
2911 * First step of unserialization process.
2913 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2915 return tinyInfo[6]<=0;
2919 * Second step of serialization process.
2920 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2922 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2924 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2926 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2930 * Third and final step of serialization process.
2932 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2934 MEDCouplingPointSet::serialize(a1,a2);
2935 if(getMeshDimension()>-1)
2937 a1=DataArrayInt::New();
2938 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2939 int *ptA1=a1->getPointer();
2940 const int *conn=getNodalConnectivity()->getConstPointer();
2941 const int *index=getNodalConnectivityIndex()->getConstPointer();
2942 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2943 std::copy(conn,conn+getMeshLength(),ptA1);
2950 * Second and final unserialization process.
2951 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2953 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2955 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2956 setMeshDimension(tinyInfo[5]);
2960 const int *recvBuffer=a1->getConstPointer();
2961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
2962 myConnecIndex->alloc(tinyInfo[6]+1,1);
2963 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2964 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
2965 myConnec->alloc(tinyInfo[7],1);
2966 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2967 setConnectivity(myConnec, myConnecIndex);
2972 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2973 * CellIds are given using range specified by a start an end and step.
2975 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2977 checkFullyDefined();
2978 int ncell=getNumberOfCells();
2979 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2980 ret->_mesh_dim=_mesh_dim;
2981 ret->setCoords(_coords);
2982 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2984 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2986 const int *conn=_nodal_connec->getConstPointer();
2987 const int *connIndex=_nodal_connec_index->getConstPointer();
2988 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2990 if(work>=0 && work<ncell)
2992 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2996 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2997 throw INTERP_KERNEL::Exception(oss.str().c_str());
3000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3001 int *newConnPtr=newConn->getPointer();
3002 std::set<INTERP_KERNEL::NormalizedCellType> types;
3004 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3006 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3007 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3009 ret->setConnectivity(newConn,newConnI,false);
3011 ret->copyTinyInfoFrom(this);
3016 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3017 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3018 * The return newly allocated mesh will share the same coordinates as 'this'.
3020 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3022 checkFullyDefined();
3023 int ncell=getNumberOfCells();
3024 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3025 ret->_mesh_dim=_mesh_dim;
3026 ret->setCoords(_coords);
3027 std::size_t nbOfElemsRet=std::distance(begin,end);
3028 int *connIndexRet=new int[nbOfElemsRet+1];
3030 const int *conn=_nodal_connec->getConstPointer();
3031 const int *connIndex=_nodal_connec_index->getConstPointer();
3033 for(const int *work=begin;work!=end;work++,newNbring++)
3035 if(*work>=0 && *work<ncell)
3036 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3039 delete [] connIndexRet;
3040 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3041 throw INTERP_KERNEL::Exception(oss.str().c_str());
3044 int *connRet=new int[connIndexRet[nbOfElemsRet]];
3045 int *connRetWork=connRet;
3046 std::set<INTERP_KERNEL::NormalizedCellType> types;
3047 for(const int *work=begin;work!=end;work++)
3049 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3050 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3053 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3055 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3056 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3058 ret->copyTinyInfoFrom(this);
3063 * brief returns the volumes of the cells underlying the field \a field
3065 * For 2D geometries, the returned field contains the areas.
3066 * For 3D geometries, the returned field contains the volumes.
3068 * param field field on which cells the volumes are required
3069 * return field containing the volumes, area or length depending the meshdimension.
3071 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3073 std::string name="MeasureOfMesh_";
3075 int nbelem=getNumberOfCells();
3076 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3077 field->setName(name.c_str());
3078 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3079 array->alloc(nbelem,1);
3080 double *area_vol=array->getPointer();
3081 field->setArray(array) ; array=0;
3082 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3083 field->synchronizeTimeWithMesh();
3084 if(getMeshDimension()!=-1)
3087 INTERP_KERNEL::NormalizedCellType type;
3088 int dim_space=getSpaceDimension();
3089 const double *coords=getCoords()->getConstPointer();
3090 const int *connec=getNodalConnectivity()->getConstPointer();
3091 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3092 for(int iel=0;iel<nbelem;iel++)
3094 ipt=connec_index[iel];
3095 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3096 area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3099 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3103 area_vol[0]=std::numeric_limits<double>::max();
3105 return field.retn();
3109 * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3110 * This method avoids to build explicitely part of this to perform the work.
3112 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3114 std::string name="PartMeasureOfMesh_";
3116 int nbelem=(int)std::distance(begin,end);
3117 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3118 array->setName(name.c_str());
3119 array->alloc(nbelem,1);
3120 double *area_vol=array->getPointer();
3121 if(getMeshDimension()!=-1)
3124 INTERP_KERNEL::NormalizedCellType type;
3125 int dim_space=getSpaceDimension();
3126 const double *coords=getCoords()->getConstPointer();
3127 const int *connec=getNodalConnectivity()->getConstPointer();
3128 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3129 for(const int *iel=begin;iel!=end;iel++)
3131 ipt=connec_index[*iel];
3132 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3133 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3136 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3140 area_vol[0]=std::numeric_limits<double>::max();
3142 return array.retn();
3146 * This methods returns a field on nodes and no time. This method is useful to check "P1*" conservative interpolators.
3147 * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3149 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3151 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3152 std::string name="MeasureOnNodeOfMesh_";
3154 int nbNodes=getNumberOfNodes();
3155 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3156 double cst=1./((double)getMeshDimension()+1.);
3157 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3158 array->alloc(nbNodes,1);
3159 double *valsToFill=array->getPointer();
3160 std::fill(valsToFill,valsToFill+nbNodes,0.);
3161 const double *values=tmp->getArray()->getConstPointer();
3162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3164 getReverseNodalConnectivity(da,daInd);
3165 const int *daPtr=da->getConstPointer();
3166 const int *daIPtr=daInd->getConstPointer();
3167 for(int i=0;i<nbNodes;i++)
3168 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3169 valsToFill[i]+=cst*values[*cell];
3171 ret->setArray(array);
3176 * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3177 * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3179 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3181 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3182 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3183 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3184 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3185 int nbOfCells=getNumberOfCells();
3186 int nbComp=getMeshDimension()+1;
3187 array->alloc(nbOfCells,nbComp);
3188 double *vals=array->getPointer();
3189 const int *connI=_nodal_connec_index->getConstPointer();
3190 const int *conn=_nodal_connec->getConstPointer();
3191 const double *coords=_coords->getConstPointer();
3192 if(getMeshDimension()==2)
3194 if(getSpaceDimension()==3)
3196 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3197 const double *locPtr=loc->getConstPointer();
3198 for(int i=0;i<nbOfCells;i++,vals+=3)
3200 int offset=connI[i];
3201 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3202 double n=INTERP_KERNEL::norm<3>(vals);
3203 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3208 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3209 const double *isAbsPtr=isAbs->getArray()->begin();
3210 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3211 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3214 else//meshdimension==1
3217 for(int i=0;i<nbOfCells;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);
3229 ret->synchronizeTimeWithSupport();
3234 * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3235 * This method avoids to build explicitely part of this to perform the work.
3237 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3239 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3240 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3241 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3243 std::size_t nbelems=std::distance(begin,end);
3244 int nbComp=getMeshDimension()+1;
3245 array->alloc((int)nbelems,nbComp);
3246 double *vals=array->getPointer();
3247 const int *connI=_nodal_connec_index->getConstPointer();
3248 const int *conn=_nodal_connec->getConstPointer();
3249 const double *coords=_coords->getConstPointer();
3250 if(getMeshDimension()==2)
3252 if(getSpaceDimension()==3)
3254 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3255 const double *locPtr=loc->getConstPointer();
3256 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3258 int offset=connI[*i];
3259 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3260 double n=INTERP_KERNEL::norm<3>(vals);
3261 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3266 for(std::size_t i=0;i<nbelems;i++)
3267 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3270 else//meshdimension==1
3273 for(const int *i=begin;i!=end;i++)
3275 int offset=connI[*i];
3276 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3277 double n=INTERP_KERNEL::norm<2>(tmp);
3278 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3283 ret->setArray(array);
3285 ret->synchronizeTimeWithSupport();
3290 * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3291 * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3293 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3295 if(getMeshDimension()!=1)
3296 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3297 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3298 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3299 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3300 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3301 int nbOfCells=getNumberOfCells();
3302 int spaceDim=getSpaceDimension();
3303 array->alloc(nbOfCells,spaceDim);
3304 double *pt=array->getPointer();
3305 const double *coo=getCoords()->getConstPointer();
3306 std::vector<int> conn;
3308 for(int i=0;i<nbOfCells;i++)
3311 getNodeIdsOfCell(i,conn);
3312 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3314 ret->setArray(array);
3316 ret->synchronizeTimeWithSupport();
3321 * 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.
3322 * This method returns 2 objects :
3323 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3324 * - 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
3325 * mesh the 3D cell id is 'this' it comes from.
3326 * This method works only for linear meshes (non quadratic).
3327 * 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
3328 * face. Only 'cellIds' parameter can distinguish the 2.
3329 * @param origin is the origin of the plane. It should be an array of length 3.
3330 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3331 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3332 * 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).
3334 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3336 checkFullyDefined();
3337 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3338 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3340 if(candidates->empty())
3341 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3342 std::vector<int> nodes;
3343 DataArrayInt *cellIds1D=0;
3344 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3345 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3350 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3351 revDesc2=0; revDescIndx2=0;
3352 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3353 revDesc1=0; revDescIndx1=0;
3354 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3357 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3358 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3360 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3361 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3362 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3363 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3364 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3366 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3367 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3368 if(cellIds2->empty())
3369 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3370 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3371 ret->setCoords(mDesc1->getCoords());
3372 ret->setConnectivity(conn,connI,true);
3373 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3378 * 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.
3379 * This method returns 2 objects :
3380 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3381 * - 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
3382 * mesh the 3DSurf cell id is 'this' it comes from.
3383 * This method works only for linear meshes (non quadratic).
3384 * 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
3385 * face. Only 'cellIds' parameter can distinguish the 2.
3386 * @param origin is the origin of the plane. It should be an array of length 3.
3387 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3388 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3389 * 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).
3391 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3393 checkFullyDefined();
3394 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3397 if(candidates->empty())
3398 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3399 std::vector<int> nodes;
3400 DataArrayInt *cellIds1D=0;
3401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3402 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3407 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3408 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3409 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3411 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3412 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3414 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3415 int ncellsSub=subMesh->getNumberOfCells();
3416 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3417 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3418 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3419 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3422 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3423 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3424 for(int i=0;i<ncellsSub;i++)
3426 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3428 if(cut3DSurf[i].first!=-2)
3430 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3431 connI->pushBackSilent(conn->getNumberOfTuples());
3432 cellIds2->pushBackSilent(i);
3436 int cellId3DSurf=cut3DSurf[i].second;
3437 int offset=nodalI[cellId3DSurf]+1;
3438 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3439 for(int j=0;j<nbOfEdges;j++)
3441 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3442 connI->pushBackSilent(conn->getNumberOfTuples());
3443 cellIds2->pushBackSilent(cellId3DSurf);
3448 if(cellIds2->empty())
3449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3450 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3451 ret->setCoords(mDesc1->getCoords());
3452 ret->setConnectivity(conn,connI,true);
3453 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3458 * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3459 * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3460 * @param origin is the origin of the plane. It should be an array of length 3.
3461 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3463 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3465 checkFullyDefined();
3466 if(getSpaceDimension()!=3)
3467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3468 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3470 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3472 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3473 double angle=acos(vec[2]/normm);
3474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3478 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3479 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3480 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3482 mw->getBoundingBox(bbox);
3483 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3484 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3488 getBoundingBox(bbox);
3489 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3490 cellIds=getCellsInBoundingBox(bbox,eps);
3492 return cellIds.retn();
3496 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3497 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3498 * No consideration of coordinate is done by this method.
3499 * 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)
3500 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3502 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3504 if(getMeshDimension()!=1)
3505 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3506 int nbCells=getNumberOfCells();
3508 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3509 const int *connI=_nodal_connec_index->getConstPointer();
3510 const int *conn=_nodal_connec->getConstPointer();
3511 int ref=conn[connI[0]+2];
3512 for(int i=1;i<nbCells;i++)
3514 if(conn[connI[i]+1]!=ref)
3516 ref=conn[connI[i]+2];
3522 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3523 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3524 * @param pt reference point of the line
3525 * @param v normalized director vector of the line
3526 * @param eps max precision before throwing an exception
3527 * @param res output of size this->getNumberOfCells
3529 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3531 if(getMeshDimension()!=1)
3532 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3533 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3534 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3535 if(getSpaceDimension()!=3)
3536 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3537 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3538 const double *fPtr=f->getArray()->getConstPointer();
3540 for(int i=0;i<getNumberOfCells();i++)
3542 const double *tmp1=fPtr+3*i;
3543 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3544 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3545 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3546 double n1=INTERP_KERNEL::norm<3>(tmp);
3547 n1/=INTERP_KERNEL::norm<3>(tmp1);
3549 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3551 const double *coo=getCoords()->getConstPointer();
3552 for(int i=0;i<getNumberOfNodes();i++)
3554 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3555 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3556 res[i]=std::accumulate(tmp,tmp+3,0.);
3561 * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance.
3562 * \a this is expected to be a mesh so that its space dimension is equal to its
3563 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3564 * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3566 * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found
3567 * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked
3568 * to the node that minimizes distance with the input point then -1 is returned in cellId.
3570 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3571 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3573 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3574 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3575 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3576 * \return the positive value of the distance.
3577 * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
3579 * \sa DataArrayDouble::distanceToTuple
3581 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
3583 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3584 if(meshDim!=spaceDim-1)
3585 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3586 if(meshDim!=2 && meshDim!=1)
3587 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3588 checkFullyDefined();
3589 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3590 { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
3592 double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
3594 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
3595 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
3600 distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
3605 distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
3609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3617 * \param [in] pt the start pointer (included) of the coordinates of the point
3618 * \param [in] cellIds
3619 * \param [in,out] ret0 the min distance between \a this and the external input point
3620 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3621 * \sa MEDCouplingUMesh::distanceToPoint
3623 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3625 const double *coords=_coords->getConstPointer();
3627 if(cellIds->empty())
3629 const int *ptr=_nodal_connec->getConstPointer();
3630 const int *ptrI=_nodal_connec_index->getConstPointer();
3631 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3633 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3635 case INTERP_KERNEL::NORM_TRI3:
3637 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
3639 { ret0=tmp; cellId=*zeCell; }
3642 case INTERP_KERNEL::NORM_QUAD4:
3643 case INTERP_KERNEL::NORM_POLYGON:
3645 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
3647 { ret0=tmp; cellId=*zeCell; }
3651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3657 * \param [in] pt the start pointer (included) of the coordinates of the point
3658 * \param [in] cellIds
3659 * \param [in,out] ret0 the min distance between \a this and the external input point
3660 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3661 * \sa MEDCouplingUMesh::distanceToPoint
3663 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3665 const double *coords=_coords->getConstPointer();
3666 if(cellIds->empty())
3667 { cellId=-1; return; }
3668 const int *ptr=_nodal_connec->getConstPointer();
3669 const int *ptrI=_nodal_connec_index->getConstPointer();
3670 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3672 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3674 case INTERP_KERNEL::NORM_SEG2:
3676 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
3677 if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
3679 { ret0=tmp; cellId=*zeCell; }
3683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3689 * Returns a cell if any that contains the point located on 'pos' with precison eps.
3690 * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3691 * \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'
3692 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3694 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3696 std::vector<int> elts;
3697 getCellsContainingPoint(pos,eps,elts);
3700 return elts.front();
3704 * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3705 * \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'
3706 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3708 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3710 std::vector<int> eltsIndex;
3711 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3716 namespace ParaMEDMEM
3718 template<const int SPACEDIMM>
3722 static const int MY_SPACEDIM=SPACEDIMM;
3723 static const int MY_MESHDIM=8;
3724 typedef int MyConnType;
3725 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3727 // useless, but for windows compilation ...
3728 const double* getCoordinatesPtr() const { return 0; }
3729 const int* getConnectivityPtr() const { return 0; }
3730 const int* getConnectivityIndexPtr() const { return 0; }
3731 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3735 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3737 INTERP_KERNEL::Edge *ret=0;
3740 case INTERP_KERNEL::NORM_SEG2:
3742 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3745 case INTERP_KERNEL::NORM_SEG3:
3747 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3748 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3749 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3750 bool colinearity=inters.areColinears();
3751 delete e1; delete e2;
3753 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3755 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3756 mapp2[bg[2]].second=false;
3760 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3766 * 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'.
3767 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3768 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3770 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3773 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.
3774 const double *coo=mDesc->getCoords()->getConstPointer();
3775 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3776 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3778 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3779 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3780 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3782 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3783 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3785 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3786 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3788 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3789 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3791 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3793 if((*it2).second.second)
3794 mapp[(*it2).second.first]=(*it2).first;
3795 ((*it2).second.first)->decrRef();
3800 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3804 int locId=nodeId-offset2;
3805 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3809 int locId=nodeId-offset1;
3810 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3812 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3815 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3816 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3817 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3819 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3821 int eltId1=abs(*desc1)-1;
3822 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3824 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3825 if(it==mappRev.end())
3827 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3838 template<int SPACEDIM>
3839 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3840 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3842 std::vector<double> bbox;
3843 eltsIndex.resize(nbOfPoints+1);
3846 getBoundingBoxForBBTree(bbox);
3847 int nbOfCells=getNumberOfCells();
3848 const int *conn=_nodal_connec->getConstPointer();
3849 const int *connI=_nodal_connec_index->getConstPointer();
3850 double bb[2*SPACEDIM];
3851 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3852 for(int i=0;i<nbOfPoints;i++)
3854 eltsIndex[i+1]=eltsIndex[i];
3855 for(int j=0;j<SPACEDIM;j++)
3857 bb[2*j]=pos[SPACEDIM*i+j];
3858 bb[2*j+1]=pos[SPACEDIM*i+j];
3860 std::vector<int> candidates;
3861 myTree.getIntersectingElems(bb,candidates);
3862 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3864 int sz=connI[(*iter)+1]-connI[*iter]-1;
3865 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3866 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3867 coords,conn+connI[*iter]+1,sz,eps))
3870 elts.push_back(*iter);
3877 * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3878 * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3879 * in case of multi points searching.
3880 * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3881 * 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]).
3883 * \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...
3885 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3886 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3888 int spaceDim=getSpaceDimension();
3889 int mDim=getMeshDimension();
3894 const double *coords=_coords->getConstPointer();
3895 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3902 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3904 else if(spaceDim==2)
3908 const double *coords=_coords->getConstPointer();
3909 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3912 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3914 else if(spaceDim==1)
3918 const double *coords=_coords->getConstPointer();
3919 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3922 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3925 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3929 * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3930 * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3931 * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3932 * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3934 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3936 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3937 if(getMeshDimension()!=2)
3938 throw INTERP_KERNEL::Exception(msg);
3939 int spaceDim=getSpaceDimension();
3940 if(spaceDim!=2 && spaceDim!=3)
3941 throw INTERP_KERNEL::Exception(msg);
3942 const int *conn=_nodal_connec->getConstPointer();
3943 const int *connI=_nodal_connec_index->getConstPointer();
3944 int nbOfCells=getNumberOfCells();
3945 std::vector<double> cell2DinS2;
3946 for(int i=0;i<nbOfCells;i++)
3948 int offset=connI[i];
3949 int nbOfNodesForCell=connI[i+1]-offset-1;
3950 if(nbOfNodesForCell<=3)
3952 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3953 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3954 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3961 * This method is typically requested to unbutterfly 2D linear cells in \b this.
3963 * 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.
3964 * 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.
3966 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3967 * This convex envelop is computed using Jarvis march algorithm.
3968 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3969 * 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)
3970 * 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.
3972 * @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.
3974 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3976 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3977 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
3978 checkFullyDefined();
3979 const double *coords=getCoords()->getConstPointer();
3980 int nbOfCells=getNumberOfCells();
3981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3982 nodalConnecIndexOut->alloc(nbOfCells+1,1);
3983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
3984 int *workIndexOut=nodalConnecIndexOut->getPointer();
3986 const int *nodalConnecIn=_nodal_connec->getConstPointer();
3987 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3988 std::set<INTERP_KERNEL::NormalizedCellType> types;
3989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
3990 isChanged->alloc(0,1);
3991 for(int i=0;i<nbOfCells;i++,workIndexOut++)
3993 int pos=nodalConnecOut->getNumberOfTuples();
3994 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3995 isChanged->pushBackSilent(i);
3996 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
3997 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
3999 if(isChanged->empty())
4001 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4003 return isChanged.retn();
4007 * This method is \b NOT const because it can modify 'this'.
4008 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4009 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4010 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4011 * \b 1 for translation and rotation around point of 'mesh1D'.
4012 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
4014 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4016 checkFullyDefined();
4017 mesh1D->checkFullyDefined();
4018 if(!mesh1D->isContiguous1D())
4019 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4020 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4021 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4022 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4023 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4024 if(mesh1D->getMeshDimension()!=1)
4025 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4027 if(isPresenceOfQuadratic())
4029 if(mesh1D->isFullyQuadratic())
4032 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4035 int oldNbOfNodes=getNumberOfNodes();
4036 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4041 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4046 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4050 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4052 setCoords(newCoords);
4053 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4059 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4060 * If it is not the case an exception will be thrown.
4061 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4062 * intersection of plane defined by ('origin','vec').
4063 * This method has one in/out parameter : 'cut3DCurve'.
4064 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4065 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4066 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4067 * This method will throw an exception if 'this' contains a non linear segment.
4069 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4071 checkFullyDefined();
4072 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4073 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4074 int ncells=getNumberOfCells();
4075 int nnodes=getNumberOfNodes();
4076 double vec2[3],vec3[3],vec4[3];
4077 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4079 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4080 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4081 const int *conn=_nodal_connec->getConstPointer();
4082 const int *connI=_nodal_connec_index->getConstPointer();
4083 const double *coo=_coords->getConstPointer();
4084 std::vector<double> addCoo;
4085 for(int i=0;i<ncells;i++)
4087 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4089 if(cut3DCurve[i]==-2)
4091 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4092 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];
4093 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4094 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4095 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4097 const double *st2=coo+3*st;
4098 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4099 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]));
4100 if(pos>eps && pos<1-eps)
4102 int nNode=((int)addCoo.size())/3;
4103 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4104 addCoo.insert(addCoo.end(),vec4,vec4+3);
4105 cut3DCurve[i]=nnodes+nNode;
4111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4115 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4116 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4117 coo2->alloc(newNbOfNodes,3);
4118 double *tmp=coo2->getPointer();
4119 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4120 std::copy(addCoo.begin(),addCoo.end(),tmp);
4121 DataArrayDouble::SetArrayIn(coo2,_coords);
4126 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4127 * @param mesh1D is the input 1D mesh used for translation computation.
4128 * @return newCoords new coords filled by this method.
4130 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4132 int oldNbOfNodes=getNumberOfNodes();
4133 int nbOf1DCells=mesh1D->getNumberOfCells();
4134 int spaceDim=getSpaceDimension();
4135 DataArrayDouble *ret=DataArrayDouble::New();
4136 std::vector<bool> isQuads;
4137 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4138 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4139 double *retPtr=ret->getPointer();
4140 const double *coords=getCoords()->getConstPointer();
4141 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4143 std::vector<double> c;
4147 for(int i=0;i<nbOf1DCells;i++)
4150 mesh1D->getNodeIdsOfCell(i,v);
4152 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4153 mesh1D->getCoordinatesOfNode(v[0],c);
4154 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4155 for(int j=0;j<oldNbOfNodes;j++)
4156 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4160 mesh1D->getCoordinatesOfNode(v[1],c);
4161 mesh1D->getCoordinatesOfNode(v[0],c);
4162 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4163 for(int j=0;j<oldNbOfNodes;j++)
4164 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4167 ret->copyStringInfoFrom(*getCoords());
4172 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4173 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4174 * @return newCoords new coords filled by this method.
4176 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4178 if(mesh1D->getSpaceDimension()==2)
4179 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4180 if(mesh1D->getSpaceDimension()==3)
4181 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4182 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4186 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4187 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4188 * @return newCoords new coords filled by this method.
4190 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4193 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4194 int oldNbOfNodes=getNumberOfNodes();
4195 int nbOf1DCells=mesh1D->getNumberOfCells();
4197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4198 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4199 int nbOfLevsInVec=nbOf1DCells+1;
4200 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4201 double *retPtr=ret->getPointer();
4202 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4203 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4204 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4205 tmp->setCoords(tmp2);
4206 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4207 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4208 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4209 for(int i=1;i<nbOfLevsInVec;i++)
4211 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4212 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4213 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4214 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4215 tmp->translate(vec);
4216 double tmp3[2],radius,alpha,alpha0;
4217 const double *p0=i+1<nbOfLevsInVec?begin:third;
4218 const double *p1=i+1<nbOfLevsInVec?end:begin;
4219 const double *p2=i+1<nbOfLevsInVec?third:end;
4220 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4221 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]);
4222 double angle=acos(cosangle/(radius*radius));
4223 tmp->rotate(end,0,angle);
4224 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4230 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4231 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4232 * @return newCoords new coords filled by this method.
4234 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4237 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4238 int oldNbOfNodes=getNumberOfNodes();
4239 int nbOf1DCells=mesh1D->getNumberOfCells();
4241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4243 int nbOfLevsInVec=nbOf1DCells+1;
4244 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4245 double *retPtr=ret->getPointer();
4246 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4247 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4248 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4249 tmp->setCoords(tmp2);
4250 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4251 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4252 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4253 for(int i=1;i<nbOfLevsInVec;i++)
4255 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4256 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4257 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4258 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4259 tmp->translate(vec);
4260 double tmp3[2],radius,alpha,alpha0;
4261 const double *p0=i+1<nbOfLevsInVec?begin:third;
4262 const double *p1=i+1<nbOfLevsInVec?end:begin;
4263 const double *p2=i+1<nbOfLevsInVec?third:end;
4264 double vecPlane[3]={
4265 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4266 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4267 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4269 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4272 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4273 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4274 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4276 double c2=cos(asin(s2));
4278 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4279 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4280 {-vec2[1]*s2, vec2[0]*s2, c2}
4282 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]};
4283 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]};
4284 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]};
4285 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4286 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]);
4287 double angle=acos(cosangle/(radius*radius));
4288 tmp->rotate(end,vecPlane,angle);
4291 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4297 * This method is private because not easy to use for end user. This method is const contrary to
4298 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4299 * the coords sorted slice by slice.
4300 * @param isQuad specifies presence of quadratic cells.
4302 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4304 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4305 int nbOf2DCells=getNumberOfCells();
4306 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4307 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4308 const int *conn=_nodal_connec->getConstPointer();
4309 const int *connI=_nodal_connec_index->getConstPointer();
4310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4312 newConnI->alloc(nbOf3DCells+1,1);
4313 int *newConnIPtr=newConnI->getPointer();
4315 std::vector<int> newc;
4316 for(int j=0;j<nbOf2DCells;j++)
4318 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4319 *newConnIPtr++=(int)newc.size();
4321 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4322 int *newConnPtr=newConn->getPointer();
4323 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4324 newConnIPtr=newConnI->getPointer();
4325 for(int iz=0;iz<nbOf1DCells;iz++)
4328 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4329 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4331 int icell=(int)(iter-newc.begin());
4332 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4335 *newConnPtr=(*iter)+iz*deltaPerLev;
4340 *newConnPtr=(*iter);
4343 ret->setConnectivity(newConn,newConnI,true);
4344 ret->setCoords(getCoords());
4349 * This method returns if 'this' is constituted by only quadratic cells.
4351 bool MEDCouplingUMesh::isFullyQuadratic() const
4353 checkFullyDefined();
4355 int nbOfCells=getNumberOfCells();
4356 for(int i=0;i<nbOfCells && ret;i++)
4358 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4359 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4360 ret=cm.isQuadratic();
4366 * This method returns if there is at least one quadratic cell.
4368 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4370 checkFullyDefined();
4372 int nbOfCells=getNumberOfCells();
4373 for(int i=0;i<nbOfCells && !ret;i++)
4375 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4376 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4377 ret=cm.isQuadratic();
4383 * This method convert quadratic cells to linear cells if any was found.
4384 * If no such cells exists 'this' remains unchanged.
4386 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4388 checkFullyDefined();
4389 int nbOfCells=getNumberOfCells();
4391 for(int i=0;i<nbOfCells;i++)
4393 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4394 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4395 if(cm.isQuadratic())
4397 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4398 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4399 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4406 newConn->alloc(getMeshLength()-delta,1);
4407 newConnI->alloc(nbOfCells+1,1);
4408 const int *icptr=_nodal_connec->getConstPointer();
4409 const int *iciptr=_nodal_connec_index->getConstPointer();
4410 int *ocptr=newConn->getPointer();
4411 int *ociptr=newConnI->getPointer();
4414 for(int i=0;i<nbOfCells;i++,ociptr++)
4416 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4417 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4418 if(!cm.isQuadratic())
4420 _types.insert(type);
4421 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4422 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4426 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4427 _types.insert(typel);
4428 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4429 int newNbOfNodes=cml.getNumberOfNodes();
4430 *ocptr++=(int)typel;
4431 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4432 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4435 setConnectivity(newConn,newConnI,false);
4439 * This method converts all linear cell in \a this to quadratic one.
4440 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4441 * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
4442 * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
4443 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4444 * end of the existing coordinates.
4446 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4447 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4448 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4450 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4452 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4454 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4456 DataArrayInt *conn=0,*connI=0;
4457 DataArrayDouble *coords=0;
4458 std::set<INTERP_KERNEL::NormalizedCellType> types;
4459 checkFullyDefined();
4460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4461 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4462 int meshDim=getMeshDimension();
4463 switch(conversionType)
4469 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4470 connSafe=conn; connISafe=connI; coordsSafe=coords;
4473 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4474 connSafe=conn; connISafe=connI; coordsSafe=coords;
4477 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4478 connSafe=conn; connISafe=connI; coordsSafe=coords;
4481 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4489 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4490 connSafe=conn; connISafe=connI; coordsSafe=coords;
4493 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4494 connSafe=conn; connISafe=connI; coordsSafe=coords;
4497 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4498 connSafe=conn; connISafe=connI; coordsSafe=coords;
4501 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4506 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4508 setConnectivity(connSafe,connISafe,false);
4510 setCoords(coordsSafe);
4515 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4516 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4517 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4519 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4521 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4522 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4524 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4525 int nbOfCells=getNumberOfCells();
4526 int nbOfNodes=getNumberOfNodes();
4527 const int *cPtr=_nodal_connec->getConstPointer();
4528 const int *icPtr=_nodal_connec_index->getConstPointer();
4529 int lastVal=0,offset=nbOfNodes;
4530 for(int i=0;i<nbOfCells;i++,icPtr++)
4532 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4533 if(type==INTERP_KERNEL::NORM_SEG2)
4535 types.insert(INTERP_KERNEL::NORM_SEG3);
4536 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4537 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4538 newConn->pushBackSilent(offset++);
4540 newConnI->pushBackSilent(lastVal);
4541 ret->pushBackSilent(i);
4546 lastVal+=(icPtr[1]-icPtr[0]);
4547 newConnI->pushBackSilent(lastVal);
4548 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4551 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4552 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4556 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4562 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4563 DataArrayInt *conn1D=0,*conn1DI=0;
4564 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4565 DataArrayDouble *coordsTmp=0;
4566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4567 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4568 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4569 const int *c1DPtr=conn1D->begin();
4570 const int *c1DIPtr=conn1DI->begin();
4571 int nbOfCells=getNumberOfCells();
4572 const int *cPtr=_nodal_connec->getConstPointer();
4573 const int *icPtr=_nodal_connec_index->getConstPointer();
4575 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4577 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4578 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4579 if(!cm.isQuadratic())
4581 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4582 types.insert(typ2); newConn->pushBackSilent(typ2);
4583 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4584 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4585 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4586 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4587 newConnI->pushBackSilent(lastVal);
4588 ret->pushBackSilent(i);
4593 lastVal+=(icPtr[1]-icPtr[0]);
4594 newConnI->pushBackSilent(lastVal);
4595 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4598 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4603 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4604 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4605 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4607 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4611 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4612 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4615 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4618 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4620 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4621 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4622 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4624 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4625 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4626 DataArrayInt *conn1D=0,*conn1DI=0;
4627 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4628 DataArrayDouble *coordsTmp=0;
4629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4630 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4632 const int *c1DPtr=conn1D->begin();
4633 const int *c1DIPtr=conn1DI->begin();
4634 int nbOfCells=getNumberOfCells();
4635 const int *cPtr=_nodal_connec->getConstPointer();
4636 const int *icPtr=_nodal_connec_index->getConstPointer();
4637 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4638 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4640 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4641 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4642 if(!cm.isQuadratic())
4644 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4645 types.insert(typ2); newConn->pushBackSilent(typ2);
4646 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4647 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4648 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4649 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4650 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4651 newConnI->pushBackSilent(lastVal);
4652 ret->pushBackSilent(i);
4657 lastVal+=(icPtr[1]-icPtr[0]);
4658 newConnI->pushBackSilent(lastVal);
4659 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4662 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4663 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4668 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4669 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4670 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4672 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4675 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4676 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4679 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4682 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
4683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
4684 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
4686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
4690 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4691 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
4692 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
4693 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
4694 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
4695 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
4696 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4697 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4698 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
4699 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
4700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
4701 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
4702 int nbOfCells=getNumberOfCells();
4703 const int *cPtr=_nodal_connec->getConstPointer();
4704 const int *icPtr=_nodal_connec_index->getConstPointer();
4705 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4706 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
4708 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4709 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4710 if(!cm.isQuadratic())
4712 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4713 if(typ2==INTERP_KERNEL::NORM_ERROR)
4715 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
4716 throw INTERP_KERNEL::Exception(oss.str().c_str());
4718 types.insert(typ2); newConn->pushBackSilent(typ2);
4719 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4720 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4721 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4722 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
4724 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
4725 int tmpPos=newConn->getNumberOfTuples();
4726 newConn->pushBackSilent(nodeId2);
4727 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
4729 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4730 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
4731 newConnI->pushBackSilent(lastVal);
4732 ret->pushBackSilent(i);
4737 lastVal+=(icPtr[1]-icPtr[0]);
4738 newConnI->pushBackSilent(lastVal);
4739 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
4743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
4744 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
4745 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4746 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
4747 int *c=newConn->getPointer();
4748 const int *cI(newConnI->begin());
4749 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
4750 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
4751 offset=coordsTmp2Safe->getNumberOfTuples();
4752 for(const int *elt=ret->begin();elt!=ret->end();elt++)
4753 c[cI[(*elt)+1]-1]+=offset;
4754 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
4759 * This method tessallates 'this' so that the number of cells remains the same.
4760 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4761 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4763 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4764 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4766 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4768 checkFullyDefined();
4769 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4770 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4771 double epsa=fabs(eps);
4772 if(epsa<std::numeric_limits<double>::min())
4773 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 !");
4774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4778 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4779 revDesc1=0; revDescIndx1=0;
4780 mDesc->tessellate2DCurve(eps);
4781 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4782 setCoords(mDesc->getCoords());
4786 * This method tessallates 'this' so that the number of cells remains the same.
4787 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4788 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4790 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4791 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4793 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4795 checkFullyDefined();
4796 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4798 double epsa=fabs(eps);
4799 if(epsa<std::numeric_limits<double>::min())
4800 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 !");
4801 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4802 int nbCells=getNumberOfCells();
4803 int nbNodes=getNumberOfNodes();
4804 const int *conn=_nodal_connec->getConstPointer();
4805 const int *connI=_nodal_connec_index->getConstPointer();
4806 const double *coords=_coords->getConstPointer();
4807 std::vector<double> addCoo;
4808 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
4809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
4810 newConnI->alloc(nbCells+1,1);
4811 int *newConnIPtr=newConnI->getPointer();
4814 INTERP_KERNEL::Node *tmp2[3];
4815 std::set<INTERP_KERNEL::NormalizedCellType> types;
4816 for(int i=0;i<nbCells;i++,newConnIPtr++)
4818 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4819 if(cm.isQuadratic())
4820 {//assert(connI[i+1]-connI[i]-1==3)
4821 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4822 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4823 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4824 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4825 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4828 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4829 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4831 newConnIPtr[1]=(int)newConn.size();
4835 types.insert(INTERP_KERNEL::NORM_SEG2);
4836 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4837 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4838 newConnIPtr[1]=newConnIPtr[0]+3;
4843 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4844 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4845 newConnIPtr[1]=newConnIPtr[0]+3;
4848 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4851 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4853 newConnArr->alloc((int)newConn.size(),1);
4854 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4855 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4856 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4857 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4858 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4859 std::copy(addCoo.begin(),addCoo.end(),work);
4860 DataArrayDouble::SetArrayIn(newCoords,_coords);
4865 * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4866 * This cut into simplex is performed following the parameter \a policy. This method so typically increases the number of cells of \a this.
4867 * This method \b keeps the number of nodes \b unchanged. That's why the splitting policy in 3D INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4868 * This method returns new2old newly allocated array that specifies a each cell of \a this after the call what was its id it comes.
4870 * The semantic of \a policy parameter :
4871 * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4872 * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4873 * - PLANAR_FACE_5 only HEXA8. All HEXA8 are split into 5 TETRA4
4874 * - PLANAR_FACE_6 only HEXA8. All HEXA8 are split into 6 TETRA4
4876 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4881 return simplexizePol0();
4883 return simplexizePol1();
4884 case (int) INTERP_KERNEL::PLANAR_FACE_5:
4885 return simplexizePlanarFace5();
4886 case (int) INTERP_KERNEL::PLANAR_FACE_6:
4887 return simplexizePlanarFace6();
4889 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n - 0 or 1 (only available for meshdim=2) \n - PLANAR_FACE_5, PLANAR_FACE_6 (only for meshdim=3)");
4893 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4895 checkFullyDefined();
4896 if(getMeshDimension()<1)
4897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4898 int nbCells=getNumberOfCells();
4899 const int *conn=_nodal_connec->getConstPointer();
4900 const int *connI=_nodal_connec_index->getConstPointer();
4901 for(int i=0;i<nbCells;i++)
4903 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4911 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4913 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4915 checkConnectivityFullyDefined();
4916 if(getMeshDimension()!=2)
4917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4918 int nbOfCells=getNumberOfCells();
4919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4920 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4921 ret->alloc(nbOfCells+nbOfCutCells,1);
4922 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4923 int *retPt=ret->getPointer();
4924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4926 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4927 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4928 int *pt=newConn->getPointer();
4929 int *ptI=newConnI->getPointer();
4931 const int *oldc=_nodal_connec->getConstPointer();
4932 const int *ci=_nodal_connec_index->getConstPointer();
4933 for(int i=0;i<nbOfCells;i++,ci++)
4935 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4937 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4938 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4939 pt=std::copy(tmp,tmp+8,pt);
4948 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4949 ptI[1]=ptI[0]+ci[1]-ci[0];
4954 _nodal_connec->decrRef();
4955 _nodal_connec=newConn.retn();
4956 _nodal_connec_index->decrRef();
4957 _nodal_connec_index=newConnI.retn();
4964 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4966 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4968 checkConnectivityFullyDefined();
4969 if(getMeshDimension()!=2)
4970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4971 int nbOfCells=getNumberOfCells();
4972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4973 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4974 ret->alloc(nbOfCells+nbOfCutCells,1);
4975 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4976 int *retPt=ret->getPointer();
4977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4978 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4979 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4980 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4981 int *pt=newConn->getPointer();
4982 int *ptI=newConnI->getPointer();
4984 const int *oldc=_nodal_connec->getConstPointer();
4985 const int *ci=_nodal_connec_index->getConstPointer();
4986 for(int i=0;i<nbOfCells;i++,ci++)
4988 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4990 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4991 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4992 pt=std::copy(tmp,tmp+8,pt);
5001 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5002 ptI[1]=ptI[0]+ci[1]-ci[0];
5007 _nodal_connec->decrRef();
5008 _nodal_connec=newConn.retn();
5009 _nodal_connec_index->decrRef();
5010 _nodal_connec_index=newConnI.retn();
5017 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5019 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5021 checkConnectivityFullyDefined();
5022 if(getMeshDimension()!=3)
5023 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5024 int nbOfCells=getNumberOfCells();
5025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5026 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5027 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5028 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5029 int *retPt=ret->getPointer();
5030 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5032 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5033 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5034 int *pt=newConn->getPointer();
5035 int *ptI=newConnI->getPointer();
5037 const int *oldc=_nodal_connec->getConstPointer();
5038 const int *ci=_nodal_connec_index->getConstPointer();
5039 for(int i=0;i<nbOfCells;i++,ci++)
5041 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5043 for(int j=0;j<5;j++,pt+=5,ptI++)
5045 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5046 pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5053 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5054 ptI[1]=ptI[0]+ci[1]-ci[0];
5059 _nodal_connec->decrRef();
5060 _nodal_connec=newConn.retn();
5061 _nodal_connec_index->decrRef();
5062 _nodal_connec_index=newConnI.retn();
5069 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5071 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5073 checkConnectivityFullyDefined();
5074 if(getMeshDimension()!=3)
5075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5076 int nbOfCells=getNumberOfCells();
5077 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5078 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5079 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5080 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5081 int *retPt=ret->getPointer();
5082 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5084 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5085 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5086 int *pt=newConn->getPointer();
5087 int *ptI=newConnI->getPointer();
5089 const int *oldc=_nodal_connec->getConstPointer();
5090 const int *ci=_nodal_connec_index->getConstPointer();
5091 for(int i=0;i<nbOfCells;i++,ci++)
5093 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5095 for(int j=0;j<6;j++,pt+=5,ptI++)
5097 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5098 pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5105 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5106 ptI[1]=ptI[0]+ci[1]-ci[0];
5111 _nodal_connec->decrRef();
5112 _nodal_connec=newConn.retn();
5113 _nodal_connec_index->decrRef();
5114 _nodal_connec_index=newConnI.retn();
5121 * 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.
5122 * This method completly ignore coordinates.
5123 * @param nodeSubdived is the nodal connectivity of subdivision of edges
5124 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5125 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5126 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5128 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5130 checkFullyDefined();
5131 if(getMeshDimension()!=2)
5132 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5133 int nbOfCells=getNumberOfCells();
5134 int *connI=_nodal_connec_index->getPointer();
5136 for(int i=0;i<nbOfCells;i++,connI++)
5138 int offset=descIndex[i];
5139 int nbOfEdges=descIndex[i+1]-offset;
5141 bool ddirect=desc[offset+nbOfEdges-1]>0;
5142 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5143 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5144 for(int j=0;j<nbOfEdges;j++)
5146 bool direct=desc[offset+j]>0;
5147 int edgeId=std::abs(desc[offset+j])-1;
5148 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5150 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5151 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5152 int ref2=direct?id1:id2;
5155 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5156 newConnLgth+=nbOfSubNodes-1;
5161 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5162 throw INTERP_KERNEL::Exception(oss.str().c_str());
5167 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5170 newConnLgth++;//+1 is for cell type
5171 connI[1]=newConnLgth;
5174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5175 newConn->alloc(newConnLgth,1);
5176 int *work=newConn->getPointer();
5177 for(int i=0;i<nbOfCells;i++)
5179 *work++=INTERP_KERNEL::NORM_POLYGON;
5180 int offset=descIndex[i];
5181 int nbOfEdges=descIndex[i+1]-offset;
5182 for(int j=0;j<nbOfEdges;j++)
5184 bool direct=desc[offset+j]>0;
5185 int edgeId=std::abs(desc[offset+j])-1;
5187 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5190 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5191 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5192 work=std::copy(it,it+nbOfSubNodes-1,work);
5196 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5199 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5203 * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
5204 * nodal connectivity will be transform to a NORM_TRI3 cell.
5205 * This method works \b only \b on \b linear cells.
5206 * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
5207 * method could be useful before calling this method in case of presence of several pair of nodes located on same position.
5208 * This method throws an exception if 'this' is not fully defined (connectivity).
5209 * 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.
5211 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5213 checkFullyDefined();
5214 if(getMeshDimension()<=1)
5215 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5216 int nbOfCells=getNumberOfCells();
5219 int initMeshLgth=getMeshLength();
5220 int *conn=_nodal_connec->getPointer();
5221 int *index=_nodal_connec_index->getPointer();
5225 for(int i=0;i<nbOfCells;i++)
5227 lgthOfCurCell=index[i+1]-posOfCurCell;
5228 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5230 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5231 conn+newPos+1,newLgth);
5232 conn[newPos]=newType;
5234 posOfCurCell=index[i+1];
5237 if(newPos!=initMeshLgth)
5238 _nodal_connec->reAlloc(newPos);
5243 * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5244 * The 'vec' vector has to have a non nul norm.
5245 * If not 'cells' parameter will be appended with cellIds of incorrect cells.
5246 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5248 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5250 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5251 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5252 int nbOfCells=getNumberOfCells();
5253 const int *conn=_nodal_connec->getConstPointer();
5254 const int *connI=_nodal_connec_index->getConstPointer();
5255 const double *coordsPtr=_coords->getConstPointer();
5256 for(int i=0;i<nbOfCells;i++)
5258 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5259 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5261 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5262 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5269 * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5270 * The 'vec' vector has to have a non nul norm.
5271 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5273 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5275 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5276 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5277 int nbOfCells=getNumberOfCells();
5278 int *conn=_nodal_connec->getPointer();
5279 const int *connI=_nodal_connec_index->getConstPointer();
5280 const double *coordsPtr=_coords->getConstPointer();
5281 bool isModified=false;
5282 for(int i=0;i<nbOfCells;i++)
5284 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5285 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5287 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5288 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5291 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5292 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5293 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5298 _nodal_connec->declareAsNew();
5303 * This method checks that all polyhedrons cells have correctly oriented faces.
5304 * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
5305 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
5307 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5309 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5310 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5311 int nbOfCells=getNumberOfCells();
5312 const int *conn=_nodal_connec->getConstPointer();
5313 const int *connI=_nodal_connec_index->getConstPointer();
5314 const double *coordsPtr=_coords->getConstPointer();
5315 for(int i=0;i<nbOfCells;i++)
5317 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5318 if(type==INTERP_KERNEL::NORM_POLYHED)
5320 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5327 * This method tries to orient correctly polhedrons cells.
5329 * \throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
5330 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5332 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5334 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5335 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5336 int nbOfCells=getNumberOfCells();
5337 int *conn=_nodal_connec->getPointer();
5338 const int *connI=_nodal_connec_index->getConstPointer();
5339 const double *coordsPtr=_coords->getConstPointer();
5340 for(int i=0;i<nbOfCells;i++)
5342 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5343 if(type==INTERP_KERNEL::NORM_POLYHED)
5347 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5348 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5350 catch(INTERP_KERNEL::Exception& e)
5352 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5353 throw INTERP_KERNEL::Exception(oss.str().c_str());
5361 * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
5362 * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
5363 * 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).
5364 * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
5366 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5367 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5369 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5371 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5372 if(getMeshDimension()!=3)
5373 throw INTERP_KERNEL::Exception(msg);
5374 int spaceDim=getSpaceDimension();
5376 throw INTERP_KERNEL::Exception(msg);
5378 int nbOfCells=getNumberOfCells();
5379 int *conn=_nodal_connec->getPointer();
5380 const int *connI=_nodal_connec_index->getConstPointer();
5381 const double *coo=getCoords()->getConstPointer();
5382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5383 for(int i=0;i<nbOfCells;i++)
5385 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5386 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5388 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5390 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5391 cells->pushBackSilent(i);
5395 return cells.retn();
5399 * This method is a faster method to correct orientation of all 3D cells in \a this.
5400 * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
5401 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5403 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5404 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5406 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5408 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5409 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5410 int nbOfCells=getNumberOfCells();
5411 int *conn=_nodal_connec->getPointer();
5412 const int *connI=_nodal_connec_index->getConstPointer();
5413 const double *coordsPtr=_coords->getConstPointer();
5414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5415 for(int i=0;i<nbOfCells;i++)
5417 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5420 case INTERP_KERNEL::NORM_TETRA4:
5422 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5424 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5425 ret->pushBackSilent(i);
5429 case INTERP_KERNEL::NORM_PYRA5:
5431 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5433 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5434 ret->pushBackSilent(i);
5438 case INTERP_KERNEL::NORM_PENTA6:
5439 case INTERP_KERNEL::NORM_HEXA8:
5440 case INTERP_KERNEL::NORM_HEXGP12:
5442 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5444 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5445 ret->pushBackSilent(i);
5449 case INTERP_KERNEL::NORM_POLYHED:
5451 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5453 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5454 ret->pushBackSilent(i);
5459 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
5467 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5468 * If it is not the case an exception will be thrown.
5469 * This method is fast because the first cell of 'this' is used to compute the plane.
5470 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5471 * @param pos output of size at least 3 used to store a point owned of searched plane.
5473 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5475 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5476 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5477 const int *conn=_nodal_connec->getConstPointer();
5478 const int *connI=_nodal_connec_index->getConstPointer();
5479 const double *coordsPtr=_coords->getConstPointer();
5480 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5481 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5485 * The returned newly created field has to be managed by the caller.
5486 * 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.
5487 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5488 * If a cell has an another type an exception will be thrown.
5490 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5493 int spaceDim=getSpaceDimension();
5494 int meshDim=getMeshDimension();
5495 if(spaceDim!=2 && spaceDim!=3)
5496 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5497 if(meshDim!=2 && meshDim!=3)
5498 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5501 int nbOfCells=getNumberOfCells();
5502 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5503 arr->alloc(nbOfCells,1);
5504 double *pt=arr->getPointer();
5505 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5506 const int *conn=_nodal_connec->getConstPointer();
5507 const int *connI=_nodal_connec_index->getConstPointer();
5508 const double *coo=_coords->getConstPointer();
5510 for(int i=0;i<nbOfCells;i++,pt++)
5512 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5515 case INTERP_KERNEL::NORM_TRI3:
5517 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5518 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5521 case INTERP_KERNEL::NORM_QUAD4:
5523 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5524 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5527 case INTERP_KERNEL::NORM_TETRA4:
5529 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5530 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5534 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5536 conn+=connI[i+1]-connI[i];
5538 ret->setName("EdgeRatio");
5539 ret->synchronizeTimeWithSupport();
5544 * The returned newly created field has to be managed by the caller.
5545 * 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.
5546 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5547 * If a cell has an another type an exception will be thrown.
5549 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5552 int spaceDim=getSpaceDimension();
5553 int meshDim=getMeshDimension();
5554 if(spaceDim!=2 && spaceDim!=3)
5555 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5556 if(meshDim!=2 && meshDim!=3)
5557 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5558 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5560 int nbOfCells=getNumberOfCells();
5561 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5562 arr->alloc(nbOfCells,1);
5563 double *pt=arr->getPointer();
5564 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5565 const int *conn=_nodal_connec->getConstPointer();
5566 const int *connI=_nodal_connec_index->getConstPointer();
5567 const double *coo=_coords->getConstPointer();
5569 for(int i=0;i<nbOfCells;i++,pt++)
5571 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5574 case INTERP_KERNEL::NORM_TRI3:
5576 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5577 *pt=INTERP_KERNEL::triAspectRatio(tmp);
5580 case INTERP_KERNEL::NORM_QUAD4:
5582 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5583 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5586 case INTERP_KERNEL::NORM_TETRA4:
5588 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5589 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5595 conn+=connI[i+1]-connI[i];
5597 ret->setName("AspectRatio");
5598 ret->synchronizeTimeWithSupport();
5603 * The returned newly created field has to be managed by the caller.
5604 * 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.
5605 * This method for the moment only deals with NORM_QUAD4 geometric type.
5606 * If a cell has an another type an exception will be thrown.
5608 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
5611 int spaceDim=getSpaceDimension();
5612 int meshDim=getMeshDimension();
5614 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5616 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5617 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5619 int nbOfCells=getNumberOfCells();
5620 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5621 arr->alloc(nbOfCells,1);
5622 double *pt=arr->getPointer();
5623 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5624 const int *conn=_nodal_connec->getConstPointer();
5625 const int *connI=_nodal_connec_index->getConstPointer();
5626 const double *coo=_coords->getConstPointer();
5628 for(int i=0;i<nbOfCells;i++,pt++)
5630 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5633 case INTERP_KERNEL::NORM_QUAD4:
5635 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5636 *pt=INTERP_KERNEL::quadWarp(tmp);
5640 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5642 conn+=connI[i+1]-connI[i];
5644 ret->setName("Warp");
5645 ret->synchronizeTimeWithSupport();
5650 * The returned newly created field has to be managed by the caller.
5651 * 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.
5652 * This method for the moment only deals with NORM_QUAD4 geometric type.
5653 * If a cell has an another type an exception will be thrown.
5655 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5658 int spaceDim=getSpaceDimension();
5659 int meshDim=getMeshDimension();
5661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5663 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5664 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5666 int nbOfCells=getNumberOfCells();
5667 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5668 arr->alloc(nbOfCells,1);
5669 double *pt=arr->getPointer();
5670 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5671 const int *conn=_nodal_connec->getConstPointer();
5672 const int *connI=_nodal_connec_index->getConstPointer();
5673 const double *coo=_coords->getConstPointer();
5675 for(int i=0;i<nbOfCells;i++,pt++)
5677 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5680 case INTERP_KERNEL::NORM_QUAD4:
5682 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5683 *pt=INTERP_KERNEL::quadSkew(tmp);
5687 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5689 conn+=connI[i+1]-connI[i];
5691 ret->setName("Skew");
5692 ret->synchronizeTimeWithSupport();
5697 * This method aggregate the bbox of each cell and put it into bbox parameter.
5698 * @param bbox out parameter of size 2*spacedim*nbOfcells.
5700 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5702 int spaceDim=getSpaceDimension();
5703 int nbOfCells=getNumberOfCells();
5704 bbox.resize(2*nbOfCells*spaceDim);
5705 for(int i=0;i<nbOfCells*spaceDim;i++)
5707 bbox[2*i]=std::numeric_limits<double>::max();
5708 bbox[2*i+1]=-std::numeric_limits<double>::max();
5710 const double *coordsPtr=_coords->getConstPointer();
5711 const int *conn=_nodal_connec->getConstPointer();
5712 const int *connI=_nodal_connec_index->getConstPointer();
5713 for(int i=0;i<nbOfCells;i++)
5715 int offset=connI[i]+1;
5716 int nbOfNodesForCell=connI[i+1]-offset;
5717 for(int j=0;j<nbOfNodesForCell;j++)
5719 int nodeId=conn[offset+j];
5721 for(int k=0;k<spaceDim;k++)
5723 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5724 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5732 namespace ParaMEDMEMImpl
5737 ConnReader(const int *c, int val):_conn(c),_val(val) { }
5738 bool operator() (const int& pos) { return _conn[pos]!=_val; }
5747 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5748 bool operator() (const int& pos) { return _conn[pos]==_val; }
5758 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5759 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5760 * 'this' is composed in cell types.
5761 * The returned array is of size 3*n where n is the number of different types present in 'this'.
5762 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
5763 * This parameter is kept only for compatibility with other methode listed above.
5765 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5767 checkConnectivityFullyDefined();
5768 const int *conn=_nodal_connec->getConstPointer();
5769 const int *connI=_nodal_connec_index->getConstPointer();
5770 const int *work=connI;
5771 int nbOfCells=getNumberOfCells();
5772 std::size_t n=getAllTypes().size();
5773 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5774 std::set<INTERP_KERNEL::NormalizedCellType> types;
5775 for(std::size_t i=0;work!=connI+nbOfCells;i++)
5777 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5778 if(types.find(typ)!=types.end())
5780 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5781 oss << " is not contiguous !";
5782 throw INTERP_KERNEL::Exception(oss.str().c_str());
5786 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5787 ret[3*i+1]=(int)std::distance(work,work2);
5794 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5795 * only for types cell, type node is not managed.
5796 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5797 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5798 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5799 * If 2 or more same geometric type is in 'code' and exception is thrown too.
5801 * This method firstly checks
5802 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5803 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5804 * an exception is thrown too.
5806 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5807 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
5808 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5810 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5813 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5814 std::size_t sz=code.size();
5817 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5818 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5820 for(std::size_t i=0;i<n;i++)
5821 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5823 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5825 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5830 if(idsPerType.empty())
5832 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5834 if(types.size()==_types.size())
5837 DataArrayInt *ret=DataArrayInt::New();
5839 int *retPtr=ret->getPointer();
5840 const int *connI=_nodal_connec_index->getConstPointer();
5841 const int *conn=_nodal_connec->getConstPointer();
5842 int nbOfCells=getNumberOfCells();
5845 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5847 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5848 int offset=(int)std::distance(connI,i);
5849 if(code[3*kk+2]==-1)
5851 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5852 std::size_t pos2=std::distance(i,j);
5853 for(std::size_t k=0;k<pos2;k++)
5854 *retPtr++=(int)k+offset;
5859 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5860 retPtr,std::bind2nd(std::plus<int>(),offset));
5867 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
5868 * This method is the opposite of MEDCouplingUMesh::checkTypeConsistencyAndContig method. Given a list of cells in \a profile it returns a list of sub-profiles sorted by geo type.
5869 * The result is put in the array \a idsPerType. In the returned parameter \a code, foreach i \a code[3*i+2] refers (if different from -1) to a location into the \a idsPerType.
5870 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
5872 * @param [out] code is a vector of size 3*n where n is the number of different geometric type in \a this \b reduced to the profile \a profile. \a code has exactly the same semantic than in MEDCouplingUMesh::checkTypeConsistencyAndContig method.
5873 * @param [out] idsInPflPerType is a vector of size of different geometric type in the subpart defined by \a profile of \a this ( equal to \a code.size()/3). For each i,
5874 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5875 * @param [out] idsPerType is a vector of size of different sub profiles needed to be defined to represent the profile \a profile for a given geometric type.
5876 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5877 * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
5879 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5881 if(profile->getNumberOfComponents()!=1)
5882 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5883 checkConnectivityFullyDefined();
5884 const int *conn=_nodal_connec->getConstPointer();
5885 const int *connI=_nodal_connec_index->getConstPointer();
5886 int nbOfCells=getNumberOfCells();
5887 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5888 std::vector<int> typeRangeVals(1);
5889 for(const int *i=connI;i!=connI+nbOfCells;)
5891 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5892 if(std::find(types.begin(),types.end(),curType)!=types.end())
5894 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5896 types.push_back(curType);
5897 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5898 typeRangeVals.push_back((int)std::distance(connI,i));
5901 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5902 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5907 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5908 code.resize(3*nbOfCastsFinal);
5909 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5910 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5911 for(int i=0;i<nbOfCastsFinal;i++)
5913 int castId=castsPresent->getIJ(i,0);
5914 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5915 idsInPflPerType2.push_back(tmp3);
5916 code[3*i]=(int)types[castId];
5917 code[3*i+1]=tmp3->getNumberOfTuples();
5918 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5919 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5921 tmp4->copyStringInfoFrom(*profile);
5922 idsPerType2.push_back(tmp4);
5923 code[3*i+2]=(int)idsPerType2.size()-1;
5930 std::size_t sz2=idsInPflPerType2.size();
5931 idsInPflPerType.resize(sz2);
5932 for(std::size_t i=0;i<sz2;i++)
5934 DataArrayInt *locDa=idsInPflPerType2[i];
5936 idsInPflPerType[i]=locDa;
5938 std::size_t sz=idsPerType2.size();
5939 idsPerType.resize(sz);
5940 for(std::size_t i=0;i<sz;i++)
5942 DataArrayInt *locDa=idsPerType2[i];
5944 idsPerType[i]=locDa;
5949 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5950 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5951 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5952 * 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.
5954 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5956 checkFullyDefined();
5957 nM1LevMesh->checkFullyDefined();
5958 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5960 if(_coords!=nM1LevMesh->getCoords())
5961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5963 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5964 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5966 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5967 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5968 tmp->setConnectivity(tmp0,tmp1);
5969 tmp->renumberCells(ret0->getConstPointer(),false);
5970 revDesc=tmp->getNodalConnectivity();
5971 revDescIndx=tmp->getNodalConnectivityIndex();
5972 DataArrayInt *ret=0;
5973 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5976 ret->getMaxValue(tmp2);
5978 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5979 throw INTERP_KERNEL::Exception(oss.str().c_str());
5984 revDescIndx->incrRef();
5987 meshnM1Old2New=ret0;
5992 * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5993 * It avoids to deal with renum in MEDLoader so it is useful for MED file R/W with multi types.
5994 * This method returns a newly allocated array old2New.
5995 * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5997 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5999 checkConnectivityFullyDefined();
6000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6001 renumberCells(ret->getConstPointer(),false);
6006 * This methods checks that cells are sorted by their types.
6007 * This method makes asumption (no check) that connectivity is correctly set before calling.
6009 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6011 checkFullyDefined();
6012 const int *conn=_nodal_connec->getConstPointer();
6013 const int *connI=_nodal_connec_index->getConstPointer();
6014 int nbOfCells=getNumberOfCells();
6015 std::set<INTERP_KERNEL::NormalizedCellType> types;
6016 for(const int *i=connI;i!=connI+nbOfCells;)
6018 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6019 if(types.find(curType)!=types.end())
6021 types.insert(curType);
6022 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6028 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6029 * The geometric type order is specified by MED file.
6031 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6033 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6035 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6039 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6040 * that the order is specified in array defined by [orderBg,orderEnd).
6041 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6042 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6044 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6046 checkFullyDefined();
6047 const int *conn=_nodal_connec->getConstPointer();
6048 const int *connI=_nodal_connec_index->getConstPointer();
6049 int nbOfCells=getNumberOfCells();
6053 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6054 for(const int *i=connI;i!=connI+nbOfCells;)
6056 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6057 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6058 if(isTypeExists!=orderEnd)
6060 int pos=(int)std::distance(orderBg,isTypeExists);
6064 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6068 if(sg.find(curType)==sg.end())
6070 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6081 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6082 * 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
6083 * 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'.
6085 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6087 checkConnectivityFullyDefined();
6088 int nbOfCells=getNumberOfCells();
6089 const int *conn=_nodal_connec->getConstPointer();
6090 const int *connI=_nodal_connec_index->getConstPointer();
6091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6092 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6093 tmpa->alloc(nbOfCells,1);
6094 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6095 tmpb->fillWithZero();
6096 int *tmp=tmpa->getPointer();
6097 int *tmp2=tmpb->getPointer();
6098 for(const int *i=connI;i!=connI+nbOfCells;i++)
6100 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6103 int pos=(int)std::distance(orderBg,where);
6105 tmp[std::distance(connI,i)]=pos;
6109 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6110 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6111 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6112 throw INTERP_KERNEL::Exception(oss.str().c_str());
6115 nbPerType=tmpb.retn();
6120 * 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'.
6121 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6122 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6123 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6125 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6127 DataArrayInt *nbPerType=0;
6128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6129 nbPerType->decrRef();
6130 return tmpa->buildPermArrPerLevel();
6134 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6135 * The number of cells remains unchanged after the call of this method.
6136 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6137 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6139 * @return the array giving the correspondance old to new.
6141 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6143 checkFullyDefined();
6145 const int *conn=_nodal_connec->getConstPointer();
6146 const int *connI=_nodal_connec_index->getConstPointer();
6147 int nbOfCells=getNumberOfCells();
6148 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6149 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6150 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6152 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6153 types.push_back(curType);
6154 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6156 DataArrayInt *ret=DataArrayInt::New();
6157 ret->alloc(nbOfCells,1);
6158 int *retPtr=ret->getPointer();
6159 std::fill(retPtr,retPtr+nbOfCells,-1);
6161 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6163 for(const int *i=connI;i!=connI+nbOfCells;i++)
6164 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6165 retPtr[std::distance(connI,i)]=newCellId++;
6167 renumberCells(retPtr,false);
6172 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6173 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6174 * This method makes asumption that connectivity is correctly set before calling.
6176 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6178 checkFullyDefined();
6179 const int *conn=_nodal_connec->getConstPointer();
6180 const int *connI=_nodal_connec_index->getConstPointer();
6181 int nbOfCells=getNumberOfCells();
6182 std::vector<MEDCouplingUMesh *> ret;
6183 for(const int *i=connI;i!=connI+nbOfCells;)
6185 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6186 int beginCellId=(int)std::distance(connI,i);
6187 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6188 int endCellId=(int)std::distance(connI,i);
6189 int sz=endCellId-beginCellId;
6190 int *cells=new int[sz];
6191 for(int j=0;j<sz;j++)
6192 cells[j]=beginCellId+j;
6193 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6201 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6202 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6203 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6204 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6205 * are not used here to avoid the build of big permutation array.
6207 * \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
6208 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6209 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6210 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6211 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6212 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6213 * \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
6214 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6216 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6217 DataArrayInt *&szOfCellGrpOfSameType,
6218 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6220 std::vector<const MEDCouplingUMesh *> ms2;
6221 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6224 (*it)->checkConnectivityFullyDefined();
6228 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6229 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6230 int meshDim=ms2[0]->getMeshDimension();
6231 std::vector<const MEDCouplingUMesh *> m1ssm;
6232 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6234 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6235 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6238 ret1->alloc(0,1); ret2->alloc(0,1);
6239 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6241 if(meshDim!=(*it)->getMeshDimension())
6242 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6243 if(refCoo!=(*it)->getCoords())
6244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6245 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6246 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6247 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6248 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6250 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6251 m1ssmSingleAuto.push_back(singleCell);
6252 m1ssmSingle.push_back(singleCell);
6253 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6256 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6258 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6259 for(std::size_t i=0;i<m1ssm.size();i++)
6260 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6261 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6262 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6263 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6268 * This method returns a newly created DataArrayInt instance.
6269 * This method retrieves cell ids in [begin,end) that have the type 'type'.
6271 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6273 checkFullyDefined();
6274 const int *conn=_nodal_connec->getConstPointer();
6275 const int *connIndex=_nodal_connec_index->getConstPointer();
6276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6277 for(const int *w=begin;w!=end;w++)
6278 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6279 ret->pushBackSilent(*w);
6284 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6285 * are in [0:getNumberOfCells())
6287 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6289 checkFullyDefined();
6290 const int *conn=_nodal_connec->getConstPointer();
6291 const int *connI=_nodal_connec_index->getConstPointer();
6292 int nbOfCells=getNumberOfCells();
6293 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6294 int *tmp=new int[nbOfCells];
6295 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6298 for(const int *i=connI;i!=connI+nbOfCells;i++)
6299 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6300 tmp[std::distance(connI,i)]=j++;
6302 DataArrayInt *ret=DataArrayInt::New();
6303 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6304 ret->copyStringInfoFrom(*da);
6305 int *retPtr=ret->getPointer();
6306 const int *daPtr=da->getConstPointer();
6307 int nbOfElems=da->getNbOfElems();
6308 for(int k=0;k<nbOfElems;k++)
6309 retPtr[k]=tmp[daPtr[k]];
6315 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6316 * This method \b works \b for mesh sorted by type.
6317 * cells whose ids is in 'idsPerGeoType' array.
6318 * This method conserves coords and name of mesh.
6320 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6322 std::vector<int> code=getDistributionOfTypes();
6323 std::size_t nOfTypesInThis=code.size()/3;
6324 int sz=0,szOfType=0;
6325 for(std::size_t i=0;i<nOfTypesInThis;i++)
6330 szOfType=code[3*i+1];
6332 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6333 if(*work<0 || *work>=szOfType)
6335 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6336 oss << ". It should be in [0," << szOfType << ") !";
6337 throw INTERP_KERNEL::Exception(oss.str().c_str());
6339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6340 int *idsPtr=idsTokeep->getPointer();
6342 for(std::size_t i=0;i<nOfTypesInThis;i++)
6345 for(int j=0;j<code[3*i+1];j++)
6348 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6349 offset+=code[3*i+1];
6351 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6352 ret->copyTinyInfoFrom(this);
6357 * This method returns a vector of size 'this->getNumberOfCells()'.
6358 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
6360 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6362 int ncell=getNumberOfCells();
6363 std::vector<bool> ret(ncell);
6364 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6365 const int *c=getNodalConnectivity()->getConstPointer();
6366 for(int i=0;i<ncell;i++)
6368 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6369 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6370 ret[i]=cm.isQuadratic();
6376 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
6378 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6380 if(other->getType()!=UNSTRUCTURED)
6381 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6382 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6383 return MergeUMeshes(this,otherC);
6387 * This method is ** very badly named ** : This method computes the center of inertia of each cells in \a this.
6388 * So this method is not a right choice for degnerated meshes (not well oriented, cells with measure close to zero).
6390 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
6391 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6393 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6395 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6397 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6398 int spaceDim=getSpaceDimension();
6399 int nbOfCells=getNumberOfCells();
6400 ret->alloc(nbOfCells,spaceDim);
6401 ret->copyStringInfoFrom(*getCoords());
6402 double *ptToFill=ret->getPointer();
6403 const int *nodal=_nodal_connec->getConstPointer();
6404 const int *nodalI=_nodal_connec_index->getConstPointer();
6405 const double *coor=_coords->getConstPointer();
6406 for(int i=0;i<nbOfCells;i++)
6408 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6409 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6416 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6417 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
6419 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
6420 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6422 * \sa MEDCouplingUMesh::getBarycenterAndOwner
6423 * \throw If \a this is not fully defined (coordinates and connectivity)
6424 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6426 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
6428 checkFullyDefined();
6429 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6430 int spaceDim=getSpaceDimension();
6431 int nbOfCells=getNumberOfCells();
6432 int nbOfNodes=getNumberOfNodes();
6433 ret->alloc(nbOfCells,spaceDim);
6434 double *ptToFill=ret->getPointer();
6435 const int *nodal=_nodal_connec->getConstPointer();
6436 const int *nodalI=_nodal_connec_index->getConstPointer();
6437 const double *coor=_coords->getConstPointer();
6438 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6440 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6441 std::fill(ptToFill,ptToFill+spaceDim,0.);
6442 if(type!=INTERP_KERNEL::NORM_POLYHED)
6444 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6446 if(*conn>=0 && *conn<nbOfNodes)
6447 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6450 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
6451 throw INTERP_KERNEL::Exception(oss.str().c_str());
6454 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6455 if(nbOfNodesInCell>0)
6456 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6459 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6460 throw INTERP_KERNEL::Exception(oss.str().c_str());
6465 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6467 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6469 if(*it>=0 && *it<nbOfNodes)
6470 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6473 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
6474 throw INTERP_KERNEL::Exception(oss.str().c_str());
6478 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6481 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6482 throw INTERP_KERNEL::Exception(oss.str().c_str());
6490 * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
6491 * 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().
6492 * No check of that will be done !
6494 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6496 DataArrayDouble *ret=DataArrayDouble::New();
6497 int spaceDim=getSpaceDimension();
6498 int nbOfTuple=(int)std::distance(begin,end);
6499 ret->alloc(nbOfTuple,spaceDim);
6500 double *ptToFill=ret->getPointer();
6501 double *tmp=new double[spaceDim];
6502 const int *nodal=_nodal_connec->getConstPointer();
6503 const int *nodalI=_nodal_connec_index->getConstPointer();
6504 const double *coor=_coords->getConstPointer();
6505 for(const int *w=begin;w!=end;w++)
6507 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6508 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6516 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6519 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
6522 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6523 da->checkAllocated();
6524 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
6526 int nbOfTuples=da->getNumberOfTuples();
6527 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6528 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6529 c->alloc(2*nbOfTuples,1);
6530 cI->alloc(nbOfTuples+1,1);
6531 int *cp=c->getPointer();
6532 int *cip=cI->getPointer();
6534 for(int i=0;i<nbOfTuples;i++)
6536 *cp++=INTERP_KERNEL::NORM_POINT1;
6540 ret->setConnectivity(c,cI,true);
6545 * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
6546 * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
6548 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6550 std::vector<const MEDCouplingUMesh *> tmp(2);
6551 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6552 return MergeUMeshes(tmp);
6556 * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
6557 * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
6558 * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
6559 * cells in meshes in 'a' (in the same order too).
6561 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6563 std::size_t sz=a.size();
6565 return MergeUMeshesLL(a);
6566 for(std::size_t ii=0;ii<sz;ii++)
6569 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6570 throw INTERP_KERNEL::Exception(oss.str().c_str());
6572 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
6573 std::vector< const MEDCouplingUMesh * > aa(sz);
6575 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6577 const MEDCouplingUMesh *cur=a[i];
6578 const DataArrayDouble *coo=cur->getCoords();
6580 spaceDim=coo->getNumberOfComponents();
6583 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6584 for(std::size_t i=0;i<sz;i++)
6586 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6589 return MergeUMeshesLL(aa);
6594 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
6598 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
6599 int meshDim=(*it)->getMeshDimension();
6600 int nbOfCells=(*it)->getNumberOfCells();
6601 int meshLgth=(*it++)->getMeshLength();
6602 for(;it!=a.end();it++)
6604 if(meshDim!=(*it)->getMeshDimension())
6605 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
6606 nbOfCells+=(*it)->getNumberOfCells();
6607 meshLgth+=(*it)->getMeshLength();
6609 std::vector<const MEDCouplingPointSet *> aps(a.size());
6610 std::copy(a.begin(),a.end(),aps.begin());
6611 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
6612 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
6613 ret->setCoords(pts);
6614 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6615 c->alloc(meshLgth,1);
6616 int *cPtr=c->getPointer();
6617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6618 cI->alloc(nbOfCells+1,1);
6619 int *cIPtr=cI->getPointer();
6623 for(it=a.begin();it!=a.end();it++)
6625 int curNbOfCell=(*it)->getNumberOfCells();
6626 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
6627 const int *curC=(*it)->_nodal_connec->getConstPointer();
6628 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
6629 for(int j=0;j<curNbOfCell;j++)
6631 const int *src=curC+curCI[j];
6633 for(;src!=curC+curCI[j+1];src++,cPtr++)
6641 offset+=curCI[curNbOfCell];
6642 offset2+=(*it)->getNumberOfNodes();
6645 ret->setConnectivity(c,cI,true);
6652 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6653 * 'meshes' must be a non empty vector.
6655 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6657 std::vector<const MEDCouplingUMesh *> tmp(2);
6658 tmp[0]=mesh1; tmp[1]=mesh2;
6659 return MergeUMeshesOnSameCoords(tmp);
6663 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6664 * 'meshes' must be a non empty vector.
6666 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6669 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6670 for(std::size_t ii=0;ii<meshes.size();ii++)
6673 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6674 throw INTERP_KERNEL::Exception(oss.str().c_str());
6676 const DataArrayDouble *coords=meshes.front()->getCoords();
6677 int meshDim=meshes.front()->getMeshDimension();
6678 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6680 int meshIndexLgth=0;
6681 for(;iter!=meshes.end();iter++)
6683 if(coords!=(*iter)->getCoords())
6684 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6685 if(meshDim!=(*iter)->getMeshDimension())
6686 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6687 meshLgth+=(*iter)->getMeshLength();
6688 meshIndexLgth+=(*iter)->getNumberOfCells();
6690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
6691 nodal->alloc(meshLgth,1);
6692 int *nodalPtr=nodal->getPointer();
6693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
6694 nodalIndex->alloc(meshIndexLgth+1,1);
6695 int *nodalIndexPtr=nodalIndex->getPointer();
6697 for(iter=meshes.begin();iter!=meshes.end();iter++)
6699 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
6700 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
6701 int nbOfCells=(*iter)->getNumberOfCells();
6702 int meshLgth2=(*iter)->getMeshLength();
6703 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6704 if(iter!=meshes.begin())
6705 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6707 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6710 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6711 ret->setName("merge");
6712 ret->setMeshDimension(meshDim);
6713 ret->setConnectivity(nodal,nodalIndex,true);
6714 ret->setCoords(coords);
6719 * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
6720 * 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)
6722 * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
6723 * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
6724 * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
6725 * The arrays contained in 'corr' parameter are returned with refcounter set to one.
6726 * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
6727 * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
6728 * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
6730 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6732 //All checks are delegated to MergeUMeshesOnSameCoords
6733 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6735 corr.resize(meshes.size());
6736 std::size_t nbOfMeshes=meshes.size();
6738 const int *o2nPtr=o2n->getConstPointer();
6739 for(std::size_t i=0;i<nbOfMeshes;i++)
6741 DataArrayInt *tmp=DataArrayInt::New();
6742 int curNbOfCells=meshes[i]->getNumberOfCells();
6743 tmp->alloc(curNbOfCells,1);
6744 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6745 offset+=curNbOfCells;
6746 tmp->setName(meshes[i]->getName());
6753 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6754 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6755 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6756 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6758 * This method performs nothing if size of \b meshes is in [0,1].
6759 * This method is particulary useful in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6760 * coordinates DataArrayDouble instance.
6762 * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6764 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6766 std::size_t sz=meshes.size();
6769 std::vector< const DataArrayDouble * > coords(meshes.size());
6770 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6771 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6775 (*it)->checkConnectivityFullyDefined();
6776 const DataArrayDouble *coo=(*it)->getCoords();
6781 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6782 oss << " has no coordinate array defined !";
6783 throw INTERP_KERNEL::Exception(oss.str().c_str());
6788 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6789 oss << " is null !";
6790 throw INTERP_KERNEL::Exception(oss.str().c_str());
6793 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6794 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6795 int offset=(*it)->getNumberOfNodes();
6796 (*it++)->setCoords(res);
6797 for(;it!=meshes.end();it++)
6799 int oldNumberOfNodes=(*it)->getNumberOfNodes();
6800 (*it)->setCoords(res);
6801 (*it)->shiftNodeNumbersInConn(offset);
6802 offset+=oldNumberOfNodes;
6807 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6808 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6809 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6810 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6811 * 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.
6813 * This method performs nothing if size of \b meshes is empty.
6814 * This method is particulary useful in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6815 * coordinates DataArrayDouble instance.
6817 * \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.
6818 * \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.
6820 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6824 std::set<const DataArrayDouble *> s;
6825 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6828 s.insert((*it)->getCoords());
6831 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 !";
6832 throw INTERP_KERNEL::Exception(oss.str().c_str());
6837 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 !";
6838 throw INTERP_KERNEL::Exception(oss.str().c_str());
6840 const DataArrayDouble *coo=*(s.begin());
6844 DataArrayInt *comm,*commI;
6845 coo->findCommonTuples(eps,-1,comm,commI);
6846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6847 int oldNbOfNodes=coo->getNumberOfTuples();
6849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6850 if(oldNbOfNodes==newNbOfNodes)
6852 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6853 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6855 (*it)->renumberNodesInConn(o2n->getConstPointer());
6856 (*it)->setCoords(newCoords);
6861 * 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.
6862 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6863 * @param isQuad specifies the policy of connectivity.
6864 * @ret in/out parameter in which the result will be append
6866 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6868 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6869 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6870 ret.push_back(cm.getExtrudedType());
6871 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6874 case INTERP_KERNEL::NORM_POINT1:
6876 ret.push_back(connBg[1]);
6877 ret.push_back(connBg[1]+nbOfNodesPerLev);
6880 case INTERP_KERNEL::NORM_SEG2:
6882 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6883 ret.insert(ret.end(),conn,conn+4);
6886 case INTERP_KERNEL::NORM_SEG3:
6888 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6889 ret.insert(ret.end(),conn,conn+8);
6892 case INTERP_KERNEL::NORM_QUAD4:
6894 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6895 ret.insert(ret.end(),conn,conn+8);
6898 case INTERP_KERNEL::NORM_TRI3:
6900 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6901 ret.insert(ret.end(),conn,conn+6);
6904 case INTERP_KERNEL::NORM_TRI6:
6906 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,
6907 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6908 ret.insert(ret.end(),conn,conn+15);
6911 case INTERP_KERNEL::NORM_QUAD8:
6914 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6915 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6916 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6918 ret.insert(ret.end(),conn,conn+20);
6921 case INTERP_KERNEL::NORM_POLYGON:
6923 std::back_insert_iterator< std::vector<int> > ii(ret);
6924 std::copy(connBg+1,connEnd,ii);
6926 std::reverse_iterator<const int *> rConnBg(connEnd);
6927 std::reverse_iterator<const int *> rConnEnd(connBg+1);
6928 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6929 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6930 for(std::size_t i=0;i<nbOfRadFaces;i++)
6933 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6934 std::copy(conn,conn+4,ii);
6939 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6944 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6946 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6948 double v[3]={0.,0.,0.};
6949 std::size_t sz=std::distance(begin,end);
6952 for(std::size_t i=0;i<sz;i++)
6954 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];
6955 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6956 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6958 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6962 * The polyhedron is specfied by its connectivity nodes in [begin,end).
6964 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6966 std::vector<std::pair<int,int> > edges;
6967 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6968 const int *bgFace=begin;
6969 for(std::size_t i=0;i<nbOfFaces;i++)
6971 const int *endFace=std::find(bgFace+1,end,-1);
6972 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6973 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6975 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6976 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6978 edges.push_back(p1);
6982 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6986 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
6988 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6990 double vec0[3],vec1[3];
6991 std::size_t sz=std::distance(begin,end);
6993 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6994 int nbOfNodes=(int)sz/2;
6995 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6996 const double *pt0=coords+3*begin[0];
6997 const double *pt1=coords+3*begin[nbOfNodes];
6998 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6999 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7002 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7004 std::size_t sz=std::distance(begin,end);
7005 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7006 std::size_t nbOfNodes(sz/2);
7007 std::copy(begin,end,(int *)tmp);
7008 for(std::size_t j=1;j<nbOfNodes;j++)
7010 begin[j]=tmp[nbOfNodes-j];
7011 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7015 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7017 std::size_t sz=std::distance(begin,end);
7019 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7020 double vec0[3],vec1[3];
7021 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7022 vec0[0]=pt1[0]-pt0[0]; vec0[1]=pt1[1]-pt0[1]; vec0[2]=pt1[2]-pt0[2]; vec1[0]=pt2[0]-pt0[0]; vec1[1]=pt2[1]-pt0[1]; vec1[2]=pt2[2]-pt0[2];
7023 return ((vec0[1]*vec1[2]-vec0[2]*vec1[1])*(pt3[0]-pt0[0])+(vec0[2]*vec1[0]-vec0[0]*vec1[2])*(pt3[1]-pt0[1])+(vec0[0]*vec1[1]-vec0[1]*vec1[0])*(pt3[2]-pt0[2]))<0;
7026 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7028 std::size_t sz=std::distance(begin,end);
7030 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7032 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7033 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7034 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7038 * 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)
7039 * 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
7042 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7043 * \param [in] coords the coordinates with nb of components exactly equal to 3
7044 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7045 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7046 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7048 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7050 int nbFaces=std::count(begin+1,end,-1)+1;
7051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7052 double *vPtr=v->getPointer();
7053 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7054 double *pPtr=p->getPointer();
7055 const int *stFaceConn=begin+1;
7056 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7058 const int *endFaceConn=std::find(stFaceConn,end,-1);
7059 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7060 stFaceConn=endFaceConn+1;
7062 pPtr=p->getPointer(); vPtr=v->getPointer();
7063 DataArrayInt *comm1=0,*commI1=0;
7064 v->findCommonTuples(eps,-1,comm1,commI1);
7065 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7066 const int *comm1Ptr=comm1->getConstPointer();
7067 const int *commI1Ptr=commI1->getConstPointer();
7068 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7069 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7071 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7072 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7073 mm->finishInsertingCells();
7075 for(int i=0;i<nbOfGrps1;i++)
7077 int vecId=comm1Ptr[commI1Ptr[i]];
7078 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7079 DataArrayInt *comm2=0,*commI2=0;
7080 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7082 const int *comm2Ptr=comm2->getConstPointer();
7083 const int *commI2Ptr=commI2->getConstPointer();
7084 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7085 for(int j=0;j<nbOfGrps2;j++)
7087 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7089 res->insertAtTheEnd(begin,end);
7090 res->pushBackSilent(-1);
7094 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7096 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7097 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7098 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7099 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7101 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7102 const int *idsNodePtr=idsNode->getConstPointer();
7103 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];
7104 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7105 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7106 if(std::abs(norm)>eps)
7108 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7109 mm3->rotate(center,vec,angle);
7111 mm3->changeSpaceDimension(2);
7112 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7113 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7114 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7115 int nbOfCells=mm4->getNumberOfCells();
7116 for(int k=0;k<nbOfCells;k++)
7119 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7120 res->pushBackSilent(idsNodePtr[*work]);
7121 res->pushBackSilent(-1);
7126 res->popBackSilent();
7130 * 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
7131 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
7133 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7134 * \param [in] coords coordinates expected to have 3 components.
7135 * \param [in] begin start of the nodal connectivity of the face.
7136 * \param [in] end end of the nodal connectivity (excluded) of the face.
7137 * \param [out] v the normalized vector of size 3
7138 * \param [out] p the pos of plane
7140 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7142 std::size_t nbPoints=std::distance(begin,end);
7144 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7147 bool refFound=false;
7148 for(;j<nbPoints-1 && !refFound;j++)
7150 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7151 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7152 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7153 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7157 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7160 for(std::size_t i=j;i<nbPoints-1;i++)
7163 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7164 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7165 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7166 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7169 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7170 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];
7171 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7174 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7175 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7179 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7183 * This method tries to obtain a well oriented polyhedron.
7184 * If the algorithm fails, an exception will be thrown.
7186 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7188 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7189 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7190 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7192 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7193 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7194 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7196 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7199 std::size_t smthChanged=0;
7200 for(std::size_t i=0;i<nbOfFaces;i++)
7202 endFace=std::find(bgFace+1,end,-1);
7203 nbOfEdgesInFace=std::distance(bgFace,endFace);
7207 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7209 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7210 std::pair<int,int> p2(p1.second,p1.first);
7211 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7212 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7213 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7218 std::reverse(bgFace+1,endFace);
7219 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7221 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7222 std::pair<int,int> p2(p1.second,p1.first);
7223 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7224 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7225 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7226 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7227 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7228 if(it!=edgesOK.end())
7231 edgesFinished.push_back(p1);
7234 edgesOK.push_back(p1);
7241 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7243 if(!edgesOK.empty())
7244 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7245 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7246 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7248 for(std::size_t i=0;i<nbOfFaces;i++)
7250 endFace=std::find(bgFace+1,end,-1);
7251 std::reverse(bgFace+1,endFace);
7258 * This method makes the assumption spacedimension == meshdimension == 2.
7259 * This method works only for linear cells.
7261 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7263 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7265 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7267 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7268 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7269 int nbOfNodesExpected=m->getNumberOfNodes();
7270 if(m->getNumberOfCells()!=nbOfNodesExpected)
7271 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7273 const int *n2oPtr=n2o->getConstPointer();
7274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7275 m->getReverseNodalConnectivity(revNodal,revNodalI);
7276 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7277 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7278 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7280 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7281 if(nbOfNodesExpected<1)
7284 int prevNode=nodalPtr[nodalIPtr[0]+1];
7285 *work++=n2oPtr[prevNode];
7286 for(int i=1;i<nbOfNodesExpected;i++)
7288 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7290 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7291 conn.erase(prevNode);
7294 int curNode=*(conn.begin());
7295 *work++=n2oPtr[curNode];
7296 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7297 shar.erase(prevCell);
7300 prevCell=*(shar.begin());
7304 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7307 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7316 * This method makes the assumption spacedimension == meshdimension == 3.
7317 * This method works only for linear cells.
7319 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7321 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7323 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7324 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7325 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7326 const int *conn=m->getNodalConnectivity()->getConstPointer();
7327 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7328 int nbOfCells=m->getNumberOfCells();
7329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7330 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7333 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7334 for(int i=1;i<nbOfCells;i++)
7337 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7343 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7344 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7346 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7350 for(int i=0;i<nbOfNodesInCell;i++)
7351 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7352 else if(spaceDim==2)
7354 for(int i=0;i<nbOfNodesInCell;i++)
7356 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7361 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7364 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7366 int nbOfCells=getNumberOfCells();
7368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7369 static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,-1,4};
7370 ofs << " <" << getVTKDataSetType() << ">\n";
7371 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7372 ofs << " <PointData>\n" << pointData << std::endl;
7373 ofs << " </PointData>\n";
7374 ofs << " <CellData>\n" << cellData << std::endl;
7375 ofs << " </CellData>\n";
7376 ofs << " <Points>\n";
7377 if(getSpaceDimension()==3)
7378 _coords->writeVTK(ofs,8,"Points");
7381 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7382 coo->writeVTK(ofs,8,"Points");
7384 ofs << " </Points>\n";
7385 ofs << " <Cells>\n";
7386 const int *cPtr=_nodal_connec->getConstPointer();
7387 const int *cIPtr=_nodal_connec_index->getConstPointer();
7388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7392 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7393 int szFaceOffsets=0,szConn=0;
7394 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7397 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7400 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7401 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7405 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7406 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7407 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7408 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7409 w4=std::copy(c.begin(),c.end(),w4);
7412 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
7413 types->writeVTK(ofs,8,"UInt8","types");
7414 offsets->writeVTK(ofs,8,"Int32","offsets");
7415 if(szFaceOffsets!=0)
7416 {//presence of Polyhedra
7417 connectivity->reAlloc(szConn);
7418 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
7419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7420 w1=faces->getPointer();
7421 for(int i=0;i<nbOfCells;i++)
7422 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7424 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7426 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7427 for(int j=0;j<nbFaces;j++)
7429 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7430 *w1++=(int)std::distance(w6,w5);
7431 w1=std::copy(w6,w5,w1);
7435 faces->writeVTK(ofs,8,"Int32","faces");
7437 connectivity->writeVTK(ofs,8,"Int32","connectivity");
7438 ofs << " </Cells>\n";
7439 ofs << " </Piece>\n";
7440 ofs << " </" << getVTKDataSetType() << ">\n";
7443 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
7445 stream << "MEDCouplingUMesh C++ instance at " << this << ".";
7447 { stream << " Not set !"; return ; }
7448 stream << " Mesh dimension : " << _mesh_dim << ".";
7452 { stream << " No coordinates set !"; return ; }
7453 if(!_coords->isAllocated())
7454 { stream << " Coordinates set but not allocated !"; return ; }
7455 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7456 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7457 if(!_nodal_connec_index)
7458 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7459 if(!_nodal_connec_index->isAllocated())
7460 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7461 int lgth=_nodal_connec_index->getNumberOfTuples();
7462 int cpt=_nodal_connec_index->getNumberOfComponents();
7463 if(cpt!=1 || lgth<1)
7465 stream << std::endl << "Number of cells : " << lgth-1 << ".";
7468 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
7470 return std::string("UnstructuredGrid");
7475 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
7477 m1->checkFullyDefined();
7478 m2->checkFullyDefined();
7479 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
7480 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
7481 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
7482 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
7483 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
7484 std::vector<double> addCoo,addCoordsQuadratic;
7485 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
7486 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
7487 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
7488 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
7489 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
7490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
7491 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
7492 std::vector< std::vector<int> > intersectEdge2;
7493 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
7494 subDiv2.clear(); dd5=0; dd6=0;
7495 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
7496 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
7497 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
7498 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
7500 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
7501 addCooDa->alloc((int)(addCoo.size())/2,2);
7502 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
7503 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
7504 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
7505 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
7506 std::vector<const DataArrayDouble *> coordss(4);
7507 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
7508 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
7509 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
7510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
7511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
7512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
7513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
7514 ret->setConnectivity(conn,connI,true);
7515 ret->setCoords(coo);
7516 cellNb1=c1.retn(); cellNb2=c2.retn();
7522 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
7523 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
7524 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
7525 const std::vector<double>& addCoords,
7526 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
7528 static const int SPACEDIM=2;
7529 std::vector<double> bbox1,bbox2;
7530 const double *coo1=m1->getCoords()->getConstPointer();
7531 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
7532 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
7533 int offset1=m1->getNumberOfNodes();
7534 const double *coo2=m2->getCoords()->getConstPointer();
7535 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
7536 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
7537 int offset2=offset1+m2->getNumberOfNodes();
7538 int offset3=offset2+((int)addCoords.size())/2;
7539 m1->getBoundingBoxForBBTree(bbox1);
7540 m2->getBoundingBoxForBBTree(bbox2);
7541 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
7542 int ncell1=m1->getNumberOfCells();
7544 for(int i=0;i<ncell1;i++)
7546 std::vector<int> candidates2;
7547 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7548 std::map<INTERP_KERNEL::Node *,int> mapp;
7549 std::map<int,INTERP_KERNEL::Node *> mappRev;
7550 INTERP_KERNEL::QuadraticPolygon pol1;
7551 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
7552 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7553 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
7554 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
7555 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
7557 std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result
7558 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
7559 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
7560 for(it1.first();!it1.finished();it1.next())
7561 edges1.insert(it1.current()->getPtr());
7563 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
7564 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
7566 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7568 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
7569 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
7570 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
7571 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
7572 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
7575 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7577 pol1.initLocationsWithOther(pol2s[ii]);
7578 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
7579 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
7580 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7586 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7588 catch(INTERP_KERNEL::Exception& e)
7590 std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
7591 throw INTERP_KERNEL::Exception(oss.str().c_str());
7594 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
7595 (*it).second->decrRef();
7600 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
7603 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
7604 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
7605 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
7606 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
7607 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
7609 static const int SPACEDIM=2;
7610 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
7611 desc2=DataArrayInt::New();
7612 descIndx2=DataArrayInt::New();
7613 revDesc2=DataArrayInt::New();
7614 revDescIndx2=DataArrayInt::New();
7615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
7616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
7617 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
7618 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
7619 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
7620 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
7621 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
7622 std::vector<double> bbox1,bbox2;
7623 m1Desc->getBoundingBoxForBBTree(bbox1);
7624 m2Desc->getBoundingBoxForBBTree(bbox2);
7625 int ncell1=m1Desc->getNumberOfCells();
7626 int ncell2=m2Desc->getNumberOfCells();
7627 intersectEdge1.resize(ncell1);
7628 colinear2.resize(ncell2);
7629 subDiv2.resize(ncell2);
7630 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
7631 std::vector<int> candidates1(1);
7632 int offset1=m1->getNumberOfNodes();
7633 int offset2=offset1+m2->getNumberOfNodes();
7634 for(int i=0;i<ncell1;i++)
7636 std::vector<int> candidates2;
7637 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7638 if(!candidates2.empty())
7640 std::map<INTERP_KERNEL::Node *,int> map1,map2;
7641 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
7643 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
7644 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
7649 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
7651 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
7652 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
7656 * This method performs the 2nd step of Partition of 2D mesh.
7657 * This method has 4 inputs :
7658 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
7659 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
7660 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
7661 * 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'
7662 * @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'
7663 * @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.
7664 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
7666 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)
7668 int offset1=m1->getNumberOfNodes();
7669 int ncell=m2->getNumberOfCells();
7670 const int *c=m2->getNodalConnectivity()->getConstPointer();
7671 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
7672 const double *coo=m2->getCoords()->getConstPointer();
7673 const double *cooBis=m1->getCoords()->getConstPointer();
7674 int offset2=offset1+m2->getNumberOfNodes();
7675 intersectEdge.resize(ncell);
7676 for(int i=0;i<ncell;i++,cI++)
7678 const std::vector<int>& divs=subDiv[i];
7679 int nnode=cI[1]-cI[0]-1;
7680 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
7681 std::map<INTERP_KERNEL::Node *, int> mapp22;
7682 for(int j=0;j<nnode;j++)
7684 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
7685 int nnid=c[(*cI)+j+1];
7686 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
7687 mapp22[nn]=nnid+offset1;
7689 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
7690 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
7691 ((*it).second.first)->decrRef();
7692 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
7693 std::map<INTERP_KERNEL::Node *,int> mapp3;
7694 for(std::size_t j=0;j<divs.size();j++)
7697 INTERP_KERNEL::Node *tmp=0;
7699 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
7701 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
7703 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
7707 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
7708 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
7715 * 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).
7716 * 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
7717 * with a plane. The result will be put in 'cut3DSuf' out parameter.
7718 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
7719 * @param nodesOnPlane, returns all the nodes that are on the plane.
7720 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
7721 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
7722 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
7723 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
7724 * @param desc is the descending connectivity 3DSurf->3DCurve
7725 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
7726 * @param cut3DSuf input/output param.
7728 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
7729 const int *nodal3DCurve, const int *nodalIndx3DCurve,
7730 const int *desc, const int *descIndx,
7731 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
7733 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
7734 int nbOf3DSurfCell=(int)cut3DSurf.size();
7735 for(int i=0;i<nbOf3DSurfCell;i++)
7737 std::vector<int> res;
7738 int offset=descIndx[i];
7739 int nbOfSeg=descIndx[i+1]-offset;
7740 for(int j=0;j<nbOfSeg;j++)
7742 int edgeId=desc[offset+j];
7743 int status=cut3DCurve[edgeId];
7747 res.push_back(status);
7750 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
7751 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
7759 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7765 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
7766 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
7769 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7773 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
7778 {// case when plane is on a multi colinear edge of a polyhedron
7779 if((int)res.size()==2*nbOfSeg)
7781 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
7784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
7791 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
7792 * 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).
7793 * 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
7794 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
7795 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
7796 * @param desc is the descending connectivity 3D->3DSurf
7797 * @param descIndx is the descending connectivity index 3D->3DSurf
7799 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
7800 const int *desc, const int *descIndx,
7801 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
7803 checkFullyDefined();
7804 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7805 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
7806 const int *nodal3D=_nodal_connec->getConstPointer();
7807 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
7808 int nbOfCells=getNumberOfCells();
7809 for(int i=0;i<nbOfCells;i++)
7811 std::map<int, std::set<int> > m;
7812 int offset=descIndx[i];
7813 int nbOfFaces=descIndx[i+1]-offset;
7816 for(int j=0;j<nbOfFaces;j++)
7818 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
7819 if(p.first!=-1 && p.second!=-1)
7823 start=p.first; end=p.second;
7824 m[p.first].insert(p.second);
7825 m[p.second].insert(p.first);
7829 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
7830 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
7831 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7832 INTERP_KERNEL::NormalizedCellType cmsId;
7833 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
7834 start=tmp[0]; end=tmp[nbOfNodesSon-1];
7835 for(unsigned k=0;k<nbOfNodesSon;k++)
7837 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
7838 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
7845 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
7849 std::map<int, std::set<int> >::const_iterator it=m.find(start);
7850 const std::set<int>& s=(*it).second;
7851 std::set<int> s2; s2.insert(prev);
7853 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
7856 int val=*s3.begin();
7857 conn.push_back(start);
7864 conn.push_back(end);
7867 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
7868 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
7869 cellIds->pushBackSilent(i);
7875 * 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
7876 * 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
7877 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7878 * 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
7879 * 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.
7881 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7883 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
7885 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7888 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7889 if(cm.getDimension()==2)
7891 const int *node=nodalConnBg+1;
7892 int startNode=*node++;
7893 double refX=coords[2*startNode];
7894 for(;node!=nodalConnEnd;node++)
7896 if(coords[2*(*node)]<refX)
7899 refX=coords[2*startNode];
7902 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7906 double angle0=-M_PI/2;
7912 while(nextNode!=startNode)
7916 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7918 if(*node!=tmpOut.back() && *node!=prevNode)
7920 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7921 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7926 res=angle0-angleM+2.*M_PI;
7935 if(nextNode!=startNode)
7937 angle0=angleNext-M_PI;
7940 prevNode=tmpOut.back();
7941 tmpOut.push_back(nextNode);
7944 std::vector<int> tmp3(2*(sz-1));
7945 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7946 std::copy(nodalConnBg+1,nodalConnEnd,it);
7947 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7949 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7952 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7954 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7959 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7960 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7972 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7973 * 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.
7975 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7976 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7977 * \param [in,out] arr array in which the remove operation will be done.
7978 * \param [in,out] arrIndx array in the remove operation will modify
7979 * \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])
7980 * \return true if \b arr and \b arrIndx have been modified, false if not.
7982 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7984 if(!arrIndx || !arr)
7985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7986 if(offsetForRemoval<0)
7987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7988 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7989 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7990 int *arrIPtr=arrIndx->getPointer();
7993 const int *arrPtr=arr->getConstPointer();
7994 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7995 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7997 if(*arrIPtr-previousArrI>offsetForRemoval)
7999 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8001 if(s.find(*work)==s.end())
8002 arrOut.push_back(*work);
8005 previousArrI=*arrIPtr;
8006 *arrIPtr=(int)arrOut.size();
8008 if(arr->getNumberOfTuples()==(int)arrOut.size())
8010 arr->alloc((int)arrOut.size(),1);
8011 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8016 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8017 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8018 * The selection of extraction is done standardly in new2old format.
8019 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8021 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8022 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8023 * \param [in] arrIn arr origin array from which the extraction will be done.
8024 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8025 * \param [out] arrOut the resulting array
8026 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8028 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8029 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8031 if(!arrIn || !arrIndxIn)
8032 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8033 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8034 const int *arrInPtr=arrIn->getConstPointer();
8035 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8036 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8037 int maxSizeOfArr=arrIn->getNumberOfTuples();
8038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8039 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8040 arrIo->alloc((int)(sz+1),1);
8041 const int *idsIt=idsOfSelectBg;
8042 int *work=arrIo->getPointer();
8045 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8047 if(*idsIt>=0 && *idsIt<nbOfGrps)
8048 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8051 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8052 throw INTERP_KERNEL::Exception(oss.str().c_str());
8058 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8059 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8060 throw INTERP_KERNEL::Exception(oss.str().c_str());
8063 arro->alloc(lgth,1);
8064 work=arro->getPointer();
8065 idsIt=idsOfSelectBg;
8066 for(std::size_t i=0;i<sz;i++,idsIt++)
8068 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8069 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8072 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8073 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8074 throw INTERP_KERNEL::Exception(oss.str().c_str());
8078 arrIndexOut=arrIo.retn();
8082 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8083 * 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
8084 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8085 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8087 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8088 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8089 * \param [in] arrIn arr origin array from which the extraction will be done.
8090 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8091 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8092 * \param [in] srcArrIndex index array of \b srcArr
8093 * \param [out] arrOut the resulting array
8094 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8096 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8098 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8099 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8100 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8102 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8103 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8106 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8107 std::vector<bool> v(nbOfTuples,true);
8109 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8110 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8111 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8113 if(*it>=0 && *it<nbOfTuples)
8116 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8120 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8121 throw INTERP_KERNEL::Exception(oss.str().c_str());
8124 srcArrIndexPtr=srcArrIndex->getConstPointer();
8125 arrIo->alloc(nbOfTuples+1,1);
8126 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8127 const int *arrInPtr=arrIn->getConstPointer();
8128 const int *srcArrPtr=srcArr->getConstPointer();
8129 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8130 int *arroPtr=arro->getPointer();
8131 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8135 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8136 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8140 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8141 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8142 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8146 arrIndexOut=arrIo.retn();
8150 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8151 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8153 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8154 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8155 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8156 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8157 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8158 * \param [in] srcArrIndex index array of \b srcArr
8160 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8162 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8163 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8165 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8166 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8167 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8168 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8169 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8170 int *arrInOutPtr=arrInOut->getPointer();
8171 const int *srcArrPtr=srcArr->getConstPointer();
8172 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8174 if(*it>=0 && *it<nbOfTuples)
8176 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8177 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8180 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] !";
8181 throw INTERP_KERNEL::Exception(oss.str().c_str());
8186 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8187 throw INTERP_KERNEL::Exception(oss.str().c_str());
8193 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8194 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8195 * 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]].
8196 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8197 * A negative value in \b arrIn means that it is ignored.
8198 * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
8200 * \param [in] arrIn arr origin array from which the extraction will be done.
8201 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8202 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8203 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8205 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8207 int seed=0,nbOfDepthPeelingPerformed=0;
8208 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8212 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8213 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8214 * 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]].
8215 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8216 * A negative value in \b arrIn means that it is ignored.
8217 * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
8218 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8219 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8220 * \param [in] arrIn arr origin array from which the extraction will be done.
8221 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8222 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8223 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8224 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8225 * \sa MEDCouplingUMesh::partitionBySpreadZone
8227 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8229 nbOfDepthPeelingPerformed=0;
8231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8232 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8235 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8239 std::vector<bool> fetched(nbOfTuples,false);
8240 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8243 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8245 nbOfDepthPeelingPerformed=0;
8246 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8247 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8248 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8249 std::vector<bool> fetched2(nbOfTuples,false);
8251 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8253 if(*seedElt>=0 && *seedElt<nbOfTuples)
8254 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8256 { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8258 const int *arrInPtr=arrIn->getConstPointer();
8259 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8260 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8261 std::vector<int> idsToFetch1(seedBg,seedEnd);
8262 std::vector<int> idsToFetch2;
8263 std::vector<int> *idsToFetch=&idsToFetch1;
8264 std::vector<int> *idsToFetchOther=&idsToFetch2;
8265 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8267 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8268 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8270 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8271 std::swap(idsToFetch,idsToFetchOther);
8272 idsToFetchOther->clear();
8273 nbOfDepthPeelingPerformed++;
8275 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8278 int *retPtr=ret->getPointer();
8279 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8286 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8287 * 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
8288 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8289 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8291 * \param [in] start begin of set of ids of the input extraction (included)
8292 * \param [in] end end of set of ids of the input extraction (excluded)
8293 * \param [in] step step of the set of ids in range mode.
8294 * \param [in] arrIn arr origin array from which the extraction will be done.
8295 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8296 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8297 * \param [in] srcArrIndex index array of \b srcArr
8298 * \param [out] arrOut the resulting array
8299 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8301 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8303 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8304 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8305 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8307 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8308 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8311 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8313 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8314 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8315 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8317 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8319 if(it>=0 && it<nbOfTuples)
8320 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8323 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8324 throw INTERP_KERNEL::Exception(oss.str().c_str());
8327 srcArrIndexPtr=srcArrIndex->getConstPointer();
8328 arrIo->alloc(nbOfTuples+1,1);
8329 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8330 const int *arrInPtr=arrIn->getConstPointer();
8331 const int *srcArrPtr=srcArr->getConstPointer();
8332 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8333 int *arroPtr=arro->getPointer();
8334 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8336 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8339 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8340 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8344 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8345 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8349 arrIndexOut=arrIo.retn();
8353 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8354 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8356 * \param [in] start begin of set of ids of the input extraction (included)
8357 * \param [in] end end of set of ids of the input extraction (excluded)
8358 * \param [in] step step of the set of ids in range mode.
8359 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8360 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8361 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8362 * \param [in] srcArrIndex index array of \b srcArr
8364 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8366 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8367 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8369 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8370 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
8371 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8372 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8373 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8374 int *arrInOutPtr=arrInOut->getPointer();
8375 const int *srcArrPtr=srcArr->getConstPointer();
8376 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
8378 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8380 if(it>=0 && it<nbOfTuples)
8382 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8383 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8386 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8387 throw INTERP_KERNEL::Exception(oss.str().c_str());
8392 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8393 throw INTERP_KERNEL::Exception(oss.str().c_str());
8399 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8400 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8401 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8402 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8403 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8405 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8407 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
8409 checkFullyDefined();
8410 int mdim=getMeshDimension();
8411 int spaceDim=getSpaceDimension();
8413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8414 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8415 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8416 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
8417 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8418 ret->setCoords(getCoords());
8419 ret->allocateCells((int)partition.size());
8421 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8423 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
8428 cell=tmp->buildUnionOf2DMesh();
8431 cell=tmp->buildUnionOf3DMesh();
8434 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8437 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
8440 ret->finishInsertingCells();
8445 * This method partitions \b this into contiguous zone.
8446 * This method only needs a well defined connectivity. Coordinates are not considered here.
8447 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8449 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
8452 int nbOfCellsCur=getNumberOfCells();
8453 std::vector<DataArrayInt *> ret;
8456 DataArrayInt *neigh=0,*neighI=0;
8457 computeNeighborsOfCells(neigh,neighI);
8458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8459 std::vector<bool> fetchedCells(nbOfCellsCur,false);
8460 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8462 while(seed<nbOfCellsCur)
8464 int nbOfPeelPerformed=0;
8465 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
8466 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8468 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8469 ret.push_back((*it).retn());
8473 int nbOfCellsCur=getNumberOfCells();
8474 DataArrayInt *neigh=0,*neighI=0;
8475 computeNeighborsOfCells(neigh,neighI);
8476 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
8478 std::vector<DataArrayInt *> ret;
8479 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8480 while(nbOfCellsCur>0)
8482 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
8483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
8484 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
8485 ret2.push_back(tmp2); ret.push_back(tmp2);
8486 nbOfCellsCur=tmp3->getNumberOfTuples();
8489 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
8490 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
8493 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
8494 neighAuto->transformWithIndArr(renum->begin(),renum->end());
8497 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
8504 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8505 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8507 * \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.
8508 * \return a newly allocated DataArrayInt to be managed by the caller.
8509 * \throw In case of \a code has not the right format (typically of size 3*n)
8511 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
8513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
8514 std::size_t nb=code.size()/3;
8515 if(code.size()%3!=0)
8516 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8517 ret->alloc((int)nb,2);
8518 int *retPtr=ret->getPointer();
8519 for(std::size_t i=0;i<nb;i++,retPtr+=2)
8521 retPtr[0]=code[3*i+2];
8522 retPtr[1]=code[3*i+2]+code[3*i+1];
8527 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8528 _own_cell(true),_cell_id(-1),_nb_cell(0)
8533 _nb_cell=mesh->getNumberOfCells();
8537 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8545 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8546 _own_cell(false),_cell_id(bg-1),
8553 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8556 if(_cell_id<_nb_cell)
8565 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8571 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8573 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8576 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8582 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8590 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8596 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8601 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8606 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8608 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8611 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8616 _nb_cell=mesh->getNumberOfCells();
8620 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8627 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8629 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
8630 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
8631 if(_cell_id<_nb_cell)
8633 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8634 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
8635 int startId=_cell_id;
8636 _cell_id+=nbOfElems;
8637 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8643 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8647 _conn=mesh->getNodalConnectivity()->getPointer();
8648 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8652 void MEDCouplingUMeshCell::next()
8654 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8659 _conn_lgth=_conn_indx[1]-_conn_indx[0];
8662 std::string MEDCouplingUMeshCell::repr() const
8664 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8666 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8668 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8672 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8675 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8677 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8678 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8680 return INTERP_KERNEL::NORM_ERROR;
8683 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8686 if(_conn_lgth!=NOTICABLE_FIRST_VAL)