1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
29 #include "SplitterTetra.hxx"
30 #include "DirectedBoundingBox.hxx"
31 #include "InterpKernelMeshQuality.hxx"
32 #include "InterpKernelCellSimplify.hxx"
33 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
34 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
35 #include "InterpKernelAutoPtr.hxx"
36 #include "InterpKernelGeo2DNode.hxx"
37 #include "InterpKernelGeo2DEdgeLin.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
48 using namespace ParaMEDMEM;
50 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
54 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 return new MEDCouplingUMesh;
59 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
62 ret->setName(meshName);
63 ret->setMeshDimension(meshDim);
67 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
72 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
74 return new MEDCouplingUMesh(*this,recDeepCpy);
77 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
81 ret+=_nodal_connec->getHeapMemorySize();
82 if(_nodal_connec_index)
83 ret+=_nodal_connec_index->getHeapMemorySize();
84 return MEDCouplingPointSet::getHeapMemorySize()+ret;
87 void MEDCouplingUMesh::updateTime() const
89 MEDCouplingPointSet::updateTime();
92 updateTimeWith(*_nodal_connec);
94 if(_nodal_connec_index)
96 updateTimeWith(*_nodal_connec_index);
100 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
105 * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity.
106 * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be
107 * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check
108 * that all is in order in 'this'.
110 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
113 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
115 MEDCouplingPointSet::checkCoherency();
116 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
118 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
120 std::ostringstream message;
121 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
122 throw INTERP_KERNEL::Exception(message.str().c_str());
127 if(_nodal_connec->getNumberOfComponents()!=1)
128 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
129 if(_nodal_connec->getInfoOnComponent(0)!="")
130 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
132 if(_nodal_connec_index)
134 if(_nodal_connec_index->getNumberOfComponents()!=1)
135 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
136 if(_nodal_connec_index->getInfoOnComponent(0)!="")
137 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
142 * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does.
143 * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids.
144 * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2.
146 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
151 int meshDim=getMeshDimension();
152 int nbOfNodes=getNumberOfNodes();
153 int nbOfCells=getNumberOfCells();
154 const int *ptr=_nodal_connec->getConstPointer();
155 const int *ptrI=_nodal_connec_index->getConstPointer();
156 for(int i=0;i<nbOfCells;i++)
158 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
159 if((int)cm.getDimension()!=meshDim)
161 std::ostringstream oss;
162 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
163 throw INTERP_KERNEL::Exception(oss.str().c_str());
165 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
167 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
169 std::ostringstream oss;
170 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
171 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
172 throw INTERP_KERNEL::Exception(oss.str().c_str());
174 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
179 if(nodeId>=nbOfNodes)
181 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
182 throw INTERP_KERNEL::Exception(oss.str().c_str());
187 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
188 throw INTERP_KERNEL::Exception(oss.str().c_str());
192 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
194 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
195 throw INTERP_KERNEL::Exception(oss.str().c_str());
202 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
204 checkCoherency1(eps);
207 void MEDCouplingUMesh::setMeshDimension(int meshDim)
210 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 !");
215 void MEDCouplingUMesh::allocateCells(int nbOfCells)
217 if(_nodal_connec_index)
219 _nodal_connec_index->decrRef();
223 _nodal_connec->decrRef();
225 _nodal_connec_index=DataArrayInt::New();
226 _nodal_connec_index->reserve(nbOfCells+1);
227 _nodal_connec_index->pushBackSilent(0);
228 _nodal_connec=DataArrayInt::New();
229 _nodal_connec->reserve(2*nbOfCells);
235 * Appends a cell in connectivity array.
236 * @param type type of cell to add.
237 * @param size number of nodes constituting this cell.
238 * @param nodalConnOfCell the connectivity of the cell to add.
240 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
242 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
243 if(_nodal_connec_index==0)
244 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
245 if((int)cm.getDimension()==_mesh_dim)
248 if(size!=(int)cm.getNumberOfNodes())
250 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
251 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
252 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 int idx=_nodal_connec_index->back();
256 _nodal_connec_index->pushBackSilent(val);
257 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
262 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
263 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
264 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
265 throw INTERP_KERNEL::Exception(oss.str().c_str());
270 * Method to be called to cloture the insertion of cells using this->insertNextCell.
272 void MEDCouplingUMesh::finishInsertingCells()
274 _nodal_connec->pack();
275 _nodal_connec_index->pack();
276 _nodal_connec->declareAsNew();
277 _nodal_connec_index->declareAsNew();
282 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
283 * Useful for python users.
285 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
287 return new MEDCouplingUMeshCellIterator(this);
291 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
292 * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
293 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
294 * Useful for python users.
296 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
298 if(!checkConsecutiveCellTypes())
299 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
300 return new MEDCouplingUMeshCellByTypeEntry(this);
303 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
309 * This method is a method that compares 'this' and 'other'.
310 * This method compares \b all attributes, even names and component names.
312 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
315 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
316 std::ostringstream oss; oss.precision(15);
317 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
320 reason="mesh given in input is not castable in MEDCouplingUMesh !";
323 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
325 if(_mesh_dim!=otherC->_mesh_dim)
327 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
331 if(_types!=otherC->_types)
333 oss << "umesh geometric type mismatch :\nThis geometric types are :";
334 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
335 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
336 oss << "\nOther geometric types are :";
337 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
338 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
342 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
343 if(_nodal_connec==0 || otherC->_nodal_connec==0)
345 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
348 if(_nodal_connec!=otherC->_nodal_connec)
349 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
351 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
354 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
355 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
357 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
360 if(_nodal_connec_index!=otherC->_nodal_connec_index)
361 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
363 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
369 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
371 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
374 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
376 if(_mesh_dim!=otherC->_mesh_dim)
378 if(_types!=otherC->_types)
380 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
381 if(_nodal_connec==0 || otherC->_nodal_connec==0)
383 if(_nodal_connec!=otherC->_nodal_connec)
384 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
386 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
387 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
389 if(_nodal_connec_index!=otherC->_nodal_connec_index)
390 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
396 * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
397 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
399 * In case of success cellCor and nodeCor are informed both.
400 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
401 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
402 * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
404 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
405 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
407 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
409 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
410 MEDCouplingMesh::checkFastEquivalWith(other,prec);
411 if(_types!=otherC->_types)
412 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
413 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
416 int oldNbOfNodes=getNumberOfNodes();
417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
420 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
421 const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
422 if(pt!=da->getConstPointer()+da->getNbOfElems())
423 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
424 m->renumberNodes(da->getConstPointer(),newNbOfNodes);
426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
427 da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
430 da=m->zipConnectivityTraducer(cellCompPol);
431 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
432 pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
433 if(pt!=da->getConstPointer()+da->getNbOfElems())
434 throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
435 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
436 nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
437 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
441 * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
442 * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
443 * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
444 * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception !
446 * In case of success cellCor are informed both.
447 * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
448 * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
450 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
451 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
453 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
455 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
456 MEDCouplingMesh::checkFastEquivalWith(other,prec);
457 if(_types!=otherC->_types)
458 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
459 if(_coords!=otherC->_coords)
460 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
461 std::vector<const MEDCouplingUMesh *> ms(2);
464 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
466 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
467 const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
468 if(pt!=da->getConstPointer()+da->getNbOfElems())
470 throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
473 cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
477 * This method checks fastly that 'this' and 'other' are equal.
479 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
481 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
483 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
484 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
485 int nbOfCells=getNumberOfCells();
489 status&=areCellsFrom2MeshEqual(otherC,0,prec);
490 status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
491 status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
493 throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
497 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
498 * For speed reasons no check of this will be done.
500 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
503 int nbOfNodes=getNumberOfNodes();
504 int *revNodalIndxPtr=new int[nbOfNodes+1];
505 revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
506 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
507 const int *conn=_nodal_connec->getConstPointer();
508 const int *connIndex=_nodal_connec_index->getConstPointer();
509 int nbOfCells=getNumberOfCells();
510 int nbOfEltsInRevNodal=0;
511 for(int eltId=0;eltId<nbOfCells;eltId++)
513 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
514 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
515 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
516 if(*iter>=0)//for polyhedrons
518 nbOfEltsInRevNodal++;
519 revNodalIndxPtr[(*iter)+1]++;
522 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
523 int *revNodalPtr=new int[nbOfEltsInRevNodal];
524 revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
525 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
526 for(int eltId=0;eltId<nbOfCells;eltId++)
528 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
529 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
530 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
531 if(*iter>=0)//for polyhedrons
532 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
538 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
543 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
549 if(cm.getOrientationStatus(nb,conn1,conn2))
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 MinusTwoSonsGenerator
570 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
571 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
572 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
573 static const int DELTA=2;
575 const INTERP_KERNEL::CellModel& _cm;
581 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
582 * For speed reasons no check of this will be done.
583 * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
584 * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
585 * The algorithm to compute this p-1 mesh is the following :
586 * For each cell in 'this' it splits into p-1 elements.
587 * If this p-1 element does not already exists it is appended to the returned mesh
588 * If this p-1 element already exists, it is not appended.
589 * This method returns or 4 arrays plus the returned mesh.
590 * '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.
591 * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
593 * 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.
594 * 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])
596 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
597 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
599 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
601 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
605 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
606 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
607 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
608 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
609 * \sa MEDCouplingUMesh::buildDescendingConnectivity
611 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
614 if(getMeshDimension()!=3)
615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
616 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
620 * WARNING this method do the assumption that connectivity lies on the coordinates set.
621 * For speed reasons no check of this will be done.
622 * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
623 * 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,
624 * 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
625 * an array in relative "FORTRAN" mode.
627 * \warning This method returns a mesh whose geometric type order in are \b not sorted.
628 * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
630 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
632 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
636 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
637 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
638 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
639 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
641 * \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
642 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
643 * \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.
645 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
648 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
651 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
653 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
657 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
658 * 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,
659 * excluding a set of meshdim-1 cells in input descending connectivity.
660 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
661 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
662 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
664 * \param [in] desc descending connectivity array.
665 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
666 * \param [in] revDesc reverse descending connectivity array.
667 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
668 * \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
669 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
670 * \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.
672 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
673 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
675 if(!desc || !descIndx || !revDesc || !revDescIndx)
676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
677 const int *descPtr=desc->getConstPointer();
678 const int *descIPtr=descIndx->getConstPointer();
679 const int *revDescPtr=revDesc->getConstPointer();
680 const int *revDescIPtr=revDescIndx->getConstPointer();
682 int nbCells=descIndx->getNumberOfTuples()-1;
683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
685 int *out1Ptr=out1->getPointer();
687 out0->reserve(desc->getNumberOfTuples());
688 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
690 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
692 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
694 out0->insertAtTheEnd(s.begin(),s.end());
696 *out1Ptr=out0->getNumberOfTuples();
698 neighbors=out0.retn();
699 neighborsIndx=out1.retn();
705 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
706 * For speed reasons no check of this will be done.
708 template<class SonsGenerator>
709 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
711 checkConnectivityFullyDefined();
712 int nbOfCells=getNumberOfCells();
713 int nbOfNodes=getNumberOfNodes();
714 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
715 int *revNodalIndxPtr=revNodalIndx->getPointer();
716 const int *conn=_nodal_connec->getConstPointer();
717 const int *connIndex=_nodal_connec_index->getConstPointer();
718 std::string name="Mesh constituent of "; name+=getName();
719 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
720 ret->setCoords(getCoords());
721 ret->allocateCells(2*nbOfCells);
722 descIndx->alloc(nbOfCells+1,1);
723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
724 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
725 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
727 int pos=connIndex[eltId];
728 int posP1=connIndex[eltId+1];
729 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
730 SonsGenerator sg(cm);
731 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
732 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
733 for(unsigned i=0;i<nbOfSons;i++)
735 INTERP_KERNEL::NormalizedCellType cmsId;
736 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
737 for(unsigned k=0;k<nbOfNodesSon;k++)
739 revNodalIndxPtr[tmp[k]+1]++;
740 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
741 revDesc2->pushBackSilent(eltId);
743 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
745 int nbOfCellsM1=ret->getNumberOfCells();
746 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
747 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
748 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
749 int *revNodalPtr=revNodal->getPointer();
750 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
751 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
752 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
754 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
755 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
756 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
757 if(*iter>=0)//for polyhedrons
758 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
761 DataArrayInt *commonCells=0,*commonCellsI=0;
762 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
764 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
765 int newNbOfCellsM1=-1;
766 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
767 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
768 std::vector<bool> isImpacted(nbOfCellsM1,false);
769 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
770 for(int work2=work[0];work2!=work[1];work2++)
771 isImpacted[commonCellsPtr[work2]]=true;
772 const int *o2nM1Ptr=o2nM1->getConstPointer();
773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
774 const int *n2oM1Ptr=n2oM1->getConstPointer();
775 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
776 ret2->copyTinyInfoFrom(this);
777 desc->alloc(descIndx->back(),1);
778 int *descPtr=desc->getPointer();
779 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
780 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
783 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
786 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
788 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
789 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
792 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
795 revDesc->reserve(newNbOfCellsM1);
796 revDescIndx->alloc(newNbOfCellsM1+1,1);
797 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
798 const int *revDesc2Ptr=revDesc2->getConstPointer();
799 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
801 int oldCellIdM1=n2oM1Ptr[i];
802 if(!isImpacted[oldCellIdM1])
804 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
805 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
809 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
810 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
811 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
819 struct MEDCouplingAccVisit
821 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
822 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
823 int _new_nb_of_nodes;
830 * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
831 * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
832 * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
833 * If mesh dimension is not in [2,3] an exception is thrown.
834 * Of course pay attention that the resulting mesh is slower than previous one.
835 * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
836 * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
837 * If mesh==3, after throw the mesh is \b unconsistent !
838 * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
840 * \warning This method modifies can modify significantly the geometric type order in \a this.
841 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
843 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
846 int dim=getMeshDimension();
848 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
849 int nbOfCells=getNumberOfCells();
852 const int *connIndex=_nodal_connec_index->getConstPointer();
853 int *conn=_nodal_connec->getPointer();
854 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
856 if(*iter>=0 && *iter<nbOfCells)
858 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
860 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
862 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
866 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
867 oss << " in range [0," << nbOfCells << ") !";
868 throw INTERP_KERNEL::Exception(oss.str().c_str());
874 int *connIndex=_nodal_connec_index->getPointer();
875 int connIndexLgth=_nodal_connec_index->getNbOfElems();
876 const int *connOld=_nodal_connec->getConstPointer();
877 int connOldLgth=_nodal_connec->getNbOfElems();
878 std::vector<int> connNew(connOld,connOld+connOldLgth);
879 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
881 if(*iter>=0 && *iter<nbOfCells)
883 int pos=connIndex[*iter];
884 int posP1=connIndex[(*iter)+1];
885 int lgthOld=posP1-pos-1;
886 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
887 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
888 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
889 int *tmp=new int[nbOfFaces*lgthOld];
891 for(int j=0;j<(int)nbOfFaces;j++)
893 INTERP_KERNEL::NormalizedCellType type;
894 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
898 std::size_t newLgth=std::distance(tmp,work)-1;
899 std::size_t delta=newLgth-lgthOld;
900 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
901 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
902 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
907 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
908 oss << " in range [0," << nbOfCells << ") !";
909 throw INTERP_KERNEL::Exception(oss.str().c_str());
912 _nodal_connec->alloc((int)connNew.size(),1);
913 int *newConnPtr=_nodal_connec->getPointer();
914 std::copy(connNew.begin(),connNew.end(),newConnPtr);
920 * This method converts all cells into poly type if possible.
921 * This method is purely for userfriendliness.
922 * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
924 void MEDCouplingUMesh::convertAllToPoly()
926 int nbOfCells=getNumberOfCells();
927 std::vector<int> cellIds(nbOfCells);
928 for(int i=0;i<nbOfCells;i++)
930 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
934 * 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.
935 * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
936 * 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
937 * each 2 faces hidden in the single face of polyhedron).
938 * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
939 * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
940 * 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'
942 * This method is usefull only for users that wants to build extruded unstructured mesh.
943 * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
944 * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
946 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
949 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
950 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
951 int nbOfCells=getNumberOfCells();
952 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
953 newCi->alloc(nbOfCells+1,1);
954 int *newci=newCi->getPointer();
955 const int *ci=_nodal_connec_index->getConstPointer();
956 const int *c=_nodal_connec->getConstPointer();
958 for(int i=0;i<nbOfCells;i++)
960 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
961 if(type==INTERP_KERNEL::NORM_POLYHED)
963 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
965 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
966 throw INTERP_KERNEL::Exception(oss.str().c_str());
968 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
971 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 !";
972 throw INTERP_KERNEL::Exception(oss.str().c_str());
975 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)
978 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
981 newC->alloc(newci[nbOfCells],1);
982 int *newc=newC->getPointer();
983 for(int i=0;i<nbOfCells;i++)
985 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
986 if(type==INTERP_KERNEL::NORM_POLYHED)
988 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
989 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
991 for(std::size_t j=0;j<n1;j++)
993 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
995 newc[n1+5*j+1]=c[ci[i]+1+j];
996 newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
997 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
998 newc[n1+5*j+4]=c[ci[i]+1+j+n1];
1003 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1005 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1006 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1010 * This method is the opposite of ParaMEDMEM::MEDCouplingUMesh::convertToPolyTypes method.
1011 * The aim is to take all polygons or polyhedrons cell and to try to traduce them into classical cells.
1013 * \return If true at least one cell has been unpolyzed.
1014 \n If false has been returned the nodal connectivity of \a this has **not** been altered and \a this has remains unchanged.
1016 * \warning This method modifies can modify significantly the geometric type order in \a this.
1017 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1019 bool MEDCouplingUMesh::unPolyze()
1021 checkFullyDefined();
1022 int mdim=getMeshDimension();
1024 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1027 int nbOfCells=getNumberOfCells();
1030 int initMeshLgth=getMeshLength();
1031 int *conn=_nodal_connec->getPointer();
1032 int *index=_nodal_connec_index->getPointer();
1037 for(int i=0;i<nbOfCells;i++)
1039 lgthOfCurCell=index[i+1]-posOfCurCell;
1040 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1041 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1042 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1046 switch(cm.getDimension())
1050 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1051 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1052 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1057 int nbOfFaces,lgthOfPolyhConn;
1058 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1059 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1064 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1068 ret=ret || (newType!=type);
1069 conn[newPos]=newType;
1071 posOfCurCell=index[i+1];
1076 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1077 newPos+=lgthOfCurCell;
1078 posOfCurCell+=lgthOfCurCell;
1082 if(newPos!=initMeshLgth)
1083 _nodal_connec->reAlloc(newPos);
1090 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1091 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1092 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1094 * \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
1097 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1099 checkFullyDefined();
1100 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1101 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1102 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1103 coords->recenterForMaxPrecision(eps);
1105 int nbOfCells=getNumberOfCells();
1106 const int *conn=_nodal_connec->getConstPointer();
1107 const int *index=_nodal_connec_index->getConstPointer();
1108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1109 connINew->alloc(nbOfCells+1,1);
1110 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1113 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1115 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1117 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1121 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1122 *connINewPtr=connNew->getNumberOfTuples();
1125 setConnectivity(connNew,connINew,false);
1129 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1130 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1131 * the format of returned DataArrayInt instance.
1133 * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1134 * \sa MEDCouplingUMesh::getNodeIdsInUse
1136 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1138 checkConnectivityFullyDefined();
1139 int nbOfCells=getNumberOfCells();
1140 const int *connIndex=_nodal_connec_index->getConstPointer();
1141 const int *conn=_nodal_connec->getConstPointer();
1142 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1143 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1144 std::vector<bool> retS(maxElt,false);
1145 for(int i=0;i<nbOfCells;i++)
1146 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1150 for(int i=0;i<maxElt;i++)
1153 DataArrayInt *ret=DataArrayInt::New();
1155 int *retPtr=ret->getPointer();
1156 for(int i=0;i<maxElt;i++)
1163 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1164 * \sa MEDCouplingUMesh::getNodeIdsInUse
1166 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1168 int nbOfNodes=(int)nodeIdsInUse.size();
1169 int nbOfCells=getNumberOfCells();
1170 const int *connIndex=_nodal_connec_index->getConstPointer();
1171 const int *conn=_nodal_connec->getConstPointer();
1172 for(int i=0;i<nbOfCells;i++)
1173 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1176 if(conn[j]<nbOfNodes)
1177 nodeIdsInUse[conn[j]]=true;
1180 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1181 throw INTERP_KERNEL::Exception(oss.str().c_str());
1187 * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
1188 * The returned array is newly created and should be dealt by the caller.
1189 * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
1190 * The size of returned array is the number of nodes of 'this'.
1191 * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
1192 * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
1193 * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
1194 * \throw if a cell contains in its nodal connectivity a node id >= nb of nodes an exception will be thrown.
1195 * \sa MEDCouplingUMesh::computeNodeIdsAlg
1197 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1200 int nbOfNodes=getNumberOfNodes();
1201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1202 ret->alloc(nbOfNodes,1);
1203 int *traducer=ret->getPointer();
1204 std::fill(traducer,traducer+nbOfNodes,-1);
1205 int nbOfCells=getNumberOfCells();
1206 const int *connIndex=_nodal_connec_index->getConstPointer();
1207 const int *conn=_nodal_connec->getConstPointer();
1208 for(int i=0;i<nbOfCells;i++)
1209 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1212 if(conn[j]<nbOfNodes)
1213 traducer[conn[j]]=1;
1216 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1217 throw INTERP_KERNEL::Exception(oss.str().c_str());
1220 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1221 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1226 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1227 * For each cell in \b this the number of nodes constituting cell is computed.
1228 * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1229 * For polyhedrons, the face separation (-1) are excluded from the couting.
1231 * \return a newly allocated array
1233 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1235 checkConnectivityFullyDefined();
1236 int nbOfCells=getNumberOfCells();
1237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1238 ret->alloc(nbOfCells,1);
1239 int *retPtr=ret->getPointer();
1240 const int *conn=getNodalConnectivity()->getConstPointer();
1241 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1242 for(int i=0;i<nbOfCells;i++,retPtr++)
1244 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1245 *retPtr=connI[i+1]-connI[i]-1;
1247 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1253 * 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.
1254 * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
1255 * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
1256 * -1 values in returned array means that the corresponding old node is no more used.
1258 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1260 int newNbOfNodes=-1;
1261 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1262 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1267 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1268 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1270 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1275 return AreCellsEqual0(conn,connI,cell1,cell2);
1277 return AreCellsEqual1(conn,connI,cell1,cell2);
1279 return AreCellsEqual2(conn,connI,cell1,cell2);
1281 return AreCellsEqual3(conn,connI,cell1,cell2);
1283 return AreCellsEqual7(conn,connI,cell1,cell2);
1285 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2 or 3.");
1289 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1291 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1293 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1294 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1299 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1301 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1303 int sz=connI[cell1+1]-connI[cell1];
1304 if(sz==connI[cell2+1]-connI[cell2])
1306 if(conn[connI[cell1]]==conn[connI[cell2]])
1308 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1309 unsigned dim=cm.getDimension();
1315 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1316 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1317 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1318 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1319 return work!=tmp+sz1?1:0;
1322 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1332 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1334 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1336 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1338 if(conn[connI[cell1]]==conn[connI[cell2]])
1340 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1341 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1349 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1351 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1353 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1355 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1356 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1363 * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1365 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1367 int sz=connI[cell1+1]-connI[cell1];
1368 if(sz==connI[cell2+1]-connI[cell2])
1370 if(conn[connI[cell1]]==conn[connI[cell2]])
1372 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1373 unsigned dim=cm.getDimension();
1379 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1380 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1381 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1382 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1387 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1388 std::reverse_iterator<int *> it2((int *)tmp);
1389 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1395 return work!=tmp+sz1?1:0;
1398 {//case of SEG2 and SEG3
1399 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1401 if(!cm.isQuadratic())
1403 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1404 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1405 if(std::equal(it1,it2,conn+connI[cell2]+1))
1411 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])
1418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1426 * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1427 * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1429 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1431 if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1433 std::vector<int> c1,c2;
1434 getNodeIdsOfCell(cellId,c1);
1435 other->getNodeIdsOfCell(cellId,c2);
1436 std::size_t sz=c1.size();
1439 for(std::size_t i=0;i<sz;i++)
1441 std::vector<double> n1,n2;
1442 getCoordinatesOfNode(c1[0],n1);
1443 other->getCoordinatesOfNode(c2[0],n2);
1444 std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1445 std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1446 if(*std::max_element(n1.begin(),n1.end())>prec)
1453 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1454 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1455 * and result remains unchanged.
1456 * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1457 * If in 'candidates' pool -1 value is considered as an empty value.
1458 * WARNING this method returns only ONE set of result !
1460 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1462 if(candidates.size()<1)
1465 std::vector<int>::const_iterator iter=candidates.begin();
1466 int start=(*iter++);
1467 for(;iter!=candidates.end();iter++)
1469 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1474 result->pushBackSilent(start);
1478 result->pushBackSilent(*iter);
1480 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1487 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1488 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1490 * \param [in] compType input specifying the technique used to compare cells each other.
1491 * - 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.
1492 * - 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)
1493 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1494 * - 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
1495 * can be used for users not sensitive to orientation of cell
1496 * \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.
1497 * \param [out] commonCells
1498 * \param [out] commonCellsI
1499 * \return the correspondance array old to new in a newly allocated array.
1502 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1504 checkConnectivityFullyDefined();
1505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1506 getReverseNodalConnectivity(revNodal,revNodalI);
1507 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1510 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1511 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1514 int nbOfCells=nodalI->getNumberOfTuples()-1;
1515 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1516 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1517 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1518 std::vector<bool> isFetched(nbOfCells,false);
1521 for(int i=0;i<nbOfCells;i++)
1525 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1526 std::vector<int> v,v2;
1527 if(connOfNode!=connPtr+connIPtr[i+1])
1529 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1530 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1533 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1537 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1538 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1539 v2.resize(std::distance(v2.begin(),it));
1543 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1545 int pos=commonCellsI->back();
1546 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1547 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1548 isFetched[*it]=true;
1556 for(int i=startCellId;i<nbOfCells;i++)
1560 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1561 std::vector<int> v,v2;
1562 if(connOfNode!=connPtr+connIPtr[i+1])
1564 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1567 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1571 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1572 v2.resize(std::distance(v2.begin(),it));
1576 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1578 int pos=commonCellsI->back();
1579 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1580 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1581 isFetched[*it]=true;
1587 commonCellsArr=commonCells.retn();
1588 commonCellsIArr=commonCellsI.retn();
1592 * 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.
1593 * This method keeps the coordiantes of \a this.
1595 * \param [in] compType input specifying the technique used to compare cells each other.
1596 * - 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.
1597 * - 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)
1598 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1599 * - 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
1600 * can be used for users not sensitive to orientation of cell
1601 * \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
1602 * \return the correspondance array old to new in a newly allocated array.
1604 * \warning This method modifies can modify significantly the geometric type order in \a this.
1605 * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1607 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1609 DataArrayInt *commonCells=0,*commonCellsI=0;
1610 findCommonCells(compType,startCellId,commonCells,commonCellsI);
1611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1612 int newNbOfCells=-1;
1613 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1614 commonCellsI->end(),newNbOfCells);
1615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1616 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1617 setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1622 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1623 * 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.
1624 * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
1625 * The main difference is that this method is not expected to throw exception.
1626 * This method has two outputs :
1628 * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
1629 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1630 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1632 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1635 int nbOfCells=getNumberOfCells();
1636 static const int possibleCompType[]={0,1,2};
1637 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1639 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1640 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1642 throw INTERP_KERNEL::Exception(oss.str().c_str());
1644 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1645 arr=o2n->substr(nbOfCells);
1646 arr->setName(other->getName());
1648 if(other->getNumberOfCells()==0)
1650 return arr->getMaxValue(tmp)<nbOfCells;
1654 * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1655 * This method tries to determine if \b other is fully included in \b this.
1656 * The main difference is that this method is not expected to throw exception.
1657 * This method has two outputs :
1659 * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1660 * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1662 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1664 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1665 DataArrayInt *commonCells=0,*commonCellsI=0;
1666 int thisNbCells=getNumberOfCells();
1667 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1669 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1670 int otherNbCells=other->getNumberOfCells();
1671 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1672 arr2->alloc(otherNbCells,1);
1673 arr2->fillWithZero();
1674 int *arr2Ptr=arr2->getPointer();
1675 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1676 for(int i=0;i<nbOfCommon;i++)
1678 int start=commonCellsPtr[commonCellsIPtr[i]];
1679 if(start<thisNbCells)
1681 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1683 int sig=commonCellsPtr[j]>0?1:-1;
1684 int val=std::abs(commonCellsPtr[j])-1;
1685 if(val>=thisNbCells)
1686 arr2Ptr[val-thisNbCells]=sig*(start+1);
1690 arr2->setName(other->getName());
1691 if(arr2->presenceOfValue(0))
1698 * @param areNodesMerged if at least two nodes have been merged.
1699 * @return old to new node correspondance.
1701 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1703 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1705 renumberNodes(ret->getConstPointer(),newNbOfNodes);
1710 * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
1712 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1714 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1716 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1721 * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
1722 * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
1723 * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
1724 * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
1726 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
1728 const DataArrayDouble *coords=other.getCoords();
1730 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
1732 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1733 int otherNbOfNodes=other.getNumberOfNodes();
1734 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1736 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1737 setCoords(newCoords);
1738 bool areNodesMerged;
1740 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1743 setCoords(oldCoords);
1744 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1746 int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1747 const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1748 if(pt!=da->getConstPointer()+da->getNbOfElems())
1750 setCoords(oldCoords);
1751 throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1753 setCoords(oldCoords);
1754 renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1759 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1760 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1761 * cellIds is not given explicitely but by a range python like.
1763 * \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.
1764 * \return a newly allocated
1766 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1767 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1769 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1771 if(getMeshDimension()!=-1)
1773 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
1780 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1782 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1784 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1786 return const_cast<MEDCouplingUMesh *>(this);
1791 * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
1792 * @param begin begin of array containing the cell ids to keep.
1793 * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
1794 * @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.
1796 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1797 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1799 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1801 if(getMeshDimension()!=-1)
1803 MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
1811 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1813 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1815 return const_cast<MEDCouplingUMesh *>(this);
1820 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1822 * 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.
1823 * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1824 * The number of cells of \b this will remain the same with this method.
1826 * \param [in] begin begin of cell ids (included) of cells in this to assign
1827 * \param [in] end end of cell ids (excluded) of cells in this to assign
1828 * \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).
1829 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1831 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1833 checkConnectivityFullyDefined();
1834 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1835 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1836 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1837 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1839 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1840 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1841 throw INTERP_KERNEL::Exception(oss.str().c_str());
1843 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1844 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1846 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1847 throw INTERP_KERNEL::Exception(oss.str().c_str());
1849 int nbOfCells=getNumberOfCells();
1850 bool easyAssign=true;
1851 const int *connI=_nodal_connec_index->getConstPointer();
1852 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1853 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1855 if(*it>=0 && *it<nbOfCells)
1857 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1861 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1862 throw INTERP_KERNEL::Exception(oss.str().c_str());
1867 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1872 DataArrayInt *arrOut=0,*arrIOut=0;
1873 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1876 setConnectivity(arrOut,arrIOut,true);
1880 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1882 checkConnectivityFullyDefined();
1883 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1884 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1886 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1888 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1889 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1890 throw INTERP_KERNEL::Exception(oss.str().c_str());
1892 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1893 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1895 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1896 throw INTERP_KERNEL::Exception(oss.str().c_str());
1898 int nbOfCells=getNumberOfCells();
1899 bool easyAssign=true;
1900 const int *connI=_nodal_connec_index->getConstPointer();
1901 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1903 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1905 if(it>=0 && it<nbOfCells)
1907 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1911 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1912 throw INTERP_KERNEL::Exception(oss.str().c_str());
1917 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1922 DataArrayInt *arrOut=0,*arrIOut=0;
1923 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1926 setConnectivity(arrOut,arrIOut,true);
1930 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1932 DataArrayInt *cellIdsKept=0;
1933 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
1934 cellIdsKept->setName(getName());
1939 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1940 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
1941 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1942 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1944 * \param [in] begin input start of array of node ids.
1945 * \param [in] end input end of array of node ids.
1946 * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
1947 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
1949 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
1951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
1952 checkConnectivityFullyDefined();
1954 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
1955 std::vector<bool> fastFinder(sz,false);
1956 for(const int *work=begin;work!=end;work++)
1957 if(*work>=0 && *work<sz)
1958 fastFinder[*work]=true;
1959 int nbOfCells=getNumberOfCells();
1960 const int *conn=getNodalConnectivity()->getConstPointer();
1961 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
1962 for(int i=0;i<nbOfCells;i++)
1964 int ref=0,nbOfHit=0;
1965 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
1969 if(fastFinder[*work2])
1972 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
1973 cellIdsKept->pushBackSilent(i);
1975 cellIdsKeptArr=cellIdsKept.retn();
1979 * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
1981 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1983 DataArrayInt *cellIdsKept=0;
1984 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1985 cellIdsKept->setName(getName());
1990 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1991 * The return newly allocated mesh will share the same coordinates as 'this'.
1992 * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1993 * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1995 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
1997 DataArrayInt *cellIdsKept=0;
1998 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2000 return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2004 * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
2005 * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
2006 * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
2007 * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
2009 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2012 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2013 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2014 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2015 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2019 * This method returns a mesh with meshDim=this->getMeshDimension()-1.
2020 * This returned mesh contains cells that are linked with one and only one cell of this.
2021 * @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.
2022 * @return mesh with ref counter equal to 1.
2024 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2026 DataArrayInt *desc=DataArrayInt::New();
2027 DataArrayInt *descIndx=DataArrayInt::New();
2028 DataArrayInt *revDesc=DataArrayInt::New();
2029 DataArrayInt *revDescIndx=DataArrayInt::New();
2031 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2034 descIndx->decrRef();
2035 int nbOfCells=meshDM1->getNumberOfCells();
2036 const int *revDescIndxC=revDescIndx->getConstPointer();
2037 std::vector<int> boundaryCells;
2038 for(int i=0;i<nbOfCells;i++)
2039 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2040 boundaryCells.push_back(i);
2041 revDescIndx->decrRef();
2042 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2047 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2048 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2049 * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
2051 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2053 checkFullyDefined();
2054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2057 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2059 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2060 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2064 const int *revDescPtr=revDesc->getConstPointer();
2065 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2066 int nbOfCells=getNumberOfCells();
2067 std::vector<bool> ret1(nbOfCells,false);
2069 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2070 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2071 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2073 DataArrayInt *ret2=DataArrayInt::New();
2075 int *ret2Ptr=ret2->getPointer();
2077 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2080 ret2->setName("BoundaryCells");
2085 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2086 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2087 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2088 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2090 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2091 * This method method returns cells ids set s = s1 + s2 where :
2093 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2094 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2096 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2097 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2099 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2100 * \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
2101 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2103 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2105 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2106 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2107 checkConnectivityFullyDefined();
2108 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2109 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2110 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2113 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2115 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2116 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2117 DataArrayInt *idsOtherInConsti=0;
2118 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2121 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2123 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2124 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2127 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2128 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2129 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2130 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2131 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2132 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2133 neighThisPartAuto=0;
2134 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2135 const int li[2]={0,1};
2136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2137 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2141 cellIdsRk0=s0arr.retn();
2142 cellIdsRk1=s_renum1.retn();
2146 * 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
2147 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2149 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2151 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2153 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2154 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2155 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2156 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2158 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2159 revDesc=0; desc=0; descIndx=0;
2160 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2161 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2162 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2166 * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2167 * The returned nodes ids are those lying on the boundary of \b this.
2169 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2171 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2172 return skin->computeFetchedNodeIds();
2175 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2178 return const_cast<MEDCouplingUMesh *>(this);
2182 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2183 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2184 * This value is asked because often known by the caller of this method.
2185 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2187 * @param newNodeNumbers array specifying the new numbering in old2New convention.
2188 * @param newNbOfNodes the new number of nodes.
2190 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2192 MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2193 renumberNodesInConn(newNodeNumbers);
2197 * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2198 * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2199 * This value is asked because often known by the caller of this method.
2200 * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2201 * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2203 * @param newNodeNumbers array specifying the new numbering.
2204 * @param newNbOfNodes the new number of nodes.
2207 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2209 MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2210 renumberNodesInConn(newNodeNumbers);
2214 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2215 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2216 * 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.
2217 * 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.
2218 * 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.
2220 * \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
2221 * parameter is altered during the call.
2222 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2223 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2224 * \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.
2226 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2228 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2229 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2231 checkFullyDefined();
2232 otherDimM1OnSameCoords.checkFullyDefined();
2233 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2234 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2235 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2236 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2237 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2238 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2241 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2242 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2246 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2248 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2250 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2251 DataArrayInt *idsTmp=0;
2252 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2253 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2255 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2256 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2257 DataArrayInt *tmp0=0,*tmp1=0;
2258 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2263 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2264 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2266 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2267 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2268 nodeIdsToDuplicate=s3.retn();
2272 * This method operates a modification of the connectivity and coords in \b this.
2273 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2274 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2275 * 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
2276 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2277 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2279 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2281 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2282 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2284 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2286 int nbOfNodes=getNumberOfNodes();
2287 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2288 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2292 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2293 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2294 * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2295 * @param [in] newNodeNumbers in old2New convention
2297 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2299 checkConnectivityFullyDefined();
2300 int *conn=getNodalConnectivity()->getPointer();
2301 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2302 int nbOfCells=getNumberOfCells();
2303 for(int i=0;i<nbOfCells;i++)
2304 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2306 int& node=conn[iconn];
2307 if(node>=0)//avoid polyhedron separator
2309 node=newNodeNumbersO2N[node];
2312 _nodal_connec->declareAsNew();
2317 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2318 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2319 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2321 * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2323 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2325 checkConnectivityFullyDefined();
2326 int *conn=getNodalConnectivity()->getPointer();
2327 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2328 int nbOfCells=getNumberOfCells();
2329 for(int i=0;i<nbOfCells;i++)
2330 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2332 int& node=conn[iconn];
2333 if(node>=0)//avoid polyhedron separator
2338 _nodal_connec->declareAsNew();
2343 * This method operates a modification of the connectivity in \b this.
2344 * 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.
2345 * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
2346 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2347 * 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
2348 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2349 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2351 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2352 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2354 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2355 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2356 * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
2358 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2360 checkConnectivityFullyDefined();
2361 std::map<int,int> m;
2363 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2365 int *conn=getNodalConnectivity()->getPointer();
2366 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2367 int nbOfCells=getNumberOfCells();
2368 for(int i=0;i<nbOfCells;i++)
2369 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2371 int& node=conn[iconn];
2372 if(node>=0)//avoid polyhedron separator
2374 std::map<int,int>::iterator it=m.find(node);
2383 * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2385 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2386 * After the call of this method the number of cells remains the same as before.
2388 * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2389 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2390 * be strictly in [0;this->getNumberOfCells()).
2392 * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2393 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2394 * should be contained in[0;this->getNumberOfCells()).
2396 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2398 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2400 checkConnectivityFullyDefined();
2401 int nbCells=getNumberOfCells();
2402 const int *array=old2NewBg;
2404 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2406 const int *conn=_nodal_connec->getConstPointer();
2407 const int *connI=_nodal_connec_index->getConstPointer();
2408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2409 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2410 newConn->copyStringInfoFrom(*_nodal_connec);
2411 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2412 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2413 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2415 int *newC=newConn->getPointer();
2416 int *newCI=newConnI->getPointer();
2419 for(int i=0;i<nbCells;i++)
2421 std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2422 int nbOfElts=connI[pos+1]-connI[pos];
2423 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2428 setConnectivity(newConn,newConnI);
2430 delete [] const_cast<int *>(array);
2434 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2435 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2436 * added in 'elems' parameter.
2438 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2440 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2441 if(getMeshDimension()==-1)
2443 elems->pushBackSilent(0);
2444 return elems.retn();
2446 int dim=getSpaceDimension();
2447 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2448 const int* conn = getNodalConnectivity()->getConstPointer();
2449 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2450 const double* coords = getCoords()->getConstPointer();
2451 int nbOfCells=getNumberOfCells();
2452 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2454 for (int i=0; i<dim; i++)
2456 elem_bb[i*2]=std::numeric_limits<double>::max();
2457 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2460 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2462 int node= conn[inode];
2463 if(node>=0)//avoid polyhedron separator
2465 for (int idim=0; idim<dim; idim++)
2467 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2469 elem_bb[idim*2] = coords[node*dim+idim] ;
2471 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2473 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2478 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2479 elems->pushBackSilent(ielem);
2481 return elems.retn();
2485 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2486 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2487 * added in 'elems' parameter.
2489 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2491 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2492 if(getMeshDimension()==-1)
2494 elems->pushBackSilent(0);
2495 return elems.retn();
2497 int dim=getSpaceDimension();
2498 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2499 const int* conn = getNodalConnectivity()->getConstPointer();
2500 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2501 const double* coords = getCoords()->getConstPointer();
2502 int nbOfCells=getNumberOfCells();
2503 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2505 for (int i=0; i<dim; i++)
2507 elem_bb[i*2]=std::numeric_limits<double>::max();
2508 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2511 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2513 int node= conn[inode];
2514 if(node>=0)//avoid polyhedron separator
2516 for (int idim=0; idim<dim; idim++)
2518 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2520 elem_bb[idim*2] = coords[node*dim+idim] ;
2522 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2524 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2529 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2530 elems->pushBackSilent(ielem);
2532 return elems.retn();
2536 * Returns the cell type of cell with id 'cellId'.
2538 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2540 const int *ptI=_nodal_connec_index->getConstPointer();
2541 const int *pt=_nodal_connec->getConstPointer();
2542 if(cellId>=0 && cellId<_nodal_connec_index->getNbOfElems()-1)
2543 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2546 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2547 throw INTERP_KERNEL::Exception(oss.str().c_str());
2552 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2553 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2554 * The coordinates array is not considered here.
2556 * \param [in] type the geometric type
2557 * \return cell ids in this having geometric type \a type.
2559 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2564 checkConnectivityFullyDefined();
2565 int nbCells=getNumberOfCells();
2566 int mdim=getMeshDimension();
2567 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2568 if(mdim!=(int)cm.getDimension())
2569 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2570 const int *ptI=_nodal_connec_index->getConstPointer();
2571 const int *pt=_nodal_connec->getConstPointer();
2572 for(int i=0;i<nbCells;i++)
2574 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2575 ret->pushBackSilent(i);
2581 * Returns nb of cells having the geometric type 'type'.
2583 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2585 const int *ptI=_nodal_connec_index->getConstPointer();
2586 const int *pt=_nodal_connec->getConstPointer();
2587 int nbOfCells=getNumberOfCells();
2589 for(int i=0;i<nbOfCells;i++)
2590 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2596 * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2597 * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2598 * That is to say -1 separator is omitted in returned conn.
2600 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2602 const int *ptI=_nodal_connec_index->getConstPointer();
2603 const int *pt=_nodal_connec->getConstPointer();
2604 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2609 std::string MEDCouplingUMesh::simpleRepr() const
2611 static const char msg0[]="No coordinates specified !";
2612 std::ostringstream ret;
2613 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2614 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2616 double tt=getTime(tmpp1,tmpp2);
2617 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2618 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2619 ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2622 const int spaceDim=getSpaceDimension();
2623 ret << spaceDim << "\nInfo attached on space dimension : ";
2624 for(int i=0;i<spaceDim;i++)
2625 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2629 ret << msg0 << "\n";
2630 ret << "Number of nodes : ";
2632 ret << getNumberOfNodes() << "\n";
2634 ret << msg0 << "\n";
2635 ret << "Number of cells : ";
2636 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2637 ret << getNumberOfCells() << "\n";
2639 ret << "No connectivity specified !" << "\n";
2640 ret << "Cell types present : ";
2641 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2643 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2644 ret << cm.getRepr() << " ";
2650 std::string MEDCouplingUMesh::advancedRepr() const
2652 std::ostringstream ret;
2653 ret << simpleRepr();
2654 ret << "\nCoordinates array : \n___________________\n\n";
2656 _coords->reprWithoutNameStream(ret);
2658 ret << "No array set !\n";
2659 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2660 reprConnectivityOfThisLL(ret);
2665 * This method returns a C++ code that is a dump of \a this.
2666 * This method will throw if this is not fully defined.
2668 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2670 static const char coordsName[]="coords";
2671 static const char connName[]="conn";
2672 static const char connIName[]="connI";
2673 checkFullyDefined();
2674 std::ostringstream ret; ret << "// coordinates" << std::endl;
2675 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2676 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2677 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2678 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2679 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2680 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2681 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2685 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2687 std::ostringstream ret;
2688 reprConnectivityOfThisLL(ret);
2693 * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2694 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2695 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2698 * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2699 * 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
2700 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2702 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2704 int mdim=getMeshDimension();
2706 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2707 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2709 bool needToCpyCT=true;
2712 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2720 if(!_nodal_connec_index)
2722 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2727 tmp2=_nodal_connec_index;
2730 ret->setConnectivity(tmp1,tmp2,false);
2735 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2736 ret->setCoords(coords);
2739 ret->setCoords(_coords);
2743 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2745 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2747 int nbOfCells=getNumberOfCells();
2748 const int *c=_nodal_connec->getConstPointer();
2749 const int *ci=_nodal_connec_index->getConstPointer();
2750 for(int i=0;i<nbOfCells;i++)
2752 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2753 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2754 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2759 stream << "Connectivity not defined !\n";
2762 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2764 const int *ptI=_nodal_connec_index->getConstPointer();
2765 const int *pt=_nodal_connec->getConstPointer();
2766 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2767 return ptI[cellId+1]-ptI[cellId]-1;
2769 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2773 * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2774 * This method avoids to compute explicitely submesh to get its types.
2776 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2778 checkFullyDefined();
2779 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2780 const int *conn=_nodal_connec->getConstPointer();
2781 const int *connIndex=_nodal_connec_index->getConstPointer();
2782 for(const int *w=begin;w!=end;w++)
2783 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2788 * Method reserved for advanced users having prepared their connectivity before.
2789 * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2791 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2793 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2794 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2795 if(isComputingTypes)
2801 * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2802 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2804 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2805 _nodal_connec(0),_nodal_connec_index(0),
2806 _types(other._types)
2808 if(other._nodal_connec)
2809 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2810 if(other._nodal_connec_index)
2811 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2814 MEDCouplingUMesh::~MEDCouplingUMesh()
2817 _nodal_connec->decrRef();
2818 if(_nodal_connec_index)
2819 _nodal_connec_index->decrRef();
2823 * This method recomputes all cell types of 'this'.
2825 void MEDCouplingUMesh::computeTypes()
2827 if(_nodal_connec && _nodal_connec_index)
2830 const int *conn=_nodal_connec->getConstPointer();
2831 const int *connIndex=_nodal_connec_index->getConstPointer();
2832 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2833 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
2834 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2839 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2841 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2843 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2844 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2848 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2850 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2852 if(!_nodal_connec_index || !_nodal_connec)
2853 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2856 int MEDCouplingUMesh::getNumberOfCells() const
2858 if(_nodal_connec_index)
2859 return _nodal_connec_index->getNumberOfTuples()-1;
2864 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2867 int MEDCouplingUMesh::getMeshDimension() const
2870 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2875 * This method is for test reason. Normally the integer returned is not useable by user.
2877 int MEDCouplingUMesh::getMeshLength() const
2879 return _nodal_connec->getNbOfElems();
2883 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2885 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2887 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2888 tinyInfo.push_back(getMeshDimension());
2889 tinyInfo.push_back(getNumberOfCells());
2891 tinyInfo.push_back(getMeshLength());
2893 tinyInfo.push_back(-1);
2897 * First step of unserialization process.
2899 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2901 return tinyInfo[6]<=0;
2905 * Second step of serialization process.
2906 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2908 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2910 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2912 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2916 * Third and final step of serialization process.
2918 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2920 MEDCouplingPointSet::serialize(a1,a2);
2921 if(getMeshDimension()>-1)
2923 a1=DataArrayInt::New();
2924 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2925 int *ptA1=a1->getPointer();
2926 const int *conn=getNodalConnectivity()->getConstPointer();
2927 const int *index=getNodalConnectivityIndex()->getConstPointer();
2928 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2929 std::copy(conn,conn+getMeshLength(),ptA1);
2936 * Second and final unserialization process.
2937 * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2939 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2941 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2942 setMeshDimension(tinyInfo[5]);
2946 const int *recvBuffer=a1->getConstPointer();
2947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
2948 myConnecIndex->alloc(tinyInfo[6]+1,1);
2949 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2950 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
2951 myConnec->alloc(tinyInfo[7],1);
2952 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2953 setConnectivity(myConnec, myConnecIndex);
2958 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2959 * CellIds are given using range specified by a start an end and step.
2961 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2963 checkFullyDefined();
2964 int ncell=getNumberOfCells();
2965 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2966 ret->_mesh_dim=_mesh_dim;
2967 ret->setCoords(_coords);
2968 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2970 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2972 const int *conn=_nodal_connec->getConstPointer();
2973 const int *connIndex=_nodal_connec_index->getConstPointer();
2974 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2976 if(work>=0 && work<ncell)
2978 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2982 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2983 throw INTERP_KERNEL::Exception(oss.str().c_str());
2986 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
2987 int *newConnPtr=newConn->getPointer();
2988 std::set<INTERP_KERNEL::NormalizedCellType> types;
2990 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2992 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
2993 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
2995 ret->setConnectivity(newConn,newConnI,false);
2997 ret->copyTinyInfoFrom(this);
3002 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3003 * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3004 * The return newly allocated mesh will share the same coordinates as 'this'.
3006 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3008 checkFullyDefined();
3009 int ncell=getNumberOfCells();
3010 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3011 ret->_mesh_dim=_mesh_dim;
3012 ret->setCoords(_coords);
3013 std::size_t nbOfElemsRet=std::distance(begin,end);
3014 int *connIndexRet=new int[nbOfElemsRet+1];
3016 const int *conn=_nodal_connec->getConstPointer();
3017 const int *connIndex=_nodal_connec_index->getConstPointer();
3019 for(const int *work=begin;work!=end;work++,newNbring++)
3021 if(*work>=0 && *work<ncell)
3022 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3025 delete [] connIndexRet;
3026 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3027 throw INTERP_KERNEL::Exception(oss.str().c_str());
3030 int *connRet=new int[connIndexRet[nbOfElemsRet]];
3031 int *connRetWork=connRet;
3032 std::set<INTERP_KERNEL::NormalizedCellType> types;
3033 for(const int *work=begin;work!=end;work++)
3035 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3036 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3039 connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3041 connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3042 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3044 ret->copyTinyInfoFrom(this);
3049 * brief returns the volumes of the cells underlying the field \a field
3051 * For 2D geometries, the returned field contains the areas.
3052 * For 3D geometries, the returned field contains the volumes.
3054 * param field field on which cells the volumes are required
3055 * return field containing the volumes, area or length depending the meshdimension.
3057 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3059 std::string name="MeasureOfMesh_";
3061 int nbelem=getNumberOfCells();
3062 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3063 field->setName(name.c_str());
3064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3065 array->alloc(nbelem,1);
3066 double *area_vol=array->getPointer();
3067 field->setArray(array) ; array=0;
3068 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3069 field->synchronizeTimeWithMesh();
3070 if(getMeshDimension()!=-1)
3073 INTERP_KERNEL::NormalizedCellType type;
3074 int dim_space=getSpaceDimension();
3075 const double *coords=getCoords()->getConstPointer();
3076 const int *connec=getNodalConnectivity()->getConstPointer();
3077 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3078 for(int iel=0;iel<nbelem;iel++)
3080 ipt=connec_index[iel];
3081 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3082 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);
3085 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3089 area_vol[0]=std::numeric_limits<double>::max();
3091 return field.retn();
3095 * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3096 * This method avoids to build explicitely part of this to perform the work.
3098 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3100 std::string name="PartMeasureOfMesh_";
3102 int nbelem=(int)std::distance(begin,end);
3103 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3104 array->setName(name.c_str());
3105 array->alloc(nbelem,1);
3106 double *area_vol=array->getPointer();
3107 if(getMeshDimension()!=-1)
3110 INTERP_KERNEL::NormalizedCellType type;
3111 int dim_space=getSpaceDimension();
3112 const double *coords=getCoords()->getConstPointer();
3113 const int *connec=getNodalConnectivity()->getConstPointer();
3114 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3115 for(const int *iel=begin;iel!=end;iel++)
3117 ipt=connec_index[*iel];
3118 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3119 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3122 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3126 area_vol[0]=std::numeric_limits<double>::max();
3128 return array.retn();
3132 * This methods returns a field on nodes and no time. This method is usefull to check "P1*" conservative interpolators.
3133 * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3135 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3137 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3138 std::string name="MeasureOnNodeOfMesh_";
3140 int nbNodes=getNumberOfNodes();
3141 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3142 double cst=1./((double)getMeshDimension()+1.);
3143 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3144 array->alloc(nbNodes,1);
3145 double *valsToFill=array->getPointer();
3146 std::fill(valsToFill,valsToFill+nbNodes,0.);
3147 const double *values=tmp->getArray()->getConstPointer();
3148 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3150 getReverseNodalConnectivity(da,daInd);
3151 const int *daPtr=da->getConstPointer();
3152 const int *daIPtr=daInd->getConstPointer();
3153 for(int i=0;i<nbNodes;i++)
3154 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3155 valsToFill[i]+=cst*values[*cell];
3157 ret->setArray(array);
3162 * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3163 * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3165 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3167 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3168 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3169 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3170 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3171 int nbOfCells=getNumberOfCells();
3172 int nbComp=getMeshDimension()+1;
3173 array->alloc(nbOfCells,nbComp);
3174 double *vals=array->getPointer();
3175 const int *connI=_nodal_connec_index->getConstPointer();
3176 const int *conn=_nodal_connec->getConstPointer();
3177 const double *coords=_coords->getConstPointer();
3178 if(getMeshDimension()==2)
3180 if(getSpaceDimension()==3)
3182 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3183 const double *locPtr=loc->getConstPointer();
3184 for(int i=0;i<nbOfCells;i++,vals+=3)
3186 int offset=connI[i];
3187 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3188 double n=INTERP_KERNEL::norm<3>(vals);
3189 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3194 for(int i=0;i<nbOfCells;i++)
3195 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3198 else//meshdimension==1
3201 for(int i=0;i<nbOfCells;i++)
3203 int offset=connI[i];
3204 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3205 double n=INTERP_KERNEL::norm<2>(tmp);
3206 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3211 ret->setArray(array);
3213 ret->synchronizeTimeWithSupport();
3218 * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3219 * This method avoids to build explicitely part of this to perform the work.
3221 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3223 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3224 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3225 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3226 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3227 std::size_t nbelems=std::distance(begin,end);
3228 int nbComp=getMeshDimension()+1;
3229 array->alloc((int)nbelems,nbComp);
3230 double *vals=array->getPointer();
3231 const int *connI=_nodal_connec_index->getConstPointer();
3232 const int *conn=_nodal_connec->getConstPointer();
3233 const double *coords=_coords->getConstPointer();
3234 if(getMeshDimension()==2)
3236 if(getSpaceDimension()==3)
3238 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3239 const double *locPtr=loc->getConstPointer();
3240 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3242 int offset=connI[*i];
3243 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3244 double n=INTERP_KERNEL::norm<3>(vals);
3245 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3250 for(std::size_t i=0;i<nbelems;i++)
3251 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3254 else//meshdimension==1
3257 for(const int *i=begin;i!=end;i++)
3259 int offset=connI[*i];
3260 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3261 double n=INTERP_KERNEL::norm<2>(tmp);
3262 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3267 ret->setArray(array);
3269 ret->synchronizeTimeWithSupport();
3274 * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3275 * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3277 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3279 if(getMeshDimension()!=1)
3280 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3281 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3282 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3283 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3284 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3285 int nbOfCells=getNumberOfCells();
3286 int spaceDim=getSpaceDimension();
3287 array->alloc(nbOfCells,spaceDim);
3288 double *pt=array->getPointer();
3289 const double *coo=getCoords()->getConstPointer();
3290 std::vector<int> conn;
3292 for(int i=0;i<nbOfCells;i++)
3295 getNodeIdsOfCell(i,conn);
3296 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3298 ret->setArray(array);
3300 ret->synchronizeTimeWithSupport();
3305 * 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.
3306 * This method returns 2 objects :
3307 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3308 * - 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
3309 * mesh the 3D cell id is 'this' it comes from.
3310 * This method works only for linear meshes (non quadratic).
3311 * 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
3312 * face. Only 'cellIds' parameter can distinguish the 2.
3313 * @param origin is the origin of the plane. It should be an array of length 3.
3314 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3315 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3316 * 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).
3318 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3320 checkFullyDefined();
3321 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3322 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3324 if(candidates->empty())
3325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3326 std::vector<int> nodes;
3327 DataArrayInt *cellIds1D=0;
3328 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3329 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3335 revDesc2=0; revDescIndx2=0;
3336 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3337 revDesc1=0; revDescIndx1=0;
3338 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3341 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3342 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3344 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3345 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3346 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3347 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3348 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3350 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3351 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3352 if(cellIds2->empty())
3353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3354 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3355 ret->setCoords(mDesc1->getCoords());
3356 ret->setConnectivity(conn,connI,true);
3357 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3362 * 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.
3363 * This method returns 2 objects :
3364 * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3365 * - 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
3366 * mesh the 3DSurf cell id is 'this' it comes from.
3367 * This method works only for linear meshes (non quadratic).
3368 * 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
3369 * face. Only 'cellIds' parameter can distinguish the 2.
3370 * @param origin is the origin of the plane. It should be an array of length 3.
3371 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3372 * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3373 * 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).
3375 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3377 checkFullyDefined();
3378 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3379 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3381 if(candidates->empty())
3382 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3383 std::vector<int> nodes;
3384 DataArrayInt *cellIds1D=0;
3385 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3386 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3391 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3392 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3395 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3396 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3398 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3399 int ncellsSub=subMesh->getNumberOfCells();
3400 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3401 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3402 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3403 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3406 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3407 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3408 for(int i=0;i<ncellsSub;i++)
3410 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3412 if(cut3DSurf[i].first!=-2)
3414 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3415 connI->pushBackSilent(conn->getNumberOfTuples());
3416 cellIds2->pushBackSilent(i);
3420 int cellId3DSurf=cut3DSurf[i].second;
3421 int offset=nodalI[cellId3DSurf]+1;
3422 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3423 for(int j=0;j<nbOfEdges;j++)
3425 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3426 connI->pushBackSilent(conn->getNumberOfTuples());
3427 cellIds2->pushBackSilent(cellId3DSurf);
3432 if(cellIds2->empty())
3433 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3434 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3435 ret->setCoords(mDesc1->getCoords());
3436 ret->setConnectivity(conn,connI,true);
3437 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3442 * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3443 * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3444 * @param origin is the origin of the plane. It should be an array of length 3.
3445 * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3447 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3449 checkFullyDefined();
3450 if(getSpaceDimension()!=3)
3451 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3452 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3454 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3456 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3457 double angle=acos(vec[2]/normm);
3458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3462 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3463 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3464 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3466 mw->getBoundingBox(bbox);
3467 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3468 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3472 getBoundingBox(bbox);
3473 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3474 cellIds=getCellsInBoundingBox(bbox,eps);
3476 return cellIds.retn();
3480 * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3481 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3482 * No consideration of coordinate is done by this method.
3483 * 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)
3484 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3486 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3488 if(getMeshDimension()!=1)
3489 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3490 int nbCells=getNumberOfCells();
3492 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3493 const int *connI=_nodal_connec_index->getConstPointer();
3494 const int *conn=_nodal_connec->getConstPointer();
3495 int ref=conn[connI[0]+2];
3496 for(int i=1;i<nbCells;i++)
3498 if(conn[connI[i]+1]!=ref)
3500 ref=conn[connI[i]+2];
3506 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3507 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3508 * @param pt reference point of the line
3509 * @param v normalized director vector of the line
3510 * @param eps max precision before throwing an exception
3511 * @param res output of size this->getNumberOfCells
3513 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3515 if(getMeshDimension()!=1)
3516 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3517 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3518 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3519 if(getSpaceDimension()!=3)
3520 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3521 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3522 const double *fPtr=f->getArray()->getConstPointer();
3524 for(int i=0;i<getNumberOfCells();i++)
3526 const double *tmp1=fPtr+3*i;
3527 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3528 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3529 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3530 double n1=INTERP_KERNEL::norm<3>(tmp);
3531 n1/=INTERP_KERNEL::norm<3>(tmp1);
3533 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3535 const double *coo=getCoords()->getConstPointer();
3536 for(int i=0;i<getNumberOfNodes();i++)
3538 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3539 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3540 res[i]=std::accumulate(tmp,tmp+3,0.);
3545 * 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.
3546 * \a this is expected to be a mesh so that its space dimension is equal to its
3547 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3548 * 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).
3550 * 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
3551 * 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
3552 * to the node that minimizes distance with the input point then -1 is returned in cellId.
3554 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3555 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3557 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3558 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3559 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3560 * \return the positive value of the distance.
3561 * \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
3563 * \sa DataArrayDouble::distanceToTuple
3565 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
3567 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3568 if(meshDim!=spaceDim-1)
3569 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3570 if(meshDim!=2 && meshDim!=1)
3571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3572 checkFullyDefined();
3573 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3574 { 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()); }
3576 double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
3578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
3579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
3584 distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
3589 distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
3593 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3601 * \param [in] pt the start pointer (included) of the coordinates of the point
3602 * \param [in] cellIds
3603 * \param [in,out] ret0 the min distance between \a this and the external input point
3604 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3605 * \sa MEDCouplingUMesh::distanceToPoint
3607 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3609 const double *coords=_coords->getConstPointer();
3611 if(cellIds->empty())
3613 const int *ptr=_nodal_connec->getConstPointer();
3614 const int *ptrI=_nodal_connec_index->getConstPointer();
3615 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3617 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3619 case INTERP_KERNEL::NORM_TRI3:
3621 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
3623 { ret0=tmp; cellId=*zeCell; }
3626 case INTERP_KERNEL::NORM_QUAD4:
3627 case INTERP_KERNEL::NORM_POLYGON:
3629 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
3631 { ret0=tmp; cellId=*zeCell; }
3635 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3641 * \param [in] pt the start pointer (included) of the coordinates of the point
3642 * \param [in] cellIds
3643 * \param [in,out] ret0 the min distance between \a this and the external input point
3644 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3645 * \sa MEDCouplingUMesh::distanceToPoint
3647 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3649 const double *coords=_coords->getConstPointer();
3650 if(cellIds->empty())
3651 { cellId=-1; return; }
3652 const int *ptr=_nodal_connec->getConstPointer();
3653 const int *ptrI=_nodal_connec_index->getConstPointer();
3654 for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3656 switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3658 case INTERP_KERNEL::NORM_SEG2:
3660 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
3661 if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
3663 { ret0=tmp; cellId=*zeCell; }
3667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3673 * Returns a cell if any that contains the point located on 'pos' with precison eps.
3674 * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3675 * \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'
3676 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3678 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3680 std::vector<int> elts;
3681 getCellsContainingPoint(pos,eps,elts);
3684 return elts.front();
3688 * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3689 * \b Warning this method is good if the caller intends to evaluate only one point. But if more than one point is requested on 'this'
3690 * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3692 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3694 std::vector<int> eltsIndex;
3695 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3700 namespace ParaMEDMEM
3702 template<const int SPACEDIMM>
3706 static const int MY_SPACEDIM=SPACEDIMM;
3707 static const int MY_MESHDIM=8;
3708 typedef int MyConnType;
3709 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3711 // useless, but for windows compilation ...
3712 const double* getCoordinatesPtr() const { return 0; }
3713 const int* getConnectivityPtr() const { return 0; }
3714 const int* getConnectivityIndexPtr() const { return 0; }
3715 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3719 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3721 INTERP_KERNEL::Edge *ret=0;
3724 case INTERP_KERNEL::NORM_SEG2:
3726 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3729 case INTERP_KERNEL::NORM_SEG3:
3731 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3732 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3733 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3734 bool colinearity=inters.areColinears();
3735 delete e1; delete e2;
3737 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3739 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3740 mapp2[bg[2]].second=false;
3744 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3750 * 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'.
3751 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3752 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3754 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3757 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.
3758 const double *coo=mDesc->getCoords()->getConstPointer();
3759 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3760 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3762 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3763 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3764 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3766 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3767 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3769 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3770 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3772 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3773 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3775 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3777 if((*it2).second.second)
3778 mapp[(*it2).second.first]=(*it2).first;
3779 ((*it2).second.first)->decrRef();
3784 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3788 int locId=nodeId-offset2;
3789 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3793 int locId=nodeId-offset1;
3794 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3796 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3799 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3800 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3801 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3803 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3805 int eltId1=abs(*desc1)-1;
3806 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3808 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3809 if(it==mappRev.end())
3811 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3822 template<int SPACEDIM>
3823 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3824 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3826 std::vector<double> bbox;
3827 eltsIndex.resize(nbOfPoints+1);
3830 getBoundingBoxForBBTree(bbox);
3831 int nbOfCells=getNumberOfCells();
3832 const int *conn=_nodal_connec->getConstPointer();
3833 const int *connI=_nodal_connec_index->getConstPointer();
3834 double bb[2*SPACEDIM];
3835 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3836 for(int i=0;i<nbOfPoints;i++)
3838 eltsIndex[i+1]=eltsIndex[i];
3839 for(int j=0;j<SPACEDIM;j++)
3841 bb[2*j]=pos[SPACEDIM*i+j];
3842 bb[2*j+1]=pos[SPACEDIM*i+j];
3844 std::vector<int> candidates;
3845 myTree.getIntersectingElems(bb,candidates);
3846 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3848 int sz=connI[(*iter)+1]-connI[*iter]-1;
3849 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3850 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3851 coords,conn+connI[*iter]+1,sz,eps))
3854 elts.push_back(*iter);
3861 * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3862 * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3863 * in case of multi points searching.
3864 * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3865 * 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]).
3867 * \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...
3869 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3870 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3872 int spaceDim=getSpaceDimension();
3873 int mDim=getMeshDimension();
3878 const double *coords=_coords->getConstPointer();
3879 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3886 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3888 else if(spaceDim==2)
3892 const double *coords=_coords->getConstPointer();
3893 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3896 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3898 else if(spaceDim==1)
3902 const double *coords=_coords->getConstPointer();
3903 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3906 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3913 * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3914 * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3915 * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3916 * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3918 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3920 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3921 if(getMeshDimension()!=2)
3922 throw INTERP_KERNEL::Exception(msg);
3923 int spaceDim=getSpaceDimension();
3924 if(spaceDim!=2 && spaceDim!=3)
3925 throw INTERP_KERNEL::Exception(msg);
3926 const int *conn=_nodal_connec->getConstPointer();
3927 const int *connI=_nodal_connec_index->getConstPointer();
3928 int nbOfCells=getNumberOfCells();
3929 std::vector<double> cell2DinS2;
3930 for(int i=0;i<nbOfCells;i++)
3932 int offset=connI[i];
3933 int nbOfNodesForCell=connI[i+1]-offset-1;
3934 if(nbOfNodesForCell<=3)
3936 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3937 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3938 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3945 * This method is typically requested to unbutterfly 2D linear cells in \b this.
3947 * 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.
3948 * 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.
3950 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3951 * This convex envelop is computed using Jarvis march algorithm.
3952 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3953 * 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)
3954 * 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.
3956 * @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.
3958 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3960 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3961 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
3962 checkFullyDefined();
3963 const double *coords=getCoords()->getConstPointer();
3964 int nbOfCells=getNumberOfCells();
3965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3966 nodalConnecIndexOut->alloc(nbOfCells+1,1);
3967 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
3968 int *workIndexOut=nodalConnecIndexOut->getPointer();
3970 const int *nodalConnecIn=_nodal_connec->getConstPointer();
3971 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3972 std::set<INTERP_KERNEL::NormalizedCellType> types;
3973 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
3974 isChanged->alloc(0,1);
3975 for(int i=0;i<nbOfCells;i++,workIndexOut++)
3977 int pos=nodalConnecOut->getNumberOfTuples();
3978 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3979 isChanged->pushBackSilent(i);
3980 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
3981 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
3983 if(isChanged->empty())
3985 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
3987 return isChanged.retn();
3991 * This method is \b NOT const because it can modify 'this'.
3992 * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
3993 * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
3994 * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
3995 * \b 1 for translation and rotation around point of 'mesh1D'.
3996 * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
3998 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4000 checkFullyDefined();
4001 mesh1D->checkFullyDefined();
4002 if(!mesh1D->isContiguous1D())
4003 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4004 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4005 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4006 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4007 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4008 if(mesh1D->getMeshDimension()!=1)
4009 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4011 if(isPresenceOfQuadratic())
4013 if(mesh1D->isFullyQuadratic())
4016 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4019 int oldNbOfNodes=getNumberOfNodes();
4020 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4025 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4030 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4034 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4036 setCoords(newCoords);
4037 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4043 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4044 * If it is not the case an exception will be thrown.
4045 * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4046 * intersection of plane defined by ('origin','vec').
4047 * This method has one in/out parameter : 'cut3DCurve'.
4048 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4049 * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4050 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4051 * This method will throw an exception if 'this' contains a non linear segment.
4053 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4055 checkFullyDefined();
4056 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4057 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4058 int ncells=getNumberOfCells();
4059 int nnodes=getNumberOfNodes();
4060 double vec2[3],vec3[3],vec4[3];
4061 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4063 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4064 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4065 const int *conn=_nodal_connec->getConstPointer();
4066 const int *connI=_nodal_connec_index->getConstPointer();
4067 const double *coo=_coords->getConstPointer();
4068 std::vector<double> addCoo;
4069 for(int i=0;i<ncells;i++)
4071 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4073 if(cut3DCurve[i]==-2)
4075 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4076 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];
4077 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4078 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4079 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4081 const double *st2=coo+3*st;
4082 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4083 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]));
4084 if(pos>eps && pos<1-eps)
4086 int nNode=((int)addCoo.size())/3;
4087 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4088 addCoo.insert(addCoo.end(),vec4,vec4+3);
4089 cut3DCurve[i]=nnodes+nNode;
4095 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4099 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4100 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4101 coo2->alloc(newNbOfNodes,3);
4102 double *tmp=coo2->getPointer();
4103 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4104 std::copy(addCoo.begin(),addCoo.end(),tmp);
4105 DataArrayDouble::SetArrayIn(coo2,_coords);
4110 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4111 * @param mesh1D is the input 1D mesh used for translation computation.
4112 * @return newCoords new coords filled by this method.
4114 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4116 int oldNbOfNodes=getNumberOfNodes();
4117 int nbOf1DCells=mesh1D->getNumberOfCells();
4118 int spaceDim=getSpaceDimension();
4119 DataArrayDouble *ret=DataArrayDouble::New();
4120 std::vector<bool> isQuads;
4121 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4122 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4123 double *retPtr=ret->getPointer();
4124 const double *coords=getCoords()->getConstPointer();
4125 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4127 std::vector<double> c;
4131 for(int i=0;i<nbOf1DCells;i++)
4134 mesh1D->getNodeIdsOfCell(i,v);
4136 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4137 mesh1D->getCoordinatesOfNode(v[0],c);
4138 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4139 for(int j=0;j<oldNbOfNodes;j++)
4140 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4144 mesh1D->getCoordinatesOfNode(v[1],c);
4145 mesh1D->getCoordinatesOfNode(v[0],c);
4146 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4147 for(int j=0;j<oldNbOfNodes;j++)
4148 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4151 ret->copyStringInfoFrom(*getCoords());
4156 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4157 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4158 * @return newCoords new coords filled by this method.
4160 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4162 if(mesh1D->getSpaceDimension()==2)
4163 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4164 if(mesh1D->getSpaceDimension()==3)
4165 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4166 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4170 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4171 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4172 * @return newCoords new coords filled by this method.
4174 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4177 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4178 int oldNbOfNodes=getNumberOfNodes();
4179 int nbOf1DCells=mesh1D->getNumberOfCells();
4181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4182 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4183 int nbOfLevsInVec=nbOf1DCells+1;
4184 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4185 double *retPtr=ret->getPointer();
4186 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4187 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4189 tmp->setCoords(tmp2);
4190 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4191 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4192 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4193 for(int i=1;i<nbOfLevsInVec;i++)
4195 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4196 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4197 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4198 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4199 tmp->translate(vec);
4200 double tmp3[2],radius,alpha,alpha0;
4201 const double *p0=i+1<nbOfLevsInVec?begin:third;
4202 const double *p1=i+1<nbOfLevsInVec?end:begin;
4203 const double *p2=i+1<nbOfLevsInVec?third:end;
4204 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4205 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]);
4206 double angle=acos(cosangle/(radius*radius));
4207 tmp->rotate(end,0,angle);
4208 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4214 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4215 * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4216 * @return newCoords new coords filled by this method.
4218 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4221 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4222 int oldNbOfNodes=getNumberOfNodes();
4223 int nbOf1DCells=mesh1D->getNumberOfCells();
4225 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4226 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4227 int nbOfLevsInVec=nbOf1DCells+1;
4228 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4229 double *retPtr=ret->getPointer();
4230 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4231 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4232 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4233 tmp->setCoords(tmp2);
4234 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4235 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4236 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4237 for(int i=1;i<nbOfLevsInVec;i++)
4239 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4240 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4241 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4242 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4243 tmp->translate(vec);
4244 double tmp3[2],radius,alpha,alpha0;
4245 const double *p0=i+1<nbOfLevsInVec?begin:third;
4246 const double *p1=i+1<nbOfLevsInVec?end:begin;
4247 const double *p2=i+1<nbOfLevsInVec?third:end;
4248 double vecPlane[3]={
4249 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4250 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4251 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4253 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4256 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4257 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4258 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4260 double c2=cos(asin(s2));
4262 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4263 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4264 {-vec2[1]*s2, vec2[0]*s2, c2}
4266 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]};
4267 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]};
4268 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]};
4269 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4270 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]);
4271 double angle=acos(cosangle/(radius*radius));
4272 tmp->rotate(end,vecPlane,angle);
4275 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4281 * This method is private because not easy to use for end user. This method is const contrary to
4282 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4283 * the coords sorted slice by slice.
4284 * @param isQuad specifies presence of quadratic cells.
4286 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4288 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4289 int nbOf2DCells=getNumberOfCells();
4290 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4291 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4292 const int *conn=_nodal_connec->getConstPointer();
4293 const int *connI=_nodal_connec_index->getConstPointer();
4294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4296 newConnI->alloc(nbOf3DCells+1,1);
4297 int *newConnIPtr=newConnI->getPointer();
4299 std::vector<int> newc;
4300 for(int j=0;j<nbOf2DCells;j++)
4302 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4303 *newConnIPtr++=(int)newc.size();
4305 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4306 int *newConnPtr=newConn->getPointer();
4307 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4308 newConnIPtr=newConnI->getPointer();
4309 for(int iz=0;iz<nbOf1DCells;iz++)
4312 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4313 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4315 int icell=(int)(iter-newc.begin());
4316 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4319 *newConnPtr=(*iter)+iz*deltaPerLev;
4324 *newConnPtr=(*iter);
4327 ret->setConnectivity(newConn,newConnI,true);
4328 ret->setCoords(getCoords());
4333 * This method returns if 'this' is constituted by only quadratic cells.
4335 bool MEDCouplingUMesh::isFullyQuadratic() const
4337 checkFullyDefined();
4339 int nbOfCells=getNumberOfCells();
4340 for(int i=0;i<nbOfCells && ret;i++)
4342 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4343 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4344 ret=cm.isQuadratic();
4350 * This method returns if there is at least one quadratic cell.
4352 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4354 checkFullyDefined();
4356 int nbOfCells=getNumberOfCells();
4357 for(int i=0;i<nbOfCells && !ret;i++)
4359 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4360 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4361 ret=cm.isQuadratic();
4367 * This method convert quadratic cells to linear cells if any was found.
4368 * If no such cells exists 'this' remains unchanged.
4370 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4372 checkFullyDefined();
4373 int nbOfCells=getNumberOfCells();
4375 for(int i=0;i<nbOfCells;i++)
4377 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4378 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4379 if(cm.isQuadratic())
4381 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4382 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4383 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4390 newConn->alloc(getMeshLength()-delta,1);
4391 newConnI->alloc(nbOfCells+1,1);
4392 const int *icptr=_nodal_connec->getConstPointer();
4393 const int *iciptr=_nodal_connec_index->getConstPointer();
4394 int *ocptr=newConn->getPointer();
4395 int *ociptr=newConnI->getPointer();
4398 for(int i=0;i<nbOfCells;i++,ociptr++)
4400 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4401 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4402 if(!cm.isQuadratic())
4404 _types.insert(type);
4405 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4406 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4410 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4411 _types.insert(typel);
4412 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4413 int newNbOfNodes=cml.getNumberOfNodes();
4414 *ocptr++=(int)typel;
4415 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4416 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4419 setConnectivity(newConn,newConnI,false);
4423 * This method converts all linear cell in \a this to quadratic one.
4424 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4425 * 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)
4426 * 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.
4427 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4428 * end of the existing coordinates.
4430 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4431 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4432 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4434 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4436 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4438 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4440 DataArrayInt *conn=0,*connI=0;
4441 DataArrayDouble *coords=0;
4442 std::set<INTERP_KERNEL::NormalizedCellType> types;
4443 checkFullyDefined();
4444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4445 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4446 int meshDim=getMeshDimension();
4447 switch(conversionType)
4453 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4454 connSafe=conn; connISafe=connI; coordsSafe=coords;
4457 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4458 connSafe=conn; connISafe=connI; coordsSafe=coords;
4461 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4462 connSafe=conn; connISafe=connI; coordsSafe=coords;
4465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4469 //return convertLinearCellsToQuadratic1();
4471 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4473 setConnectivity(connSafe,connISafe,false);
4475 setCoords(coordsSafe);
4480 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4481 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4482 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4484 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4486 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4488 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4489 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4490 int nbOfCells=getNumberOfCells();
4491 int nbOfNodes=getNumberOfNodes();
4492 const int *cPtr=_nodal_connec->getConstPointer();
4493 const int *icPtr=_nodal_connec_index->getConstPointer();
4494 int lastVal=0,offset=nbOfNodes;
4495 for(int i=0;i<nbOfCells;i++,icPtr++)
4497 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4498 if(type==INTERP_KERNEL::NORM_SEG2)
4500 types.insert(INTERP_KERNEL::NORM_SEG3);
4501 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4502 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4503 newConn->pushBackSilent(offset++);
4505 newConnI->pushBackSilent(lastVal);
4506 ret->pushBackSilent(i);
4511 lastVal+=(icPtr[1]-icPtr[0]);
4512 newConnI->pushBackSilent(lastVal);
4513 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4516 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4517 conn=newConn.retn(); connI=newConnI.retn(); coords=DataArrayDouble::Aggregate(getCoords(),tmp);
4521 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)
4523 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4524 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4525 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4527 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4528 DataArrayInt *conn1D=0,*conn1DI=0;
4529 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4530 DataArrayDouble *coordsTmp=0;
4531 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4532 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4534 const int *c1DPtr=conn1D->begin();
4535 const int *c1DIPtr=conn1DI->begin();
4536 int nbOfCells=getNumberOfCells();
4537 const int *cPtr=_nodal_connec->getConstPointer();
4538 const int *icPtr=_nodal_connec_index->getConstPointer();
4540 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4542 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4543 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4544 if(!cm.isQuadratic())
4546 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4547 types.insert(typ2); newConn->pushBackSilent(typ2);
4548 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4549 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4550 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4551 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4552 newConnI->pushBackSilent(lastVal);
4553 ret->pushBackSilent(i);
4558 lastVal+=(icPtr[1]-icPtr[0]);
4559 newConnI->pushBackSilent(lastVal);
4560 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4563 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4568 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4569 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4570 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4572 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4576 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4577 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4581 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4582 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4583 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4585 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4587 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4588 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4589 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4593 * This method tessallates 'this' so that the number of cells remains the same.
4594 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4595 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4597 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4598 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4600 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4602 checkFullyDefined();
4603 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4604 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4605 double epsa=fabs(eps);
4606 if(epsa<std::numeric_limits<double>::min())
4607 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 !");
4608 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4609 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4611 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4612 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4613 revDesc1=0; revDescIndx1=0;
4614 mDesc->tessellate2DCurve(eps);
4615 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4616 setCoords(mDesc->getCoords());
4620 * This method tessallates 'this' so that the number of cells remains the same.
4621 * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4622 * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4624 * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4625 * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4627 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4629 checkFullyDefined();
4630 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4632 double epsa=fabs(eps);
4633 if(epsa<std::numeric_limits<double>::min())
4634 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 !");
4635 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4636 int nbCells=getNumberOfCells();
4637 int nbNodes=getNumberOfNodes();
4638 const int *conn=_nodal_connec->getConstPointer();
4639 const int *connI=_nodal_connec_index->getConstPointer();
4640 const double *coords=_coords->getConstPointer();
4641 std::vector<double> addCoo;
4642 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
4643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
4644 newConnI->alloc(nbCells+1,1);
4645 int *newConnIPtr=newConnI->getPointer();
4648 INTERP_KERNEL::Node *tmp2[3];
4649 std::set<INTERP_KERNEL::NormalizedCellType> types;
4650 for(int i=0;i<nbCells;i++,newConnIPtr++)
4652 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4653 if(cm.isQuadratic())
4654 {//assert(connI[i+1]-connI[i]-1==3)
4655 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4656 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4657 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4658 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4659 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4662 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4663 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4665 newConnIPtr[1]=(int)newConn.size();
4669 types.insert(INTERP_KERNEL::NORM_SEG2);
4670 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4671 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4672 newConnIPtr[1]=newConnIPtr[0]+3;
4677 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4678 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4679 newConnIPtr[1]=newConnIPtr[0]+3;
4682 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4685 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4687 newConnArr->alloc((int)newConn.size(),1);
4688 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4689 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4690 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4691 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4692 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4693 std::copy(addCoo.begin(),addCoo.end(),work);
4694 DataArrayDouble::SetArrayIn(newCoords,_coords);
4699 * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4700 * This cut into simplex is performed following the parameter \a policy. This method so typically increases the number of cells of \a this.
4701 * 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.
4702 * This method returns new2old newly allocated array that specifies a each cell of \a this after the call what was its id it comes.
4704 * The semantic of \a policy parameter :
4705 * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4706 * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4707 * - PLANAR_FACE_5 only HEXA8. All HEXA8 are split into 5 TETRA4
4708 * - PLANAR_FACE_6 only HEXA8. All HEXA8 are split into 6 TETRA4
4710 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4715 return simplexizePol0();
4717 return simplexizePol1();
4718 case (int) INTERP_KERNEL::PLANAR_FACE_5:
4719 return simplexizePlanarFace5();
4720 case (int) INTERP_KERNEL::PLANAR_FACE_6:
4721 return simplexizePlanarFace6();
4723 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)");
4727 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4729 checkFullyDefined();
4730 if(getMeshDimension()<1)
4731 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4732 int nbCells=getNumberOfCells();
4733 const int *conn=_nodal_connec->getConstPointer();
4734 const int *connI=_nodal_connec_index->getConstPointer();
4735 for(int i=0;i<nbCells;i++)
4737 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4745 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4747 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4749 checkConnectivityFullyDefined();
4750 if(getMeshDimension()!=2)
4751 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4752 int nbOfCells=getNumberOfCells();
4753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4754 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4755 ret->alloc(nbOfCells+nbOfCutCells,1);
4756 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4757 int *retPt=ret->getPointer();
4758 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4760 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4761 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4762 int *pt=newConn->getPointer();
4763 int *ptI=newConnI->getPointer();
4765 const int *oldc=_nodal_connec->getConstPointer();
4766 const int *ci=_nodal_connec_index->getConstPointer();
4767 for(int i=0;i<nbOfCells;i++,ci++)
4769 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4771 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4772 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4773 pt=std::copy(tmp,tmp+8,pt);
4782 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4783 ptI[1]=ptI[0]+ci[1]-ci[0];
4788 _nodal_connec->decrRef();
4789 _nodal_connec=newConn.retn();
4790 _nodal_connec_index->decrRef();
4791 _nodal_connec_index=newConnI.retn();
4798 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4800 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4802 checkConnectivityFullyDefined();
4803 if(getMeshDimension()!=2)
4804 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4805 int nbOfCells=getNumberOfCells();
4806 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4807 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4808 ret->alloc(nbOfCells+nbOfCutCells,1);
4809 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4810 int *retPt=ret->getPointer();
4811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4813 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4814 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4815 int *pt=newConn->getPointer();
4816 int *ptI=newConnI->getPointer();
4818 const int *oldc=_nodal_connec->getConstPointer();
4819 const int *ci=_nodal_connec_index->getConstPointer();
4820 for(int i=0;i<nbOfCells;i++,ci++)
4822 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4824 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4825 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4826 pt=std::copy(tmp,tmp+8,pt);
4835 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4836 ptI[1]=ptI[0]+ci[1]-ci[0];
4841 _nodal_connec->decrRef();
4842 _nodal_connec=newConn.retn();
4843 _nodal_connec_index->decrRef();
4844 _nodal_connec_index=newConnI.retn();
4851 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4853 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
4855 checkConnectivityFullyDefined();
4856 if(getMeshDimension()!=3)
4857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
4858 int nbOfCells=getNumberOfCells();
4859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4860 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
4861 ret->alloc(nbOfCells+4*nbOfCutCells,1);
4862 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4863 int *retPt=ret->getPointer();
4864 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4866 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
4867 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
4868 int *pt=newConn->getPointer();
4869 int *ptI=newConnI->getPointer();
4871 const int *oldc=_nodal_connec->getConstPointer();
4872 const int *ci=_nodal_connec_index->getConstPointer();
4873 for(int i=0;i<nbOfCells;i++,ci++)
4875 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
4877 for(int j=0;j<5;j++,pt+=5,ptI++)
4879 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
4880 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];
4887 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4888 ptI[1]=ptI[0]+ci[1]-ci[0];
4893 _nodal_connec->decrRef();
4894 _nodal_connec=newConn.retn();
4895 _nodal_connec_index->decrRef();
4896 _nodal_connec_index=newConnI.retn();
4903 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4905 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
4907 checkConnectivityFullyDefined();
4908 if(getMeshDimension()!=3)
4909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
4910 int nbOfCells=getNumberOfCells();
4911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4912 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
4913 ret->alloc(nbOfCells+5*nbOfCutCells,1);
4914 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4915 int *retPt=ret->getPointer();
4916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4918 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
4919 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
4920 int *pt=newConn->getPointer();
4921 int *ptI=newConnI->getPointer();
4923 const int *oldc=_nodal_connec->getConstPointer();
4924 const int *ci=_nodal_connec_index->getConstPointer();
4925 for(int i=0;i<nbOfCells;i++,ci++)
4927 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
4929 for(int j=0;j<6;j++,pt+=5,ptI++)
4931 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
4932 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];
4939 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4940 ptI[1]=ptI[0]+ci[1]-ci[0];
4945 _nodal_connec->decrRef();
4946 _nodal_connec=newConn.retn();
4947 _nodal_connec_index->decrRef();
4948 _nodal_connec_index=newConnI.retn();
4955 * 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.
4956 * This method completly ignore coordinates.
4957 * @param nodeSubdived is the nodal connectivity of subdivision of edges
4958 * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
4959 * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4960 * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
4962 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
4964 checkFullyDefined();
4965 if(getMeshDimension()!=2)
4966 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
4967 int nbOfCells=getNumberOfCells();
4968 int *connI=_nodal_connec_index->getPointer();
4970 for(int i=0;i<nbOfCells;i++,connI++)
4972 int offset=descIndex[i];
4973 int nbOfEdges=descIndex[i+1]-offset;
4975 bool ddirect=desc[offset+nbOfEdges-1]>0;
4976 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
4977 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
4978 for(int j=0;j<nbOfEdges;j++)
4980 bool direct=desc[offset+j]>0;
4981 int edgeId=std::abs(desc[offset+j])-1;
4982 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
4984 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
4985 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
4986 int ref2=direct?id1:id2;
4989 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
4990 newConnLgth+=nbOfSubNodes-1;
4995 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
4996 throw INTERP_KERNEL::Exception(oss.str().c_str());
5001 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5004 newConnLgth++;//+1 is for cell type
5005 connI[1]=newConnLgth;
5008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5009 newConn->alloc(newConnLgth,1);
5010 int *work=newConn->getPointer();
5011 for(int i=0;i<nbOfCells;i++)
5013 *work++=INTERP_KERNEL::NORM_POLYGON;
5014 int offset=descIndex[i];
5015 int nbOfEdges=descIndex[i+1]-offset;
5016 for(int j=0;j<nbOfEdges;j++)
5018 bool direct=desc[offset+j]>0;
5019 int edgeId=std::abs(desc[offset+j])-1;
5021 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5024 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5025 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5026 work=std::copy(it,it+nbOfSubNodes-1,work);
5030 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5033 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5037 * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
5038 * nodal connectivity will be transform to a NORM_TRI3 cell.
5039 * This method works \b only \b on \b linear cells.
5040 * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
5041 * method could be usefull before calling this method in case of presence of several pair of nodes located on same position.
5042 * This method throws an exception if 'this' is not fully defined (connectivity).
5043 * 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.
5045 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5047 checkFullyDefined();
5048 if(getMeshDimension()<=1)
5049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5050 int nbOfCells=getNumberOfCells();
5053 int initMeshLgth=getMeshLength();
5054 int *conn=_nodal_connec->getPointer();
5055 int *index=_nodal_connec_index->getPointer();
5059 for(int i=0;i<nbOfCells;i++)
5061 lgthOfCurCell=index[i+1]-posOfCurCell;
5062 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5064 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5065 conn+newPos+1,newLgth);
5066 conn[newPos]=newType;
5068 posOfCurCell=index[i+1];
5071 if(newPos!=initMeshLgth)
5072 _nodal_connec->reAlloc(newPos);
5077 * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5078 * The 'vec' vector has to have a non nul norm.
5079 * If not 'cells' parameter will be appended with cellIds of incorrect cells.
5080 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5082 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5084 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5085 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5086 int nbOfCells=getNumberOfCells();
5087 const int *conn=_nodal_connec->getConstPointer();
5088 const int *connI=_nodal_connec_index->getConstPointer();
5089 const double *coordsPtr=_coords->getConstPointer();
5090 for(int i=0;i<nbOfCells;i++)
5092 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5093 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5095 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5096 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5103 * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5104 * The 'vec' vector has to have a non nul norm.
5105 * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5107 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5109 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5110 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5111 int nbOfCells=getNumberOfCells();
5112 int *conn=_nodal_connec->getPointer();
5113 const int *connI=_nodal_connec_index->getConstPointer();
5114 const double *coordsPtr=_coords->getConstPointer();
5115 bool isModified=false;
5116 for(int i=0;i<nbOfCells;i++)
5118 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5119 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5121 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5122 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5125 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5126 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5127 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5132 _nodal_connec->declareAsNew();
5137 * This method checks that all polyhedrons cells have correctly oriented faces.
5138 * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
5139 * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
5141 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5143 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5144 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5145 int nbOfCells=getNumberOfCells();
5146 const int *conn=_nodal_connec->getConstPointer();
5147 const int *connI=_nodal_connec_index->getConstPointer();
5148 const double *coordsPtr=_coords->getConstPointer();
5149 for(int i=0;i<nbOfCells;i++)
5151 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5152 if(type==INTERP_KERNEL::NORM_POLYHED)
5154 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5161 * This method tries to orient correctly polhedrons cells.
5163 * \throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
5164 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5166 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5168 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5169 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5170 int nbOfCells=getNumberOfCells();
5171 int *conn=_nodal_connec->getPointer();
5172 const int *connI=_nodal_connec_index->getConstPointer();
5173 const double *coordsPtr=_coords->getConstPointer();
5174 for(int i=0;i<nbOfCells;i++)
5176 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5177 if(type==INTERP_KERNEL::NORM_POLYHED)
5181 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5182 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5184 catch(INTERP_KERNEL::Exception& e)
5186 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5187 throw INTERP_KERNEL::Exception(oss.str().c_str());
5195 * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
5196 * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
5197 * 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).
5198 * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
5200 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5201 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5203 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5205 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5206 if(getMeshDimension()!=3)
5207 throw INTERP_KERNEL::Exception(msg);
5208 int spaceDim=getSpaceDimension();
5210 throw INTERP_KERNEL::Exception(msg);
5212 int nbOfCells=getNumberOfCells();
5213 int *conn=_nodal_connec->getPointer();
5214 const int *connI=_nodal_connec_index->getConstPointer();
5215 const double *coo=getCoords()->getConstPointer();
5216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5217 for(int i=0;i<nbOfCells;i++)
5219 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5220 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5222 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5224 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5225 cells->pushBackSilent(i);
5229 return cells.retn();
5233 * This method is a faster method to correct orientation of all 3D cells in \a this.
5234 * 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.
5235 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5237 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5238 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5240 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5242 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5243 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5244 int nbOfCells=getNumberOfCells();
5245 int *conn=_nodal_connec->getPointer();
5246 const int *connI=_nodal_connec_index->getConstPointer();
5247 const double *coordsPtr=_coords->getConstPointer();
5248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5249 for(int i=0;i<nbOfCells;i++)
5251 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5254 case INTERP_KERNEL::NORM_TETRA4:
5256 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5258 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5259 ret->pushBackSilent(i);
5263 case INTERP_KERNEL::NORM_PYRA5:
5265 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5267 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5268 ret->pushBackSilent(i);
5272 case INTERP_KERNEL::NORM_PENTA6:
5273 case INTERP_KERNEL::NORM_HEXA8:
5274 case INTERP_KERNEL::NORM_HEXGP12:
5276 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5278 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5279 ret->pushBackSilent(i);
5283 case INTERP_KERNEL::NORM_POLYHED:
5285 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5287 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5288 ret->pushBackSilent(i);
5293 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 !");
5301 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5302 * If it is not the case an exception will be thrown.
5303 * This method is fast because the first cell of 'this' is used to compute the plane.
5304 * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5305 * @param pos output of size at least 3 used to store a point owned of searched plane.
5307 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5309 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5310 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5311 const int *conn=_nodal_connec->getConstPointer();
5312 const int *connI=_nodal_connec_index->getConstPointer();
5313 const double *coordsPtr=_coords->getConstPointer();
5314 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5315 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5319 * The returned newly created field has to be managed by the caller.
5320 * 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.
5321 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5322 * If a cell has an another type an exception will be thrown.
5324 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5327 int spaceDim=getSpaceDimension();
5328 int meshDim=getMeshDimension();
5329 if(spaceDim!=2 && spaceDim!=3)
5330 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5331 if(meshDim!=2 && meshDim!=3)
5332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5333 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5335 int nbOfCells=getNumberOfCells();
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5337 arr->alloc(nbOfCells,1);
5338 double *pt=arr->getPointer();
5339 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5340 const int *conn=_nodal_connec->getConstPointer();
5341 const int *connI=_nodal_connec_index->getConstPointer();
5342 const double *coo=_coords->getConstPointer();
5344 for(int i=0;i<nbOfCells;i++,pt++)
5346 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5349 case INTERP_KERNEL::NORM_TRI3:
5351 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5352 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5355 case INTERP_KERNEL::NORM_QUAD4:
5357 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5358 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5361 case INTERP_KERNEL::NORM_TETRA4:
5363 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5364 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5370 conn+=connI[i+1]-connI[i];
5372 ret->setName("EdgeRatio");
5373 ret->synchronizeTimeWithSupport();
5378 * The returned newly created field has to be managed by the caller.
5379 * 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.
5380 * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5381 * If a cell has an another type an exception will be thrown.
5383 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5386 int spaceDim=getSpaceDimension();
5387 int meshDim=getMeshDimension();
5388 if(spaceDim!=2 && spaceDim!=3)
5389 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5390 if(meshDim!=2 && meshDim!=3)
5391 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5394 int nbOfCells=getNumberOfCells();
5395 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5396 arr->alloc(nbOfCells,1);
5397 double *pt=arr->getPointer();
5398 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5399 const int *conn=_nodal_connec->getConstPointer();
5400 const int *connI=_nodal_connec_index->getConstPointer();
5401 const double *coo=_coords->getConstPointer();
5403 for(int i=0;i<nbOfCells;i++,pt++)
5405 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5408 case INTERP_KERNEL::NORM_TRI3:
5410 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5411 *pt=INTERP_KERNEL::triAspectRatio(tmp);
5414 case INTERP_KERNEL::NORM_QUAD4:
5416 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5417 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5420 case INTERP_KERNEL::NORM_TETRA4:
5422 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5423 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5429 conn+=connI[i+1]-connI[i];
5431 ret->setName("AspectRatio");
5432 ret->synchronizeTimeWithSupport();
5437 * The returned newly created field has to be managed by the caller.
5438 * 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.
5439 * This method for the moment only deals with NORM_QUAD4 geometric type.
5440 * If a cell has an another type an exception will be thrown.
5442 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
5445 int spaceDim=getSpaceDimension();
5446 int meshDim=getMeshDimension();
5448 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5451 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5453 int nbOfCells=getNumberOfCells();
5454 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5455 arr->alloc(nbOfCells,1);
5456 double *pt=arr->getPointer();
5457 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5458 const int *conn=_nodal_connec->getConstPointer();
5459 const int *connI=_nodal_connec_index->getConstPointer();
5460 const double *coo=_coords->getConstPointer();
5462 for(int i=0;i<nbOfCells;i++,pt++)
5464 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5467 case INTERP_KERNEL::NORM_QUAD4:
5469 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5470 *pt=INTERP_KERNEL::quadWarp(tmp);
5474 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5476 conn+=connI[i+1]-connI[i];
5478 ret->setName("Warp");
5479 ret->synchronizeTimeWithSupport();
5484 * The returned newly created field has to be managed by the caller.
5485 * 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.
5486 * This method for the moment only deals with NORM_QUAD4 geometric type.
5487 * If a cell has an another type an exception will be thrown.
5489 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5492 int spaceDim=getSpaceDimension();
5493 int meshDim=getMeshDimension();
5495 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5497 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5498 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5500 int nbOfCells=getNumberOfCells();
5501 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5502 arr->alloc(nbOfCells,1);
5503 double *pt=arr->getPointer();
5504 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5505 const int *conn=_nodal_connec->getConstPointer();
5506 const int *connI=_nodal_connec_index->getConstPointer();
5507 const double *coo=_coords->getConstPointer();
5509 for(int i=0;i<nbOfCells;i++,pt++)
5511 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5514 case INTERP_KERNEL::NORM_QUAD4:
5516 FillInCompact3DMode(3,4,conn+1,coo,tmp);
5517 *pt=INTERP_KERNEL::quadSkew(tmp);
5521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5523 conn+=connI[i+1]-connI[i];
5525 ret->setName("Skew");
5526 ret->synchronizeTimeWithSupport();
5531 * This method aggregate the bbox of each cell and put it into bbox parameter.
5532 * @param bbox out parameter of size 2*spacedim*nbOfcells.
5534 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5536 int spaceDim=getSpaceDimension();
5537 int nbOfCells=getNumberOfCells();
5538 bbox.resize(2*nbOfCells*spaceDim);
5539 for(int i=0;i<nbOfCells*spaceDim;i++)
5541 bbox[2*i]=std::numeric_limits<double>::max();
5542 bbox[2*i+1]=-std::numeric_limits<double>::max();
5544 const double *coordsPtr=_coords->getConstPointer();
5545 const int *conn=_nodal_connec->getConstPointer();
5546 const int *connI=_nodal_connec_index->getConstPointer();
5547 for(int i=0;i<nbOfCells;i++)
5549 int offset=connI[i]+1;
5550 int nbOfNodesForCell=connI[i+1]-offset;
5551 for(int j=0;j<nbOfNodesForCell;j++)
5553 int nodeId=conn[offset+j];
5555 for(int k=0;k<spaceDim;k++)
5557 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5558 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5566 namespace ParaMEDMEMImpl
5571 ConnReader(const int *c, int val):_conn(c),_val(val) { }
5572 bool operator() (const int& pos) { return _conn[pos]!=_val; }
5581 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5582 bool operator() (const int& pos) { return _conn[pos]==_val; }
5592 * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5593 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5594 * 'this' is composed in cell types.
5595 * The returned array is of size 3*n where n is the number of different types present in 'this'.
5596 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
5597 * This parameter is kept only for compatibility with other methode listed above.
5599 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5601 checkConnectivityFullyDefined();
5602 const int *conn=_nodal_connec->getConstPointer();
5603 const int *connI=_nodal_connec_index->getConstPointer();
5604 const int *work=connI;
5605 int nbOfCells=getNumberOfCells();
5606 std::size_t n=getAllTypes().size();
5607 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5608 std::set<INTERP_KERNEL::NormalizedCellType> types;
5609 for(std::size_t i=0;work!=connI+nbOfCells;i++)
5611 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5612 if(types.find(typ)!=types.end())
5614 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5615 oss << " is not contiguous !";
5616 throw INTERP_KERNEL::Exception(oss.str().c_str());
5620 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5621 ret[3*i+1]=(int)std::distance(work,work2);
5628 * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5629 * only for types cell, type node is not managed.
5630 * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5631 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5632 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5633 * If 2 or more same geometric type is in 'code' and exception is thrown too.
5635 * This method firstly checks
5636 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5637 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5638 * an exception is thrown too.
5640 * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5641 * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
5642 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5644 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5647 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5648 std::size_t sz=code.size();
5651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5652 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5654 for(std::size_t i=0;i<n;i++)
5655 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5657 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5659 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5660 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5663 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5664 if(idsPerType.empty())
5666 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5668 if(types.size()==_types.size())
5671 DataArrayInt *ret=DataArrayInt::New();
5673 int *retPtr=ret->getPointer();
5674 const int *connI=_nodal_connec_index->getConstPointer();
5675 const int *conn=_nodal_connec->getConstPointer();
5676 int nbOfCells=getNumberOfCells();
5679 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5681 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5682 int offset=(int)std::distance(connI,i);
5683 if(code[3*kk+2]==-1)
5685 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5686 std::size_t pos2=std::distance(i,j);
5687 for(std::size_t k=0;k<pos2;k++)
5688 *retPtr++=(int)k+offset;
5693 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5694 retPtr,std::bind2nd(std::plus<int>(),offset));
5701 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
5702 * 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.
5703 * 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.
5704 * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
5706 * @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.
5707 * @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,
5708 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5709 * @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.
5710 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5711 * @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
5713 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5715 if(profile->getNumberOfComponents()!=1)
5716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5717 checkConnectivityFullyDefined();
5718 const int *conn=_nodal_connec->getConstPointer();
5719 const int *connI=_nodal_connec_index->getConstPointer();
5720 int nbOfCells=getNumberOfCells();
5721 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5722 std::vector<int> typeRangeVals(1);
5723 for(const int *i=connI;i!=connI+nbOfCells;)
5725 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5726 if(std::find(types.begin(),types.end(),curType)!=types.end())
5728 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5730 types.push_back(curType);
5731 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5732 typeRangeVals.push_back((int)std::distance(connI,i));
5735 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5736 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5741 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5742 code.resize(3*nbOfCastsFinal);
5743 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5744 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5745 for(int i=0;i<nbOfCastsFinal;i++)
5747 int castId=castsPresent->getIJ(i,0);
5748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5749 idsInPflPerType2.push_back(tmp3);
5750 code[3*i]=(int)types[castId];
5751 code[3*i+1]=tmp3->getNumberOfTuples();
5752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5753 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5755 tmp4->copyStringInfoFrom(*profile);
5756 idsPerType2.push_back(tmp4);
5757 code[3*i+2]=(int)idsPerType2.size()-1;
5764 std::size_t sz2=idsInPflPerType2.size();
5765 idsInPflPerType.resize(sz2);
5766 for(std::size_t i=0;i<sz2;i++)
5768 DataArrayInt *locDa=idsInPflPerType2[i];
5770 idsInPflPerType[i]=locDa;
5772 std::size_t sz=idsPerType2.size();
5773 idsPerType.resize(sz);
5774 for(std::size_t i=0;i<sz;i++)
5776 DataArrayInt *locDa=idsPerType2[i];
5778 idsPerType[i]=locDa;
5783 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5784 * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5785 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5786 * 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.
5788 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5790 checkFullyDefined();
5791 nM1LevMesh->checkFullyDefined();
5792 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5793 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5794 if(_coords!=nM1LevMesh->getCoords())
5795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5798 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5800 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5801 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5802 tmp->setConnectivity(tmp0,tmp1);
5803 tmp->renumberCells(ret0->getConstPointer(),false);
5804 revDesc=tmp->getNodalConnectivity();
5805 revDescIndx=tmp->getNodalConnectivityIndex();
5806 DataArrayInt *ret=0;
5807 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5810 ret->getMaxValue(tmp2);
5812 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5813 throw INTERP_KERNEL::Exception(oss.str().c_str());
5818 revDescIndx->incrRef();
5821 meshnM1Old2New=ret0;
5826 * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5827 * It avoids to deal with renum in MEDLoader so it is usefull for MED file R/W with multi types.
5828 * This method returns a newly allocated array old2New.
5829 * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5831 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5833 checkConnectivityFullyDefined();
5834 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5835 renumberCells(ret->getConstPointer(),false);
5840 * This methods checks that cells are sorted by their types.
5841 * This method makes asumption (no check) that connectivity is correctly set before calling.
5843 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5845 checkFullyDefined();
5846 const int *conn=_nodal_connec->getConstPointer();
5847 const int *connI=_nodal_connec_index->getConstPointer();
5848 int nbOfCells=getNumberOfCells();
5849 std::set<INTERP_KERNEL::NormalizedCellType> types;
5850 for(const int *i=connI;i!=connI+nbOfCells;)
5852 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5853 if(types.find(curType)!=types.end())
5855 types.insert(curType);
5856 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5862 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5863 * The geometric type order is specified by MED file.
5865 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5867 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
5869 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5873 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5874 * that the order is specified in array defined by [orderBg,orderEnd).
5876 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5878 checkFullyDefined();
5879 const int *conn=_nodal_connec->getConstPointer();
5880 const int *connI=_nodal_connec_index->getConstPointer();
5881 int nbOfCells=getNumberOfCells();
5883 for(const int *i=connI;i!=connI+nbOfCells;)
5885 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5886 int pos=(int)std::distance(orderBg,std::find(orderBg,orderEnd,curType));
5890 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5896 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5897 * 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
5898 * 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'.
5900 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
5902 checkConnectivityFullyDefined();
5903 int nbOfCells=getNumberOfCells();
5904 const int *conn=_nodal_connec->getConstPointer();
5905 const int *connI=_nodal_connec_index->getConstPointer();
5906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
5907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
5908 tmpa->alloc(nbOfCells,1);
5909 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5910 tmpb->fillWithZero();
5911 int *tmp=tmpa->getPointer();
5912 int *tmp2=tmpb->getPointer();
5913 for(const int *i=connI;i!=connI+nbOfCells;i++)
5915 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5918 int pos=(int)std::distance(orderBg,where);
5920 tmp[std::distance(connI,i)]=pos;
5924 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5925 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5926 oss << " has a type " << cm.getRepr() << " not in input array of type !";
5927 throw INTERP_KERNEL::Exception(oss.str().c_str());
5930 nbPerType=tmpb.retn();
5935 * 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'.
5936 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5937 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5938 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5940 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
5942 DataArrayInt *nbPerType=0;
5943 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5944 nbPerType->decrRef();
5945 return tmpa->buildPermArrPerLevel();
5949 * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
5950 * The number of cells remains unchanged after the call of this method.
5951 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5952 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5954 * @return the array giving the correspondance old to new.
5956 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5958 checkFullyDefined();
5960 const int *conn=_nodal_connec->getConstPointer();
5961 const int *connI=_nodal_connec_index->getConstPointer();
5962 int nbOfCells=getNumberOfCells();
5963 std::vector<INTERP_KERNEL::NormalizedCellType> types;
5964 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5965 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5967 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5968 types.push_back(curType);
5969 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5971 DataArrayInt *ret=DataArrayInt::New();
5972 ret->alloc(nbOfCells,1);
5973 int *retPtr=ret->getPointer();
5974 std::fill(retPtr,retPtr+nbOfCells,-1);
5976 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5978 for(const int *i=connI;i!=connI+nbOfCells;i++)
5979 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5980 retPtr[std::distance(connI,i)]=newCellId++;
5982 renumberCells(retPtr,false);
5987 * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
5988 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5989 * This method makes asumption that connectivity is correctly set before calling.
5991 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5993 checkFullyDefined();
5994 const int *conn=_nodal_connec->getConstPointer();
5995 const int *connI=_nodal_connec_index->getConstPointer();
5996 int nbOfCells=getNumberOfCells();
5997 std::vector<MEDCouplingUMesh *> ret;
5998 for(const int *i=connI;i!=connI+nbOfCells;)
6000 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6001 int beginCellId=(int)std::distance(connI,i);
6002 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6003 int endCellId=(int)std::distance(connI,i);
6004 int sz=endCellId-beginCellId;
6005 int *cells=new int[sz];
6006 for(int j=0;j<sz;j++)
6007 cells[j]=beginCellId+j;
6008 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6016 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6017 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6018 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6019 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6020 * are not used here to avoid the build of big permutation array.
6022 * \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
6023 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6024 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6025 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6026 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6027 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6028 * \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
6029 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6031 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6032 DataArrayInt *&szOfCellGrpOfSameType,
6033 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6035 std::vector<const MEDCouplingUMesh *> ms2;
6036 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6039 (*it)->checkConnectivityFullyDefined();
6043 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6044 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6045 int meshDim=ms2[0]->getMeshDimension();
6046 std::vector<const MEDCouplingUMesh *> m1ssm;
6047 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6049 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6050 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6053 ret1->alloc(0,1); ret2->alloc(0,1);
6054 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6056 if(meshDim!=(*it)->getMeshDimension())
6057 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6058 if(refCoo!=(*it)->getCoords())
6059 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6060 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6061 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6062 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6063 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6065 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6066 m1ssmSingleAuto.push_back(singleCell);
6067 m1ssmSingle.push_back(singleCell);
6068 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6071 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6073 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6074 for(std::size_t i=0;i<m1ssm.size();i++)
6075 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6076 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6077 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6078 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6083 * This method returns a newly created DataArrayInt instance.
6084 * This method retrieves cell ids in [begin,end) that have the type 'type'.
6086 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6088 checkFullyDefined();
6089 const int *conn=_nodal_connec->getConstPointer();
6090 const int *connIndex=_nodal_connec_index->getConstPointer();
6091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6092 for(const int *w=begin;w!=end;w++)
6093 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6094 ret->pushBackSilent(*w);
6099 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6100 * are in [0:getNumberOfCells())
6102 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6104 checkFullyDefined();
6105 const int *conn=_nodal_connec->getConstPointer();
6106 const int *connI=_nodal_connec_index->getConstPointer();
6107 int nbOfCells=getNumberOfCells();
6108 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6109 int *tmp=new int[nbOfCells];
6110 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6113 for(const int *i=connI;i!=connI+nbOfCells;i++)
6114 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6115 tmp[std::distance(connI,i)]=j++;
6117 DataArrayInt *ret=DataArrayInt::New();
6118 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6119 ret->copyStringInfoFrom(*da);
6120 int *retPtr=ret->getPointer();
6121 const int *daPtr=da->getConstPointer();
6122 int nbOfElems=da->getNbOfElems();
6123 for(int k=0;k<nbOfElems;k++)
6124 retPtr[k]=tmp[daPtr[k]];
6130 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6131 * This method \b works \b for mesh sorted by type.
6132 * cells whose ids is in 'idsPerGeoType' array.
6133 * This method conserves coords and name of mesh.
6135 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6137 std::vector<int> code=getDistributionOfTypes();
6138 std::size_t nOfTypesInThis=code.size()/3;
6139 int sz=0,szOfType=0;
6140 for(std::size_t i=0;i<nOfTypesInThis;i++)
6145 szOfType=code[3*i+1];
6147 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6148 if(*work<0 || *work>=szOfType)
6150 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6151 oss << ". It should be in [0," << szOfType << ") !";
6152 throw INTERP_KERNEL::Exception(oss.str().c_str());
6154 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6155 int *idsPtr=idsTokeep->getPointer();
6157 for(std::size_t i=0;i<nOfTypesInThis;i++)
6160 for(int j=0;j<code[3*i+1];j++)
6163 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6164 offset+=code[3*i+1];
6166 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6167 ret->copyTinyInfoFrom(this);
6172 * This method returns a vector of size 'this->getNumberOfCells()'.
6173 * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
6175 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6177 int ncell=getNumberOfCells();
6178 std::vector<bool> ret(ncell);
6179 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6180 const int *c=getNodalConnectivity()->getConstPointer();
6181 for(int i=0;i<ncell;i++)
6183 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6184 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6185 ret[i]=cm.isQuadratic();
6191 * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
6193 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6195 if(other->getType()!=UNSTRUCTURED)
6196 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6197 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6198 return MergeUMeshes(this,otherC);
6202 * Returns an array with this->getNumberOfCells() tuples and this->getSpaceDimension() dimension.
6203 * The false barycenter is computed that is to say barycenter of a cell is computed using average on each
6204 * components of coordinates of the cell.
6206 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6208 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6209 int spaceDim=getSpaceDimension();
6210 int nbOfCells=getNumberOfCells();
6211 ret->alloc(nbOfCells,spaceDim);
6212 ret->copyStringInfoFrom(*getCoords());
6213 double *ptToFill=ret->getPointer();
6214 const int *nodal=_nodal_connec->getConstPointer();
6215 const int *nodalI=_nodal_connec_index->getConstPointer();
6216 const double *coor=_coords->getConstPointer();
6217 for(int i=0;i<nbOfCells;i++)
6219 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6220 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6227 * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
6228 * 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().
6229 * No check of that will be done !
6231 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6233 DataArrayDouble *ret=DataArrayDouble::New();
6234 int spaceDim=getSpaceDimension();
6235 int nbOfTuple=(int)std::distance(begin,end);
6236 ret->alloc(nbOfTuple,spaceDim);
6237 double *ptToFill=ret->getPointer();
6238 double *tmp=new double[spaceDim];
6239 const int *nodal=_nodal_connec->getConstPointer();
6240 const int *nodalI=_nodal_connec_index->getConstPointer();
6241 const double *coor=_coords->getConstPointer();
6242 for(const int *w=begin;w!=end;w++)
6244 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6245 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6253 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6256 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
6259 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6260 da->checkAllocated();
6261 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
6263 int nbOfTuples=da->getNumberOfTuples();
6264 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6266 c->alloc(2*nbOfTuples,1);
6267 cI->alloc(nbOfTuples+1,1);
6268 int *cp=c->getPointer();
6269 int *cip=cI->getPointer();
6271 for(int i=0;i<nbOfTuples;i++)
6273 *cp++=INTERP_KERNEL::NORM_POINT1;
6277 ret->setConnectivity(c,cI,true);
6282 * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
6283 * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
6285 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6287 std::vector<const MEDCouplingUMesh *> tmp(2);
6288 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6289 return MergeUMeshes(tmp);
6293 * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
6294 * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
6295 * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
6296 * cells in meshes in 'a' (in the same order too).
6298 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6300 std::size_t sz=a.size();
6302 return MergeUMeshesLL(a);
6303 for(std::size_t ii=0;ii<sz;ii++)
6306 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6307 throw INTERP_KERNEL::Exception(oss.str().c_str());
6309 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
6310 std::vector< const MEDCouplingUMesh * > aa(sz);
6312 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6314 const MEDCouplingUMesh *cur=a[i];
6315 const DataArrayDouble *coo=cur->getCoords();
6317 spaceDim=coo->getNumberOfComponents();
6320 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6321 for(std::size_t i=0;i<sz;i++)
6323 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6326 return MergeUMeshesLL(aa);
6331 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6334 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
6335 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
6336 int meshDim=(*it)->getMeshDimension();
6337 int nbOfCells=(*it)->getNumberOfCells();
6338 int meshLgth=(*it++)->getMeshLength();
6339 for(;it!=a.end();it++)
6341 if(meshDim!=(*it)->getMeshDimension())
6342 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
6343 nbOfCells+=(*it)->getNumberOfCells();
6344 meshLgth+=(*it)->getMeshLength();
6346 std::vector<const MEDCouplingPointSet *> aps(a.size());
6347 std::copy(a.begin(),a.end(),aps.begin());
6348 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
6349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
6350 ret->setCoords(pts);
6351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6352 c->alloc(meshLgth,1);
6353 int *cPtr=c->getPointer();
6354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6355 cI->alloc(nbOfCells+1,1);
6356 int *cIPtr=cI->getPointer();
6360 for(it=a.begin();it!=a.end();it++)
6362 int curNbOfCell=(*it)->getNumberOfCells();
6363 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
6364 const int *curC=(*it)->_nodal_connec->getConstPointer();
6365 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
6366 for(int j=0;j<curNbOfCell;j++)
6368 const int *src=curC+curCI[j];
6370 for(;src!=curC+curCI[j+1];src++,cPtr++)
6378 offset+=curCI[curNbOfCell];
6379 offset2+=(*it)->getNumberOfNodes();
6382 ret->setConnectivity(c,cI,true);
6389 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6390 * 'meshes' must be a non empty vector.
6392 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6394 std::vector<const MEDCouplingUMesh *> tmp(2);
6395 tmp[0]=mesh1; tmp[1]=mesh2;
6396 return MergeUMeshesOnSameCoords(tmp);
6400 * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6401 * 'meshes' must be a non empty vector.
6403 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6406 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6407 for(std::size_t ii=0;ii<meshes.size();ii++)
6410 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6411 throw INTERP_KERNEL::Exception(oss.str().c_str());
6413 const DataArrayDouble *coords=meshes.front()->getCoords();
6414 int meshDim=meshes.front()->getMeshDimension();
6415 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6417 int meshIndexLgth=0;
6418 for(;iter!=meshes.end();iter++)
6420 if(coords!=(*iter)->getCoords())
6421 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6422 if(meshDim!=(*iter)->getMeshDimension())
6423 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6424 meshLgth+=(*iter)->getMeshLength();
6425 meshIndexLgth+=(*iter)->getNumberOfCells();
6427 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
6428 nodal->alloc(meshLgth,1);
6429 int *nodalPtr=nodal->getPointer();
6430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
6431 nodalIndex->alloc(meshIndexLgth+1,1);
6432 int *nodalIndexPtr=nodalIndex->getPointer();
6434 for(iter=meshes.begin();iter!=meshes.end();iter++)
6436 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
6437 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
6438 int nbOfCells=(*iter)->getNumberOfCells();
6439 int meshLgth2=(*iter)->getMeshLength();
6440 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6441 if(iter!=meshes.begin())
6442 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6444 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6447 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6448 ret->setName("merge");
6449 ret->setMeshDimension(meshDim);
6450 ret->setConnectivity(nodal,nodalIndex,true);
6451 ret->setCoords(coords);
6456 * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
6457 * 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)
6459 * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
6460 * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
6461 * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
6462 * The arrays contained in 'corr' parameter are returned with refcounter set to one.
6463 * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
6464 * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
6465 * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
6467 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6469 //All checks are delegated to MergeUMeshesOnSameCoords
6470 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6472 corr.resize(meshes.size());
6473 std::size_t nbOfMeshes=meshes.size();
6475 const int *o2nPtr=o2n->getConstPointer();
6476 for(std::size_t i=0;i<nbOfMeshes;i++)
6478 DataArrayInt *tmp=DataArrayInt::New();
6479 int curNbOfCells=meshes[i]->getNumberOfCells();
6480 tmp->alloc(curNbOfCells,1);
6481 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6482 offset+=curNbOfCells;
6483 tmp->setName(meshes[i]->getName());
6490 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6491 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6492 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6493 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6495 * This method performs nothing if size of \b meshes is in [0,1].
6496 * This method is particulary usefull in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6497 * coordinates DataArrayDouble instance.
6499 * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6501 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6503 std::size_t sz=meshes.size();
6506 std::vector< const DataArrayDouble * > coords(meshes.size());
6507 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6508 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6512 (*it)->checkConnectivityFullyDefined();
6513 const DataArrayDouble *coo=(*it)->getCoords();
6518 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6519 oss << " has no coordinate array defined !";
6520 throw INTERP_KERNEL::Exception(oss.str().c_str());
6525 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6526 oss << " is null !";
6527 throw INTERP_KERNEL::Exception(oss.str().c_str());
6530 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6531 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6532 int offset=(*it)->getNumberOfNodes();
6533 (*it++)->setCoords(res);
6534 for(;it!=meshes.end();it++)
6536 int oldNumberOfNodes=(*it)->getNumberOfNodes();
6537 (*it)->setCoords(res);
6538 (*it)->shiftNodeNumbersInConn(offset);
6539 offset+=oldNumberOfNodes;
6544 * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6545 * \b meshes should have a good coherency (connectivity and coordinates well defined).
6546 * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6547 * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6548 * 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.
6550 * This method performs nothing if size of \b meshes is empty.
6551 * This method is particulary usefull in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6552 * coordinates DataArrayDouble instance.
6554 * \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.
6555 * \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.
6557 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6561 std::set<const DataArrayDouble *> s;
6562 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6565 s.insert((*it)->getCoords());
6568 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 !";
6569 throw INTERP_KERNEL::Exception(oss.str().c_str());
6574 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 !";
6575 throw INTERP_KERNEL::Exception(oss.str().c_str());
6577 const DataArrayDouble *coo=*(s.begin());
6581 DataArrayInt *comm,*commI;
6582 coo->findCommonTuples(eps,-1,comm,commI);
6583 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6584 int oldNbOfNodes=coo->getNumberOfTuples();
6586 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6587 if(oldNbOfNodes==newNbOfNodes)
6589 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6590 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6592 (*it)->renumberNodesInConn(o2n->getConstPointer());
6593 (*it)->setCoords(newCoords);
6598 * 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.
6599 * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6600 * @param isQuad specifies the policy of connectivity.
6601 * @ret in/out parameter in which the result will be append
6603 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6605 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6606 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6607 ret.push_back(cm.getExtrudedType());
6608 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6611 case INTERP_KERNEL::NORM_POINT1:
6613 ret.push_back(connBg[1]);
6614 ret.push_back(connBg[1]+nbOfNodesPerLev);
6617 case INTERP_KERNEL::NORM_SEG2:
6619 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6620 ret.insert(ret.end(),conn,conn+4);
6623 case INTERP_KERNEL::NORM_SEG3:
6625 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6626 ret.insert(ret.end(),conn,conn+8);
6629 case INTERP_KERNEL::NORM_QUAD4:
6631 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6632 ret.insert(ret.end(),conn,conn+8);
6635 case INTERP_KERNEL::NORM_TRI3:
6637 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6638 ret.insert(ret.end(),conn,conn+6);
6641 case INTERP_KERNEL::NORM_TRI6:
6643 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,
6644 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6645 ret.insert(ret.end(),conn,conn+15);
6648 case INTERP_KERNEL::NORM_QUAD8:
6651 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6652 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6653 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6655 ret.insert(ret.end(),conn,conn+20);
6658 case INTERP_KERNEL::NORM_POLYGON:
6660 std::back_insert_iterator< std::vector<int> > ii(ret);
6661 std::copy(connBg+1,connEnd,ii);
6663 std::reverse_iterator<const int *> rConnBg(connEnd);
6664 std::reverse_iterator<const int *> rConnEnd(connBg+1);
6665 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6666 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6667 for(std::size_t i=0;i<nbOfRadFaces;i++)
6670 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6671 std::copy(conn,conn+4,ii);
6676 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6681 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6683 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6685 double v[3]={0.,0.,0.};
6686 std::size_t sz=std::distance(begin,end);
6689 for(std::size_t i=0;i<sz;i++)
6691 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];
6692 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6693 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6695 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6699 * The polyhedron is specfied by its connectivity nodes in [begin,end).
6701 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6703 std::vector<std::pair<int,int> > edges;
6704 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6705 const int *bgFace=begin;
6706 for(std::size_t i=0;i<nbOfFaces;i++)
6708 const int *endFace=std::find(bgFace+1,end,-1);
6709 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6710 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6712 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6713 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6715 edges.push_back(p1);
6719 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6723 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
6725 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6727 double vec0[3],vec1[3];
6728 std::size_t sz=std::distance(begin,end);
6730 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6731 int nbOfNodes=(int)sz/2;
6732 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6733 const double *pt0=coords+3*begin[0];
6734 const double *pt1=coords+3*begin[nbOfNodes];
6735 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6736 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6739 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6741 std::size_t sz=std::distance(begin,end);
6742 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6743 std::size_t nbOfNodes(sz/2);
6744 std::copy(begin,end,(int *)tmp);
6745 for(std::size_t j=1;j<nbOfNodes;j++)
6747 begin[j]=tmp[nbOfNodes-j];
6748 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6752 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6754 std::size_t sz=std::distance(begin,end);
6756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
6757 double vec0[3],vec1[3];
6758 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6759 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];
6760 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;
6763 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
6765 std::size_t sz=std::distance(begin,end);
6767 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
6769 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
6770 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
6771 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
6775 * 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)
6776 * 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
6779 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6780 * \param [in] coords the coordinates with nb of components exactly equal to 3
6781 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6782 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6783 * \param [out] res the result is put at the end of the vector without any alteration of the data.
6785 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
6787 int nbFaces=std::count(begin+1,end,-1)+1;
6788 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6789 double *vPtr=v->getPointer();
6790 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6791 double *pPtr=p->getPointer();
6792 const int *stFaceConn=begin+1;
6793 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6795 const int *endFaceConn=std::find(stFaceConn,end,-1);
6796 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
6797 stFaceConn=endFaceConn+1;
6799 pPtr=p->getPointer(); vPtr=v->getPointer();
6800 DataArrayInt *comm1=0,*commI1=0;
6801 v->findCommonTuples(eps,-1,comm1,commI1);
6802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6803 const int *comm1Ptr=comm1->getConstPointer();
6804 const int *commI1Ptr=commI1->getConstPointer();
6805 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6806 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
6808 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
6809 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
6810 mm->finishInsertingCells();
6812 for(int i=0;i<nbOfGrps1;i++)
6814 int vecId=comm1Ptr[commI1Ptr[i]];
6815 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6816 DataArrayInt *comm2=0,*commI2=0;
6817 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
6818 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
6819 const int *comm2Ptr=comm2->getConstPointer();
6820 const int *commI2Ptr=commI2->getConstPointer();
6821 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
6822 for(int j=0;j<nbOfGrps2;j++)
6824 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
6826 res->insertAtTheEnd(begin,end);
6827 res->pushBackSilent(-1);
6831 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
6832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
6833 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6834 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
6835 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
6836 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
6837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
6838 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
6839 const int *idsNodePtr=idsNode->getConstPointer();
6840 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];
6841 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
6842 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
6843 if(std::abs(norm)>eps)
6845 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
6846 mm3->rotate(center,vec,angle);
6848 mm3->changeSpaceDimension(2);
6849 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
6850 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
6851 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
6852 int nbOfCells=mm4->getNumberOfCells();
6853 for(int k=0;k<nbOfCells;k++)
6856 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
6857 res->pushBackSilent(idsNodePtr[*work]);
6858 res->pushBackSilent(-1);
6863 res->popBackSilent();
6867 * 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
6868 * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
6870 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
6871 * \param [in] coords coordinates expected to have 3 components.
6872 * \param [in] begin start of the nodal connectivity of the face.
6873 * \param [in] end end of the nodal connectivity (excluded) of the face.
6874 * \param [out] v the normalized vector of size 3
6875 * \param [out] p the pos of plane
6877 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
6879 std::size_t nbPoints=std::distance(begin,end);
6881 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
6884 bool refFound=false;
6885 for(;j<nbPoints-1 && !refFound;j++)
6887 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
6888 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
6889 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
6890 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
6894 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
6897 for(std::size_t i=j;i<nbPoints-1;i++)
6900 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
6901 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
6902 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
6903 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
6906 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
6907 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];
6908 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
6911 v[0]/=norm; v[1]/=norm; v[2]/=norm;
6912 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
6916 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
6920 * This method tries to obtain a well oriented polyhedron.
6921 * If the algorithm fails, an exception will be thrown.
6923 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
6925 std::list< std::pair<int,int> > edgesOK,edgesFinished;
6926 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6927 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
6929 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
6930 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6931 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
6933 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
6936 std::size_t smthChanged=0;
6937 for(std::size_t i=0;i<nbOfFaces;i++)
6939 endFace=std::find(bgFace+1,end,-1);
6940 nbOfEdgesInFace=std::distance(bgFace,endFace);
6944 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6946 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6947 std::pair<int,int> p2(p1.second,p1.first);
6948 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
6949 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
6950 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
6955 std::reverse(bgFace+1,endFace);
6956 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6958 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6959 std::pair<int,int> p2(p1.second,p1.first);
6960 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
6961 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
6962 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
6963 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
6964 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
6965 if(it!=edgesOK.end())
6968 edgesFinished.push_back(p1);
6971 edgesOK.push_back(p1);
6978 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
6980 if(!edgesOK.empty())
6981 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
6982 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
6983 {//not lucky ! The first face was not correctly oriented : reorient all faces...
6985 for(std::size_t i=0;i<nbOfFaces;i++)
6987 endFace=std::find(bgFace+1,end,-1);
6988 std::reverse(bgFace+1,endFace);
6995 * This method makes the assumption spacedimension == meshdimension == 2.
6996 * This method works only for linear cells.
6998 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7000 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7002 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7003 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7004 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7006 int nbOfNodesExpected=m->getNumberOfNodes();
7007 if(m->getNumberOfCells()!=nbOfNodesExpected)
7008 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7010 const int *n2oPtr=n2o->getConstPointer();
7011 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7012 m->getReverseNodalConnectivity(revNodal,revNodalI);
7013 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7014 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7015 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7017 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7018 if(nbOfNodesExpected<1)
7021 int prevNode=nodalPtr[nodalIPtr[0]+1];
7022 *work++=n2oPtr[prevNode];
7023 for(int i=1;i<nbOfNodesExpected;i++)
7025 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7027 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7028 conn.erase(prevNode);
7031 int curNode=*(conn.begin());
7032 *work++=n2oPtr[curNode];
7033 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7034 shar.erase(prevCell);
7037 prevCell=*(shar.begin());
7041 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7044 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7047 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7053 * This method makes the assumption spacedimension == meshdimension == 3.
7054 * This method works only for linear cells.
7056 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7058 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7060 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7061 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7062 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7063 const int *conn=m->getNodalConnectivity()->getConstPointer();
7064 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7065 int nbOfCells=m->getNumberOfCells();
7066 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7067 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7070 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7071 for(int i=1;i<nbOfCells;i++)
7074 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7080 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7081 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7083 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7087 for(int i=0;i<nbOfNodesInCell;i++)
7088 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7089 else if(spaceDim==2)
7091 for(int i=0;i<nbOfNodesInCell;i++)
7093 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7098 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7101 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7103 int nbOfCells=getNumberOfCells();
7105 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7106 static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,-1,23,-1,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,-1,-1,-1,25,42,-1,4};
7107 ofs << " <" << getVTKDataSetType() << ">\n";
7108 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7109 ofs << " <PointData>\n" << pointData << std::endl;
7110 ofs << " </PointData>\n";
7111 ofs << " <CellData>\n" << cellData << std::endl;
7112 ofs << " </CellData>\n";
7113 ofs << " <Points>\n";
7114 if(getSpaceDimension()==3)
7115 _coords->writeVTK(ofs,8,"Points");
7118 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7119 coo->writeVTK(ofs,8,"Points");
7121 ofs << " </Points>\n";
7122 ofs << " <Cells>\n";
7123 const int *cPtr=_nodal_connec->getConstPointer();
7124 const int *cIPtr=_nodal_connec_index->getConstPointer();
7125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7129 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7130 int szFaceOffsets=0,szConn=0;
7131 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7134 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7137 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7138 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7142 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7143 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7144 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7145 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7146 w4=std::copy(c.begin(),c.end(),w4);
7149 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
7150 types->writeVTK(ofs,8,"UInt8","types");
7151 offsets->writeVTK(ofs,8,"Int32","offsets");
7152 if(szFaceOffsets!=0)
7153 {//presence of Polyhedra
7154 connectivity->reAlloc(szConn);
7155 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
7156 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7157 w1=faces->getPointer();
7158 for(int i=0;i<nbOfCells;i++)
7159 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7161 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7163 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7164 for(int j=0;j<nbFaces;j++)
7166 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7167 *w1++=(int)std::distance(w6,w5);
7168 w1=std::copy(w6,w5,w1);
7172 faces->writeVTK(ofs,8,"Int32","faces");
7174 connectivity->writeVTK(ofs,8,"Int32","connectivity");
7175 ofs << " </Cells>\n";
7176 ofs << " </Piece>\n";
7177 ofs << " </" << getVTKDataSetType() << ">\n";
7180 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
7182 return std::string("UnstructuredGrid");
7187 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
7189 m1->checkFullyDefined();
7190 m2->checkFullyDefined();
7191 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
7192 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
7193 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
7194 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
7195 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
7196 std::vector<double> addCoo,addCoordsQuadratic;
7197 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
7198 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
7199 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
7200 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
7201 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
7202 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
7203 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
7204 std::vector< std::vector<int> > intersectEdge2;
7205 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
7206 subDiv2.clear(); dd5=0; dd6=0;
7207 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
7208 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
7209 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
7210 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
7212 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
7213 addCooDa->alloc((int)(addCoo.size())/2,2);
7214 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
7215 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
7216 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
7217 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
7218 std::vector<const DataArrayDouble *> coordss(4);
7219 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
7220 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
7221 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
7222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
7223 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
7224 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
7225 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
7226 ret->setConnectivity(conn,connI,true);
7227 ret->setCoords(coo);
7228 cellNb1=c1.retn(); cellNb2=c2.retn();
7234 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
7235 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
7236 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
7237 const std::vector<double>& addCoords,
7238 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
7240 static const int SPACEDIM=2;
7241 std::vector<double> bbox1,bbox2;
7242 const double *coo1=m1->getCoords()->getConstPointer();
7243 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
7244 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
7245 int offset1=m1->getNumberOfNodes();
7246 const double *coo2=m2->getCoords()->getConstPointer();
7247 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
7248 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
7249 int offset2=offset1+m2->getNumberOfNodes();
7250 int offset3=offset2+((int)addCoords.size())/2;
7251 m1->getBoundingBoxForBBTree(bbox1);
7252 m2->getBoundingBoxForBBTree(bbox2);
7253 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
7254 int ncell1=m1->getNumberOfCells();
7256 for(int i=0;i<ncell1;i++)
7258 std::vector<int> candidates2;
7259 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7260 std::map<INTERP_KERNEL::Node *,int> mapp;
7261 std::map<int,INTERP_KERNEL::Node *> mappRev;
7262 INTERP_KERNEL::QuadraticPolygon pol1;
7263 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
7264 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7265 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
7266 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
7267 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
7269 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
7270 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
7271 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
7272 for(it1.first();!it1.finished();it1.next())
7273 edges1.insert(it1.current()->getPtr());
7275 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
7276 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
7278 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7280 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
7281 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
7282 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
7283 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
7284 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
7287 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7289 pol1.initLocationsWithOther(pol2s[ii]);
7290 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
7291 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
7292 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7298 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7300 catch(INTERP_KERNEL::Exception& e)
7302 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();
7303 throw INTERP_KERNEL::Exception(oss.str().c_str());
7306 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
7307 (*it).second->decrRef();
7312 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
7315 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
7316 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
7317 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
7318 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
7319 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
7321 static const int SPACEDIM=2;
7322 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
7323 desc2=DataArrayInt::New();
7324 descIndx2=DataArrayInt::New();
7325 revDesc2=DataArrayInt::New();
7326 revDescIndx2=DataArrayInt::New();
7327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
7328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
7329 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
7330 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
7331 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
7332 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
7333 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
7334 std::vector<double> bbox1,bbox2;
7335 m1Desc->getBoundingBoxForBBTree(bbox1);
7336 m2Desc->getBoundingBoxForBBTree(bbox2);
7337 int ncell1=m1Desc->getNumberOfCells();
7338 int ncell2=m2Desc->getNumberOfCells();
7339 intersectEdge1.resize(ncell1);
7340 colinear2.resize(ncell2);
7341 subDiv2.resize(ncell2);
7342 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
7343 std::vector<int> candidates1(1);
7344 int offset1=m1->getNumberOfNodes();
7345 int offset2=offset1+m2->getNumberOfNodes();
7346 for(int i=0;i<ncell1;i++)
7348 std::vector<int> candidates2;
7349 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7350 if(!candidates2.empty())
7352 std::map<INTERP_KERNEL::Node *,int> map1,map2;
7353 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
7355 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
7356 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
7361 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
7363 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
7364 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
7368 * This method performs the 2nd step of Partition of 2D mesh.
7369 * This method has 4 inputs :
7370 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
7371 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
7372 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
7373 * 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'
7374 * @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'
7375 * @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.
7376 * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
7378 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)
7380 int offset1=m1->getNumberOfNodes();
7381 int ncell=m2->getNumberOfCells();
7382 const int *c=m2->getNodalConnectivity()->getConstPointer();
7383 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
7384 const double *coo=m2->getCoords()->getConstPointer();
7385 const double *cooBis=m1->getCoords()->getConstPointer();
7386 int offset2=offset1+m2->getNumberOfNodes();
7387 intersectEdge.resize(ncell);
7388 for(int i=0;i<ncell;i++,cI++)
7390 const std::vector<int>& divs=subDiv[i];
7391 int nnode=cI[1]-cI[0]-1;
7392 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
7393 std::map<INTERP_KERNEL::Node *, int> mapp22;
7394 for(int j=0;j<nnode;j++)
7396 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
7397 int nnid=c[(*cI)+j+1];
7398 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
7399 mapp22[nn]=nnid+offset1;
7401 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
7402 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
7403 ((*it).second.first)->decrRef();
7404 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
7405 std::map<INTERP_KERNEL::Node *,int> mapp3;
7406 for(std::size_t j=0;j<divs.size();j++)
7409 INTERP_KERNEL::Node *tmp=0;
7411 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
7413 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
7415 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
7419 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
7420 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
7427 * 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).
7428 * 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
7429 * with a plane. The result will be put in 'cut3DSuf' out parameter.
7430 * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
7431 * @param nodesOnPlane, returns all the nodes that are on the plane.
7432 * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
7433 * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
7434 * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
7435 * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
7436 * @param desc is the descending connectivity 3DSurf->3DCurve
7437 * @param descIndx is the descending connectivity index 3DSurf->3DCurve
7438 * @param cut3DSuf input/output param.
7440 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
7441 const int *nodal3DCurve, const int *nodalIndx3DCurve,
7442 const int *desc, const int *descIndx,
7443 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
7445 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
7446 int nbOf3DSurfCell=(int)cut3DSurf.size();
7447 for(int i=0;i<nbOf3DSurfCell;i++)
7449 std::vector<int> res;
7450 int offset=descIndx[i];
7451 int nbOfSeg=descIndx[i+1]-offset;
7452 for(int j=0;j<nbOfSeg;j++)
7454 int edgeId=desc[offset+j];
7455 int status=cut3DCurve[edgeId];
7459 res.push_back(status);
7462 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
7463 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
7471 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7477 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
7478 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
7481 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7485 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
7490 {// case when plane is on a multi colinear edge of a polyhedron
7491 if((int)res.size()==2*nbOfSeg)
7493 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
7496 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
7503 * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
7504 * 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).
7505 * 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
7506 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
7507 * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
7508 * @param desc is the descending connectivity 3D->3DSurf
7509 * @param descIndx is the descending connectivity index 3D->3DSurf
7511 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
7512 const int *desc, const int *descIndx,
7513 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
7515 checkFullyDefined();
7516 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
7518 const int *nodal3D=_nodal_connec->getConstPointer();
7519 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
7520 int nbOfCells=getNumberOfCells();
7521 for(int i=0;i<nbOfCells;i++)
7523 std::map<int, std::set<int> > m;
7524 int offset=descIndx[i];
7525 int nbOfFaces=descIndx[i+1]-offset;
7528 for(int j=0;j<nbOfFaces;j++)
7530 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
7531 if(p.first!=-1 && p.second!=-1)
7535 start=p.first; end=p.second;
7536 m[p.first].insert(p.second);
7537 m[p.second].insert(p.first);
7541 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
7542 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
7543 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7544 INTERP_KERNEL::NormalizedCellType cmsId;
7545 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
7546 start=tmp[0]; end=tmp[nbOfNodesSon-1];
7547 for(unsigned k=0;k<nbOfNodesSon;k++)
7549 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
7550 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
7557 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
7561 std::map<int, std::set<int> >::const_iterator it=m.find(start);
7562 const std::set<int>& s=(*it).second;
7563 std::set<int> s2; s2.insert(prev);
7565 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
7568 int val=*s3.begin();
7569 conn.push_back(start);
7576 conn.push_back(end);
7579 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
7580 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
7581 cellIds->pushBackSilent(i);
7587 * 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
7588 * 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
7589 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7590 * 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
7591 * 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.
7593 * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7595 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
7597 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7600 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7601 if(cm.getDimension()==2)
7603 const int *node=nodalConnBg+1;
7604 int startNode=*node++;
7605 double refX=coords[2*startNode];
7606 for(;node!=nodalConnEnd;node++)
7608 if(coords[2*(*node)]<refX)
7611 refX=coords[2*startNode];
7614 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7618 double angle0=-M_PI/2;
7624 while(nextNode!=startNode)
7628 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7630 if(*node!=tmpOut.back() && *node!=prevNode)
7632 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7633 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7638 res=angle0-angleM+2.*M_PI;
7647 if(nextNode!=startNode)
7649 angle0=angleNext-M_PI;
7652 prevNode=tmpOut.back();
7653 tmpOut.push_back(nextNode);
7656 std::vector<int> tmp3(2*(sz-1));
7657 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7658 std::copy(nodalConnBg+1,nodalConnEnd,it);
7659 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7661 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7664 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7666 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7671 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7672 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7680 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7684 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7685 * 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.
7687 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7688 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7689 * \param [in,out] arr array in which the remove operation will be done.
7690 * \param [in,out] arrIndx array in the remove operation will modify
7691 * \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])
7692 * \return true if \b arr and \b arrIndx have been modified, false if not.
7694 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7696 if(!arrIndx || !arr)
7697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7698 if(offsetForRemoval<0)
7699 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7700 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7701 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7702 int *arrIPtr=arrIndx->getPointer();
7705 const int *arrPtr=arr->getConstPointer();
7706 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7707 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7709 if(*arrIPtr-previousArrI>offsetForRemoval)
7711 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7713 if(s.find(*work)==s.end())
7714 arrOut.push_back(*work);
7717 previousArrI=*arrIPtr;
7718 *arrIPtr=(int)arrOut.size();
7720 if(arr->getNumberOfTuples()==(int)arrOut.size())
7722 arr->alloc((int)arrOut.size(),1);
7723 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7728 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7729 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7730 * The selection of extraction is done standardly in new2old format.
7731 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
7733 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7734 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7735 * \param [in] arrIn arr origin array from which the extraction will be done.
7736 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7737 * \param [out] arrOut the resulting array
7738 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7740 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7741 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7743 if(!arrIn || !arrIndxIn)
7744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7745 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7746 const int *arrInPtr=arrIn->getConstPointer();
7747 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7748 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7749 int maxSizeOfArr=arrIn->getNumberOfTuples();
7750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7752 arrIo->alloc((int)(sz+1),1);
7753 const int *idsIt=idsOfSelectBg;
7754 int *work=arrIo->getPointer();
7757 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7759 if(*idsIt>=0 && *idsIt<nbOfGrps)
7760 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7763 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7764 throw INTERP_KERNEL::Exception(oss.str().c_str());
7770 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7771 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7772 throw INTERP_KERNEL::Exception(oss.str().c_str());
7775 arro->alloc(lgth,1);
7776 work=arro->getPointer();
7777 idsIt=idsOfSelectBg;
7778 for(std::size_t i=0;i<sz;i++,idsIt++)
7780 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7781 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7784 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7785 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7786 throw INTERP_KERNEL::Exception(oss.str().c_str());
7790 arrIndexOut=arrIo.retn();
7794 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7795 * 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
7796 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7797 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7799 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7800 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7801 * \param [in] arrIn arr origin array from which the extraction will be done.
7802 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7803 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7804 * \param [in] srcArrIndex index array of \b srcArr
7805 * \param [out] arrOut the resulting array
7806 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7808 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7810 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7811 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7812 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
7814 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7816 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
7817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
7818 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7819 std::vector<bool> v(nbOfTuples,true);
7821 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7822 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7823 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7825 if(*it>=0 && *it<nbOfTuples)
7828 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7832 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7833 throw INTERP_KERNEL::Exception(oss.str().c_str());
7836 srcArrIndexPtr=srcArrIndex->getConstPointer();
7837 arrIo->alloc(nbOfTuples+1,1);
7838 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7839 const int *arrInPtr=arrIn->getConstPointer();
7840 const int *srcArrPtr=srcArr->getConstPointer();
7841 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7842 int *arroPtr=arro->getPointer();
7843 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7847 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7848 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7852 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7853 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7854 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7858 arrIndexOut=arrIo.retn();
7862 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7863 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7865 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7866 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7867 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7868 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7869 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7870 * \param [in] srcArrIndex index array of \b srcArr
7872 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7874 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7875 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
7877 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7878 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7879 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7880 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
7881 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
7882 int *arrInOutPtr=arrInOut->getPointer();
7883 const int *srcArrPtr=srcArr->getConstPointer();
7884 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7886 if(*it>=0 && *it<nbOfTuples)
7888 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7889 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7892 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] !";
7893 throw INTERP_KERNEL::Exception(oss.str().c_str());
7898 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7899 throw INTERP_KERNEL::Exception(oss.str().c_str());
7905 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7906 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7907 * 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]].
7908 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7909 * A negative value in \b arrIn means that it is ignored.
7910 * This method is usefull to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
7912 * \param [in] arrIn arr origin array from which the extraction will be done.
7913 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7914 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7915 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
7917 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
7919 int seed=0,nbOfDepthPeelingPerformed=0;
7920 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
7924 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7925 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7926 * 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]].
7927 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7928 * A negative value in \b arrIn means that it is ignored.
7929 * This method is usefull to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
7930 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
7931 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
7932 * \param [in] arrIn arr origin array from which the extraction will be done.
7933 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7934 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
7935 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
7936 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7937 * \sa MEDCouplingUMesh::partitionBySpreadZone
7939 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
7941 nbOfDepthPeelingPerformed=0;
7943 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
7944 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7947 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
7951 std::vector<bool> fetched(nbOfTuples,false);
7952 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
7955 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)
7957 nbOfDepthPeelingPerformed=0;
7958 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
7959 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
7960 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7961 std::vector<bool> fetched2(nbOfTuples,false);
7963 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
7965 if(*seedElt>=0 && *seedElt<nbOfTuples)
7966 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
7968 { 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()); }
7970 const int *arrInPtr=arrIn->getConstPointer();
7971 const int *arrIndxPtr=arrIndxIn->getConstPointer();
7972 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
7973 std::vector<int> idsToFetch1(seedBg,seedEnd);
7974 std::vector<int> idsToFetch2;
7975 std::vector<int> *idsToFetch=&idsToFetch1;
7976 std::vector<int> *idsToFetchOther=&idsToFetch2;
7977 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
7979 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
7980 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
7982 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
7983 std::swap(idsToFetch,idsToFetchOther);
7984 idsToFetchOther->clear();
7985 nbOfDepthPeelingPerformed++;
7987 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
7989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
7990 int *retPtr=ret->getPointer();
7991 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
7998 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7999 * 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
8000 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8001 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8003 * \param [in] start begin of set of ids of the input extraction (included)
8004 * \param [in] end end of set of ids of the input extraction (excluded)
8005 * \param [in] step step of the set of ids in range mode.
8006 * \param [in] arrIn arr origin array from which the extraction will be done.
8007 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8008 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8009 * \param [in] srcArrIndex index array of \b srcArr
8010 * \param [out] arrOut the resulting array
8011 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8013 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8015 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8016 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8017 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8019 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8020 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8021 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8023 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8025 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8026 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8027 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8029 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8031 if(it>=0 && it<nbOfTuples)
8032 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8035 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8036 throw INTERP_KERNEL::Exception(oss.str().c_str());
8039 srcArrIndexPtr=srcArrIndex->getConstPointer();
8040 arrIo->alloc(nbOfTuples+1,1);
8041 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8042 const int *arrInPtr=arrIn->getConstPointer();
8043 const int *srcArrPtr=srcArr->getConstPointer();
8044 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8045 int *arroPtr=arro->getPointer();
8046 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8048 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8051 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8052 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8056 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8057 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8061 arrIndexOut=arrIo.retn();
8065 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8066 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8068 * \param [in] start begin of set of ids of the input extraction (included)
8069 * \param [in] end end of set of ids of the input extraction (excluded)
8070 * \param [in] step step of the set of ids in range mode.
8071 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8072 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8073 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8074 * \param [in] srcArrIndex index array of \b srcArr
8076 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8078 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8079 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8081 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
8083 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8084 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8085 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8086 int *arrInOutPtr=arrInOut->getPointer();
8087 const int *srcArrPtr=srcArr->getConstPointer();
8088 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
8090 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8092 if(it>=0 && it<nbOfTuples)
8094 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8095 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8098 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8099 throw INTERP_KERNEL::Exception(oss.str().c_str());
8104 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8105 throw INTERP_KERNEL::Exception(oss.str().c_str());
8111 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8112 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8113 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8114 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8115 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8117 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8119 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
8121 checkFullyDefined();
8122 int mdim=getMeshDimension();
8123 int spaceDim=getSpaceDimension();
8125 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8126 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8127 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8128 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
8129 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8130 ret->setCoords(getCoords());
8131 ret->allocateCells((int)partition.size());
8133 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8135 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8136 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
8140 cell=tmp->buildUnionOf2DMesh();
8143 cell=tmp->buildUnionOf3DMesh();
8146 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8149 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
8152 ret->finishInsertingCells();
8157 * This method partitions \b this into contiguous zone.
8158 * This method only needs a well defined connectivity. Coordinates are not considered here.
8159 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8161 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
8164 int nbOfCellsCur=getNumberOfCells();
8165 std::vector<DataArrayInt *> ret;
8168 DataArrayInt *neigh=0,*neighI=0;
8169 computeNeighborsOfCells(neigh,neighI);
8170 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8171 std::vector<bool> fetchedCells(nbOfCellsCur,false);
8172 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8174 while(seed<nbOfCellsCur)
8176 int nbOfPeelPerformed=0;
8177 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
8178 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8180 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8181 ret.push_back((*it).retn());
8185 int nbOfCellsCur=getNumberOfCells();
8186 DataArrayInt *neigh=0,*neighI=0;
8187 computeNeighborsOfCells(neigh,neighI);
8188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
8190 std::vector<DataArrayInt *> ret;
8191 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8192 while(nbOfCellsCur>0)
8194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
8195 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
8196 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
8197 ret2.push_back(tmp2); ret.push_back(tmp2);
8198 nbOfCellsCur=tmp3->getNumberOfTuples();
8201 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
8202 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
8205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
8206 neighAuto->transformWithIndArr(renum->begin(),renum->end());
8209 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
8216 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8217 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8219 * \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.
8220 * \return a newly allocated DataArrayInt to be managed by the caller.
8221 * \throw In case of \a code has not the right format (typically of size 3*n)
8223 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
8225 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
8226 std::size_t nb=code.size()/3;
8227 if(code.size()%3!=0)
8228 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8229 ret->alloc((int)nb,2);
8230 int *retPtr=ret->getPointer();
8231 for(std::size_t i=0;i<nb;i++,retPtr+=2)
8233 retPtr[0]=code[3*i+2];
8234 retPtr[1]=code[3*i+2]+code[3*i+1];
8239 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8240 _own_cell(true),_cell_id(-1),_nb_cell(0)
8245 _nb_cell=mesh->getNumberOfCells();
8249 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8257 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8258 _own_cell(false),_cell_id(bg-1),
8265 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8268 if(_cell_id<_nb_cell)
8277 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8283 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8285 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8288 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8294 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8302 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8308 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8313 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8318 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8320 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8323 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8328 _nb_cell=mesh->getNumberOfCells();
8332 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8339 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8341 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
8342 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
8343 if(_cell_id<_nb_cell)
8345 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8346 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
8347 int startId=_cell_id;
8348 _cell_id+=nbOfElems;
8349 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8355 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8359 _conn=mesh->getNodalConnectivity()->getPointer();
8360 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8364 void MEDCouplingUMeshCell::next()
8366 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8371 _conn_lgth=_conn_indx[1]-_conn_indx[0];
8374 std::string MEDCouplingUMeshCell::repr() const
8376 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8378 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8380 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8384 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8387 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8389 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8390 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8392 return INTERP_KERNEL::NORM_ERROR;
8395 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8398 if(_conn_lgth!=NOTICABLE_FIRST_VAL)