1 // Copyright (C) 2007-2015 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, or (at your option) any later version.
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 "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DiameterCalculator.hxx"
33 #include "DirectedBoundingBox.hxx"
34 #include "InterpKernelMatrixTools.hxx"
35 #include "InterpKernelMeshQuality.hxx"
36 #include "InterpKernelCellSimplify.hxx"
37 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
38 #include "InterpKernelAutoPtr.hxx"
39 #include "InterpKernelGeo2DNode.hxx"
40 #include "InterpKernelGeo2DEdgeLin.hxx"
41 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
42 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
51 using namespace ParaMEDMEM;
53 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55 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 };
57 MEDCouplingUMesh *MEDCouplingUMesh::New()
59 return new MEDCouplingUMesh;
62 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
64 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
65 ret->setName(meshName);
66 ret->setMeshDimension(meshDim);
71 * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
72 * between \a this and the new mesh.
73 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
74 * delete this mesh using decrRef() as it is no more needed.
76 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
82 * Returns a new MEDCouplingMesh which is a copy of \a this one.
83 * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
84 * this mesh are shared by the new mesh.
85 * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
86 * delete this mesh using decrRef() as it is no more needed.
88 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
90 return new MEDCouplingUMesh(*this,recDeepCpy);
94 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
95 * The coordinates are shared between \a this and the returned instance.
97 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
98 * \sa MEDCouplingUMesh::deepCpy
100 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
102 checkConnectivityFullyDefined();
103 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
104 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
105 ret->setConnectivity(c,ci);
109 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
113 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
116 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
117 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
120 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
122 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
126 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
128 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
129 ret.push_back(_nodal_connec);
130 ret.push_back(_nodal_connec_index);
134 void MEDCouplingUMesh::updateTime() const
136 MEDCouplingPointSet::updateTime();
139 updateTimeWith(*_nodal_connec);
141 if(_nodal_connec_index)
143 updateTimeWith(*_nodal_connec_index);
147 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
153 * then \a this mesh is most probably is writable, exchangeable and available for most
154 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
155 * this method to check that all is in order with \a this mesh.
156 * \throw If the mesh dimension is not set.
157 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
158 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
159 * \throw If the connectivity data array has more than one component.
160 * \throw If the connectivity data array has a named component.
161 * \throw If the connectivity index data array has more than one component.
162 * \throw If the connectivity index data array has a named component.
164 void MEDCouplingUMesh::checkCoherency() const
167 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169 MEDCouplingPointSet::checkCoherency();
170 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174 std::ostringstream message;
175 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
176 throw INTERP_KERNEL::Exception(message.str().c_str());
181 if(_nodal_connec->getNumberOfComponents()!=1)
182 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
183 if(_nodal_connec->getInfoOnComponent(0)!="")
184 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
188 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
189 if(_nodal_connec_index)
191 if(_nodal_connec_index->getNumberOfComponents()!=1)
192 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
193 if(_nodal_connec_index->getInfoOnComponent(0)!="")
194 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
198 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
202 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
203 * then \a this mesh is most probably is writable, exchangeable and available for all
204 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
205 * method thoroughly checks the nodal connectivity.
206 * \param [in] eps - a not used parameter.
207 * \throw If the mesh dimension is not set.
208 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
209 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
210 * \throw If the connectivity data array has more than one component.
211 * \throw If the connectivity data array has a named component.
212 * \throw If the connectivity index data array has more than one component.
213 * \throw If the connectivity index data array has a named component.
214 * \throw If number of nodes defining an element does not correspond to the type of element.
215 * \throw If the nodal connectivity includes an invalid node id.
217 void MEDCouplingUMesh::checkCoherency1(double eps) const
222 int meshDim=getMeshDimension();
223 int nbOfNodes=getNumberOfNodes();
224 int nbOfCells=getNumberOfCells();
225 const int *ptr=_nodal_connec->getConstPointer();
226 const int *ptrI=_nodal_connec_index->getConstPointer();
227 for(int i=0;i<nbOfCells;i++)
229 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
230 if((int)cm.getDimension()!=meshDim)
232 std::ostringstream oss;
233 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
234 throw INTERP_KERNEL::Exception(oss.str().c_str());
236 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240 std::ostringstream oss;
241 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
242 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
243 throw INTERP_KERNEL::Exception(oss.str().c_str());
245 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
250 if(nodeId>=nbOfNodes)
252 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
253 throw INTERP_KERNEL::Exception(oss.str().c_str());
258 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
259 throw INTERP_KERNEL::Exception(oss.str().c_str());
263 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
266 throw INTERP_KERNEL::Exception(oss.str().c_str());
275 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
276 * then \a this mesh is most probably is writable, exchangeable and available for all
277 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
278 * \param [in] eps - a not used parameter.
279 * \throw If the mesh dimension is not set.
280 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
281 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
282 * \throw If the connectivity data array has more than one component.
283 * \throw If the connectivity data array has a named component.
284 * \throw If the connectivity index data array has more than one component.
285 * \throw If the connectivity index data array has a named component.
286 * \throw If number of nodes defining an element does not correspond to the type of element.
287 * \throw If the nodal connectivity includes an invalid node id.
289 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 checkCoherency1(eps);
295 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
296 * elements contained in the mesh. For more info on the mesh dimension see
297 * \ref MEDCouplingUMeshPage.
298 * \param [in] meshDim - a new mesh dimension.
299 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 if(meshDim<-1 || meshDim>3)
304 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
310 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
311 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
312 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316 * \if ENABLE_EXAMPLES
317 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
321 void MEDCouplingUMesh::allocateCells(int nbOfCells)
324 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
325 if(_nodal_connec_index)
327 _nodal_connec_index->decrRef();
331 _nodal_connec->decrRef();
333 _nodal_connec_index=DataArrayInt::New();
334 _nodal_connec_index->reserve(nbOfCells+1);
335 _nodal_connec_index->pushBackSilent(0);
336 _nodal_connec=DataArrayInt::New();
337 _nodal_connec->reserve(2*nbOfCells);
343 * Appends a cell to the connectivity array. For deeper understanding what is
344 * happening see \ref MEDCouplingUMeshNodalConnectivity.
345 * \param [in] type - type of cell to add.
346 * \param [in] size - number of nodes constituting this cell.
347 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
349 * \if ENABLE_EXAMPLES
350 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
351 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
354 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
356 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
357 if(_nodal_connec_index==0)
358 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
359 if((int)cm.getDimension()==_mesh_dim)
362 if(size!=(int)cm.getNumberOfNodes())
364 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
365 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
366 throw INTERP_KERNEL::Exception(oss.str().c_str());
368 int idx=_nodal_connec_index->back();
370 _nodal_connec_index->pushBackSilent(val);
371 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
376 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
377 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
378 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
379 throw INTERP_KERNEL::Exception(oss.str().c_str());
384 * Compacts data arrays to release unused memory. This method is to be called after
385 * finishing cell insertion using \a this->insertNextCell().
387 * \if ENABLE_EXAMPLES
388 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
389 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
392 void MEDCouplingUMesh::finishInsertingCells()
394 _nodal_connec->pack();
395 _nodal_connec_index->pack();
396 _nodal_connec->declareAsNew();
397 _nodal_connec_index->declareAsNew();
402 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
403 * Useful for python users.
405 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
407 return new MEDCouplingUMeshCellIterator(this);
411 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
412 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
413 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
414 * Useful for python users.
416 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
418 if(!checkConsecutiveCellTypes())
419 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
420 return new MEDCouplingUMeshCellByTypeEntry(this);
424 * Returns a set of all cell types available in \a this mesh.
425 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
426 * \warning this method does not throw any exception even if \a this is not defined.
427 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
429 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
435 * This method returns the sorted list of geometric types in \a this.
436 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
437 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
439 * \throw if connectivity in \a this is not correctly defined.
441 * \sa MEDCouplingMesh::getAllGeoTypes
443 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
445 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
446 checkConnectivityFullyDefined();
447 int nbOfCells(getNumberOfCells());
450 if(getMeshLength()<1)
451 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
452 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
453 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
454 for(int i=1;i<nbOfCells;i++,ci++)
455 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
456 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
461 * This method is a method that compares \a this and \a other.
462 * This method compares \b all attributes, even names and component names.
464 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
468 std::ostringstream oss; oss.precision(15);
469 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
472 reason="mesh given in input is not castable in MEDCouplingUMesh !";
475 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
477 if(_mesh_dim!=otherC->_mesh_dim)
479 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
483 if(_types!=otherC->_types)
485 oss << "umesh geometric type mismatch :\nThis geometric types are :";
486 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
487 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
488 oss << "\nOther geometric types are :";
489 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
490 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
494 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
495 if(_nodal_connec==0 || otherC->_nodal_connec==0)
497 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
500 if(_nodal_connec!=otherC->_nodal_connec)
501 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
503 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
506 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
507 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
509 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
512 if(_nodal_connec_index!=otherC->_nodal_connec_index)
513 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
515 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
522 * Checks if data arrays of this mesh (node coordinates, nodal
523 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
525 * \param [in] other - the mesh to compare with.
526 * \param [in] prec - precision value used to compare node coordinates.
527 * \return bool - \a true if the two meshes are same.
529 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
531 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
534 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
536 if(_mesh_dim!=otherC->_mesh_dim)
538 if(_types!=otherC->_types)
540 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
541 if(_nodal_connec==0 || otherC->_nodal_connec==0)
543 if(_nodal_connec!=otherC->_nodal_connec)
544 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
546 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
547 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
549 if(_nodal_connec_index!=otherC->_nodal_connec_index)
550 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
556 * Checks if \a this and \a other meshes are geometrically equivalent with high
557 * probability, else an exception is thrown. The meshes are considered equivalent if
558 * (1) meshes contain the same number of nodes and the same number of elements of the
559 * same types (2) three cells of the two meshes (first, last and middle) are based
560 * on coincident nodes (with a specified precision).
561 * \param [in] other - the mesh to compare with.
562 * \param [in] prec - the precision used to compare nodes of the two meshes.
563 * \throw If the two meshes do not match.
565 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
567 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
568 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
570 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
574 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
575 * cells each node belongs to.
576 * \warning For speed reasons, this method does not check if node ids in the nodal
577 * connectivity correspond to the size of node coordinates array.
578 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
579 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
580 * dividing cell ids in \a revNodal into groups each referring to one
581 * node. Its every element (except the last one) is an index pointing to the
582 * first id of a group of cells. For example cells sharing the node #1 are
583 * described by following range of indices:
584 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
585 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
586 * Number of cells sharing the *i*-th node is
587 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
588 * \throw If the coordinates array is not set.
589 * \throw If the nodal connectivity of cells is not defined.
591 * \if ENABLE_EXAMPLES
592 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
593 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
596 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
599 int nbOfNodes=getNumberOfNodes();
600 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
601 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
602 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
603 const int *conn=_nodal_connec->getConstPointer();
604 const int *connIndex=_nodal_connec_index->getConstPointer();
605 int nbOfCells=getNumberOfCells();
606 int nbOfEltsInRevNodal=0;
607 for(int eltId=0;eltId<nbOfCells;eltId++)
609 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
610 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
611 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
612 if(*iter>=0)//for polyhedrons
614 nbOfEltsInRevNodal++;
615 revNodalIndxPtr[(*iter)+1]++;
618 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
619 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
620 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
621 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
622 for(int eltId=0;eltId<nbOfCells;eltId++)
624 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
625 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
626 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
627 if(*iter>=0)//for polyhedrons
628 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
634 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
639 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
645 if(cm.getOrientationStatus(nb,conn1,conn2))
652 class MinusOneSonsGenerator
655 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
656 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
657 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
658 static const int DELTA=1;
660 const INTERP_KERNEL::CellModel& _cm;
663 class MinusOneSonsGeneratorBiQuadratic
666 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
667 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
668 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
669 static const int DELTA=1;
671 const INTERP_KERNEL::CellModel& _cm;
674 class MinusTwoSonsGenerator
677 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
678 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
679 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
680 static const int DELTA=2;
682 const INTERP_KERNEL::CellModel& _cm;
688 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
689 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
690 * describing correspondence between cells of \a this and the result meshes are
691 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
692 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
693 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
694 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
695 * \warning For speed reasons, this method does not check if node ids in the nodal
696 * connectivity correspond to the size of node coordinates array.
697 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
698 * to write this mesh to the MED file, its cells must be sorted using
699 * sortCellsInMEDFileFrmt().
700 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
701 * each cell of \a this mesh.
702 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
703 * dividing cell ids in \a desc into groups each referring to one
704 * cell of \a this mesh. Its every element (except the last one) is an index
705 * pointing to the first id of a group of cells. For example cells of the
706 * result mesh bounding the cell #1 of \a this mesh are described by following
708 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
709 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
710 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
711 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
712 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
713 * by each cell of the result mesh.
714 * \param [in,out] revDescIndx - the array, of length one more than number of cells
715 * in the result mesh,
716 * dividing cell ids in \a revDesc into groups each referring to one
717 * cell of the result mesh the same way as \a descIndx divides \a desc.
718 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
719 * delete this mesh using decrRef() as it is no more needed.
720 * \throw If the coordinates array is not set.
721 * \throw If the nodal connectivity of cells is node defined.
722 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
723 * revDescIndx == NULL.
725 * \if ENABLE_EXAMPLES
726 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
727 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
729 * \sa buildDescendingConnectivity2()
731 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
733 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
737 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
738 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
739 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
740 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
741 * \sa MEDCouplingUMesh::buildDescendingConnectivity
743 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
746 if(getMeshDimension()!=3)
747 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
748 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
752 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
753 * this->getMeshDimension(), that bound cells of \a this mesh. In
754 * addition arrays describing correspondence between cells of \a this and the result
755 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
756 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
757 * mesh. This method differs from buildDescendingConnectivity() in that apart
758 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
759 * result meshes. So a positive id means that order of nodes in corresponding cells
760 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
761 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
762 * i.e. cell ids are one-based.
763 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
764 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
765 * \warning For speed reasons, this method does not check if node ids in the nodal
766 * connectivity correspond to the size of node coordinates array.
767 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
768 * to write this mesh to the MED file, its cells must be sorted using
769 * sortCellsInMEDFileFrmt().
770 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
771 * each cell of \a this mesh.
772 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
773 * dividing cell ids in \a desc into groups each referring to one
774 * cell of \a this mesh. Its every element (except the last one) is an index
775 * pointing to the first id of a group of cells. For example cells of the
776 * result mesh bounding the cell #1 of \a this mesh are described by following
778 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
779 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
780 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
781 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
782 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
783 * by each cell of the result mesh.
784 * \param [in,out] revDescIndx - the array, of length one more than number of cells
785 * in the result mesh,
786 * dividing cell ids in \a revDesc into groups each referring to one
787 * cell of the result mesh the same way as \a descIndx divides \a desc.
788 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
789 * shares the node coordinates array with \a this mesh. The caller is to
790 * delete this mesh using decrRef() as it is no more needed.
791 * \throw If the coordinates array is not set.
792 * \throw If the nodal connectivity of cells is node defined.
793 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
794 * revDescIndx == NULL.
796 * \if ENABLE_EXAMPLES
797 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
798 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
800 * \sa buildDescendingConnectivity()
802 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
804 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
808 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
809 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
810 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
811 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
813 * \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
814 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
815 * \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.
817 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
819 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
823 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
825 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
829 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
830 * 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,
831 * excluding a set of meshdim-1 cells in input descending connectivity.
832 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
833 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
834 * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836 * \param [in] desc descending connectivity array.
837 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
838 * \param [in] revDesc reverse descending connectivity array.
839 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
840 * \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
841 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
842 * \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.
844 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
845 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
847 if(!desc || !descIndx || !revDesc || !revDescIndx)
848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
849 const int *descPtr=desc->getConstPointer();
850 const int *descIPtr=descIndx->getConstPointer();
851 const int *revDescPtr=revDesc->getConstPointer();
852 const int *revDescIPtr=revDescIndx->getConstPointer();
854 int nbCells=descIndx->getNumberOfTuples()-1;
855 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
857 int *out1Ptr=out1->getPointer();
859 out0->reserve(desc->getNumberOfTuples());
860 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866 out0->insertAtTheEnd(s.begin(),s.end());
868 *out1Ptr=out0->getNumberOfTuples();
870 neighbors=out0.retn();
871 neighborsIndx=out1.retn();
875 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
876 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
877 * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
878 * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
880 * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
881 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
882 * \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.
884 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
887 int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
888 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
889 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
894 mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
899 mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
904 mesh1D=const_cast<MEDCouplingUMesh *>(this);
910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
913 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
914 mesh1D->getReverseNodalConnectivity(desc,descIndx);
915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
916 ret0->alloc(desc->getNumberOfTuples(),1);
917 int *r0Pt(ret0->getPointer());
918 const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
919 for(int i=0;i<nbNodes;i++,rni++)
921 for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
922 *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
924 neighbors=ret0.retn();
925 neighborsIdx=descIndx.retn();
931 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
932 * For speed reasons no check of this will be done.
934 template<class SonsGenerator>
935 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
937 if(!desc || !descIndx || !revDesc || !revDescIndx)
938 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
939 checkConnectivityFullyDefined();
940 int nbOfCells=getNumberOfCells();
941 int nbOfNodes=getNumberOfNodes();
942 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
943 int *revNodalIndxPtr=revNodalIndx->getPointer();
944 const int *conn=_nodal_connec->getConstPointer();
945 const int *connIndex=_nodal_connec_index->getConstPointer();
946 std::string name="Mesh constituent of "; name+=getName();
947 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
948 ret->setCoords(getCoords());
949 ret->allocateCells(2*nbOfCells);
950 descIndx->alloc(nbOfCells+1,1);
951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
952 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
953 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
955 int pos=connIndex[eltId];
956 int posP1=connIndex[eltId+1];
957 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
958 SonsGenerator sg(cm);
959 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
960 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
961 for(unsigned i=0;i<nbOfSons;i++)
963 INTERP_KERNEL::NormalizedCellType cmsId;
964 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
965 for(unsigned k=0;k<nbOfNodesSon;k++)
967 revNodalIndxPtr[tmp[k]+1]++;
968 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
969 revDesc2->pushBackSilent(eltId);
971 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
973 int nbOfCellsM1=ret->getNumberOfCells();
974 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
975 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
976 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
977 int *revNodalPtr=revNodal->getPointer();
978 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
979 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
980 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
982 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
983 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
984 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
985 if(*iter>=0)//for polyhedrons
986 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
989 DataArrayInt *commonCells=0,*commonCellsI=0;
990 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
991 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
992 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
993 int newNbOfCellsM1=-1;
994 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
995 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
996 std::vector<bool> isImpacted(nbOfCellsM1,false);
997 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
998 for(int work2=work[0];work2!=work[1];work2++)
999 isImpacted[commonCellsPtr[work2]]=true;
1000 const int *o2nM1Ptr=o2nM1->getConstPointer();
1001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1002 const int *n2oM1Ptr=n2oM1->getConstPointer();
1003 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1004 ret2->copyTinyInfoFrom(this);
1005 desc->alloc(descIndx->back(),1);
1006 int *descPtr=desc->getPointer();
1007 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1008 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1011 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1014 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1016 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1017 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1020 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1023 revDesc->reserve(newNbOfCellsM1);
1024 revDescIndx->alloc(newNbOfCellsM1+1,1);
1025 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1026 const int *revDesc2Ptr=revDesc2->getConstPointer();
1027 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1029 int oldCellIdM1=n2oM1Ptr[i];
1030 if(!isImpacted[oldCellIdM1])
1032 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1033 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1037 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1038 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1039 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1047 struct MEDCouplingAccVisit
1049 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1050 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1051 int _new_nb_of_nodes;
1057 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1058 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1059 * array of cell ids. Pay attention that after conversion all algorithms work slower
1060 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1061 * conversion due presence of invalid ids in the array of cells to convert, as a
1062 * result \a this mesh contains some already converted elements. In this case the 2D
1063 * mesh remains valid but 3D mesh becomes \b inconsistent!
1064 * \warning This method can significantly modify the order of geometric types in \a this,
1065 * hence, to write this mesh to the MED file, its cells must be sorted using
1066 * sortCellsInMEDFileFrmt().
1067 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1068 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1069 * cellIdsToConvertBg.
1070 * \throw If the coordinates array is not set.
1071 * \throw If the nodal connectivity of cells is node defined.
1072 * \throw If dimension of \a this mesh is not either 2 or 3.
1074 * \if ENABLE_EXAMPLES
1075 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1076 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1079 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1081 checkFullyDefined();
1082 int dim=getMeshDimension();
1084 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1085 int nbOfCells(getNumberOfCells());
1088 const int *connIndex=_nodal_connec_index->getConstPointer();
1089 int *conn=_nodal_connec->getPointer();
1090 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1092 if(*iter>=0 && *iter<nbOfCells)
1094 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1095 if(!cm.isQuadratic())
1096 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1098 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1102 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1103 oss << " in range [0," << nbOfCells << ") !";
1104 throw INTERP_KERNEL::Exception(oss.str().c_str());
1110 int *connIndex(_nodal_connec_index->getPointer());
1111 const int *connOld(_nodal_connec->getConstPointer());
1112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1113 std::vector<bool> toBeDone(nbOfCells,false);
1114 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1116 if(*iter>=0 && *iter<nbOfCells)
1117 toBeDone[*iter]=true;
1120 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1121 oss << " in range [0," << nbOfCells << ") !";
1122 throw INTERP_KERNEL::Exception(oss.str().c_str());
1125 for(int cellId=0;cellId<nbOfCells;cellId++)
1127 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1128 int lgthOld(posP1-pos-1);
1129 if(toBeDone[cellId])
1131 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1132 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1133 int *tmp(new int[nbOfFaces*lgthOld+1]);
1134 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1135 for(unsigned j=0;j<nbOfFaces;j++)
1137 INTERP_KERNEL::NormalizedCellType type;
1138 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1142 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1143 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1144 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1149 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1150 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1153 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1159 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1160 * polyhedrons (if \a this is a 3D mesh).
1161 * \warning As this method is purely for user-friendliness and no optimization is
1162 * done to avoid construction of a useless vector, this method can be costly
1164 * \throw If the coordinates array is not set.
1165 * \throw If the nodal connectivity of cells is node defined.
1166 * \throw If dimension of \a this mesh is not either 2 or 3.
1168 void MEDCouplingUMesh::convertAllToPoly()
1170 int nbOfCells=getNumberOfCells();
1171 std::vector<int> cellIds(nbOfCells);
1172 for(int i=0;i<nbOfCells;i++)
1174 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1178 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1179 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1180 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1181 * base facet of the volume and the second half of nodes describes an opposite facet
1182 * having the same number of nodes as the base one. This method converts such
1183 * connectivity to a valid polyhedral format where connectivity of each facet is
1184 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1185 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1186 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1187 * a correct orientation of the first facet of a polyhedron, else orientation of a
1188 * corrected cell is reverse.<br>
1189 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1190 * it releases the user from boring description of polyhedra connectivity in the valid
1192 * \throw If \a this->getMeshDimension() != 3.
1193 * \throw If \a this->getSpaceDimension() != 3.
1194 * \throw If the nodal connectivity of cells is not defined.
1195 * \throw If the coordinates array is not set.
1196 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1197 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1199 * \if ENABLE_EXAMPLES
1200 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1201 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1204 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1206 checkFullyDefined();
1207 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1208 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1209 int nbOfCells=getNumberOfCells();
1210 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1211 newCi->alloc(nbOfCells+1,1);
1212 int *newci=newCi->getPointer();
1213 const int *ci=_nodal_connec_index->getConstPointer();
1214 const int *c=_nodal_connec->getConstPointer();
1216 for(int i=0;i<nbOfCells;i++)
1218 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1219 if(type==INTERP_KERNEL::NORM_POLYHED)
1221 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1223 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1224 throw INTERP_KERNEL::Exception(oss.str().c_str());
1226 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1229 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 !";
1230 throw INTERP_KERNEL::Exception(oss.str().c_str());
1233 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)
1236 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1239 newC->alloc(newci[nbOfCells],1);
1240 int *newc=newC->getPointer();
1241 for(int i=0;i<nbOfCells;i++)
1243 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1244 if(type==INTERP_KERNEL::NORM_POLYHED)
1246 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1247 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1249 for(std::size_t j=0;j<n1;j++)
1251 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1253 newc[n1+5*j+1]=c[ci[i]+1+j];
1254 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1255 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1256 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1261 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1263 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1264 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1269 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1270 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1271 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1272 * to write this mesh to the MED file, its cells must be sorted using
1273 * sortCellsInMEDFileFrmt().
1274 * \return \c true if at least one cell has been converted, \c false else. In the
1275 * last case the nodal connectivity remains unchanged.
1276 * \throw If the coordinates array is not set.
1277 * \throw If the nodal connectivity of cells is not defined.
1278 * \throw If \a this->getMeshDimension() < 0.
1280 bool MEDCouplingUMesh::unPolyze()
1282 checkFullyDefined();
1283 int mdim=getMeshDimension();
1285 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1288 int nbOfCells=getNumberOfCells();
1291 int initMeshLgth=getMeshLength();
1292 int *conn=_nodal_connec->getPointer();
1293 int *index=_nodal_connec_index->getPointer();
1298 for(int i=0;i<nbOfCells;i++)
1300 lgthOfCurCell=index[i+1]-posOfCurCell;
1301 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1302 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1303 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1307 switch(cm.getDimension())
1311 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1312 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1313 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1318 int nbOfFaces,lgthOfPolyhConn;
1319 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1320 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1325 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1329 ret=ret || (newType!=type);
1330 conn[newPos]=newType;
1332 posOfCurCell=index[i+1];
1337 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1338 newPos+=lgthOfCurCell;
1339 posOfCurCell+=lgthOfCurCell;
1343 if(newPos!=initMeshLgth)
1344 _nodal_connec->reAlloc(newPos);
1351 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1352 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1353 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1355 * \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
1358 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1360 checkFullyDefined();
1361 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1363 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1364 coords->recenterForMaxPrecision(eps);
1366 int nbOfCells=getNumberOfCells();
1367 const int *conn=_nodal_connec->getConstPointer();
1368 const int *index=_nodal_connec_index->getConstPointer();
1369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1370 connINew->alloc(nbOfCells+1,1);
1371 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1374 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1376 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1378 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1382 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1383 *connINewPtr=connNew->getNumberOfTuples();
1386 setConnectivity(connNew,connINew,false);
1390 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1391 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1392 * the format of returned DataArrayInt instance.
1394 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1395 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1397 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1399 checkConnectivityFullyDefined();
1400 int nbOfCells=getNumberOfCells();
1401 const int *connIndex=_nodal_connec_index->getConstPointer();
1402 const int *conn=_nodal_connec->getConstPointer();
1403 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1404 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1405 std::vector<bool> retS(maxElt,false);
1406 for(int i=0;i<nbOfCells;i++)
1407 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1411 for(int i=0;i<maxElt;i++)
1414 DataArrayInt *ret=DataArrayInt::New();
1416 int *retPtr=ret->getPointer();
1417 for(int i=0;i<maxElt;i++)
1424 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1425 * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1427 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1429 int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1430 const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1431 for(int i=0;i<nbOfCells;i++)
1432 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1435 if(conn[j]<nbOfNodes)
1436 nodeIdsInUse[conn[j]]=true;
1439 std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1440 throw INTERP_KERNEL::Exception(oss.str().c_str());
1446 * Finds nodes not used in any cell and returns an array giving a new id to every node
1447 * by excluding the unused nodes, for which the array holds -1. The result array is
1448 * a mapping in "Old to New" mode.
1449 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1450 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1451 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1452 * if the node is unused or a new id else. The caller is to delete this
1453 * array using decrRef() as it is no more needed.
1454 * \throw If the coordinates array is not set.
1455 * \throw If the nodal connectivity of cells is not defined.
1456 * \throw If the nodal connectivity includes an invalid id.
1458 * \if ENABLE_EXAMPLES
1459 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1460 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1462 * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1464 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1467 int nbOfNodes(getNumberOfNodes());
1468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1469 ret->alloc(nbOfNodes,1);
1470 int *traducer=ret->getPointer();
1471 std::fill(traducer,traducer+nbOfNodes,-1);
1472 int nbOfCells=getNumberOfCells();
1473 const int *connIndex=_nodal_connec_index->getConstPointer();
1474 const int *conn=_nodal_connec->getConstPointer();
1475 for(int i=0;i<nbOfCells;i++)
1476 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1479 if(conn[j]<nbOfNodes)
1480 traducer[conn[j]]=1;
1483 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1484 throw INTERP_KERNEL::Exception(oss.str().c_str());
1487 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1488 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1493 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1494 * For each cell in \b this the number of nodes constituting cell is computed.
1495 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1496 * So for pohyhedrons some nodes can be counted several times in the returned result.
1498 * \return a newly allocated array
1499 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1501 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1503 checkConnectivityFullyDefined();
1504 int nbOfCells=getNumberOfCells();
1505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1506 ret->alloc(nbOfCells,1);
1507 int *retPtr=ret->getPointer();
1508 const int *conn=getNodalConnectivity()->getConstPointer();
1509 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1510 for(int i=0;i<nbOfCells;i++,retPtr++)
1512 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1513 *retPtr=connI[i+1]-connI[i]-1;
1515 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1521 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1522 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1524 * \return DataArrayInt * - new object to be deallocated by the caller.
1525 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1527 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1529 checkConnectivityFullyDefined();
1530 int nbOfCells=getNumberOfCells();
1531 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1532 ret->alloc(nbOfCells,1);
1533 int *retPtr=ret->getPointer();
1534 const int *conn=getNodalConnectivity()->getConstPointer();
1535 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1536 for(int i=0;i<nbOfCells;i++,retPtr++)
1538 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1539 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1540 *retPtr=(int)s.size();
1544 *retPtr=(int)s.size();
1551 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1552 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1554 * \return a newly allocated array
1556 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1558 checkConnectivityFullyDefined();
1559 int nbOfCells=getNumberOfCells();
1560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1561 ret->alloc(nbOfCells,1);
1562 int *retPtr=ret->getPointer();
1563 const int *conn=getNodalConnectivity()->getConstPointer();
1564 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1565 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1567 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1568 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1574 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1575 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1576 * array mean that the corresponding old node is no more used.
1577 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1578 * this->getNumberOfNodes() before call of this method. The caller is to
1579 * delete this array using decrRef() as it is no more needed.
1580 * \throw If the coordinates array is not set.
1581 * \throw If the nodal connectivity of cells is not defined.
1582 * \throw If the nodal connectivity includes an invalid id.
1583 * \sa areAllNodesFetched
1585 * \if ENABLE_EXAMPLES
1586 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1587 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1590 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1592 return MEDCouplingPointSet::zipCoordsTraducer();
1596 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1597 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1599 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1604 return AreCellsEqual0(conn,connI,cell1,cell2);
1606 return AreCellsEqual1(conn,connI,cell1,cell2);
1608 return AreCellsEqual2(conn,connI,cell1,cell2);
1610 return AreCellsEqual3(conn,connI,cell1,cell2);
1612 return AreCellsEqual7(conn,connI,cell1,cell2);
1614 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1618 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1620 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1622 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1623 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1628 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1630 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1632 int sz=connI[cell1+1]-connI[cell1];
1633 if(sz==connI[cell2+1]-connI[cell2])
1635 if(conn[connI[cell1]]==conn[connI[cell2]])
1637 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1638 unsigned dim=cm.getDimension();
1644 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1645 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1646 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1647 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1648 return work!=tmp+sz1?1:0;
1651 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1654 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1661 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1663 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1665 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1667 if(conn[connI[cell1]]==conn[connI[cell2]])
1669 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1670 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1678 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1680 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1682 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1684 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1685 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1692 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1694 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1696 int sz=connI[cell1+1]-connI[cell1];
1697 if(sz==connI[cell2+1]-connI[cell2])
1699 if(conn[connI[cell1]]==conn[connI[cell2]])
1701 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1702 unsigned dim=cm.getDimension();
1708 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1709 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1710 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1711 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1716 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1717 std::reverse_iterator<int *> it2((int *)tmp);
1718 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1724 return work!=tmp+sz1?1:0;
1727 {//case of SEG2 and SEG3
1728 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1730 if(!cm.isQuadratic())
1732 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1733 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1734 if(std::equal(it1,it2,conn+connI[cell2]+1))
1740 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])
1747 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1754 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1755 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1756 * and result remains unchanged.
1757 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1758 * If in 'candidates' pool -1 value is considered as an empty value.
1759 * WARNING this method returns only ONE set of result !
1761 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1763 if(candidates.size()<1)
1766 std::vector<int>::const_iterator iter=candidates.begin();
1767 int start=(*iter++);
1768 for(;iter!=candidates.end();iter++)
1770 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1775 result->pushBackSilent(start);
1779 result->pushBackSilent(*iter);
1781 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1788 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1789 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1791 * \param [in] compType input specifying the technique used to compare cells each other.
1792 * - 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.
1793 * - 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)
1794 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1795 * - 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
1796 * can be used for users not sensitive to orientation of cell
1797 * \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.
1798 * \param [out] commonCells
1799 * \param [out] commonCellsI
1800 * \return the correspondance array old to new in a newly allocated array.
1803 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1806 getReverseNodalConnectivity(revNodal,revNodalI);
1807 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1810 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1811 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1814 int nbOfCells=nodalI->getNumberOfTuples()-1;
1815 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1816 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1817 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1818 std::vector<bool> isFetched(nbOfCells,false);
1821 for(int i=0;i<nbOfCells;i++)
1825 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1826 std::vector<int> v,v2;
1827 if(connOfNode!=connPtr+connIPtr[i+1])
1829 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1830 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1833 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1837 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1838 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1839 v2.resize(std::distance(v2.begin(),it));
1843 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1845 int pos=commonCellsI->back();
1846 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1847 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1848 isFetched[*it]=true;
1856 for(int i=startCellId;i<nbOfCells;i++)
1860 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1861 std::vector<int> v,v2;
1862 if(connOfNode!=connPtr+connIPtr[i+1])
1864 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1867 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1871 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1872 v2.resize(std::distance(v2.begin(),it));
1876 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1878 int pos=commonCellsI->back();
1879 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1880 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1881 isFetched[*it]=true;
1887 commonCellsArr=commonCells.retn();
1888 commonCellsIArr=commonCellsI.retn();
1892 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1893 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1894 * than \a other->getNumberOfCells() in the returned array means that there is no
1895 * corresponding cell in \a this mesh.
1896 * It is expected that \a this and \a other meshes share the same node coordinates
1897 * array, if it is not so an exception is thrown.
1898 * \param [in] other - the mesh to compare with.
1899 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1900 * valid values [0,1,2], see zipConnectivityTraducer().
1901 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1902 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1903 * values. The caller is to delete this array using
1904 * decrRef() as it is no more needed.
1905 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1908 * \if ENABLE_EXAMPLES
1909 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1910 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1912 * \sa checkDeepEquivalOnSameNodesWith()
1913 * \sa checkGeoEquivalWith()
1915 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1917 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1918 int nbOfCells=getNumberOfCells();
1919 static const int possibleCompType[]={0,1,2};
1920 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1922 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1923 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1925 throw INTERP_KERNEL::Exception(oss.str().c_str());
1927 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1928 arr=o2n->substr(nbOfCells);
1929 arr->setName(other->getName());
1931 if(other->getNumberOfCells()==0)
1933 return arr->getMaxValue(tmp)<nbOfCells;
1937 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1938 * This method tries to determine if \b other is fully included in \b this.
1939 * The main difference is that this method is not expected to throw exception.
1940 * This method has two outputs :
1942 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1943 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1945 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1947 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1948 DataArrayInt *commonCells=0,*commonCellsI=0;
1949 int thisNbCells=getNumberOfCells();
1950 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1952 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1953 int otherNbCells=other->getNumberOfCells();
1954 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1955 arr2->alloc(otherNbCells,1);
1956 arr2->fillWithZero();
1957 int *arr2Ptr=arr2->getPointer();
1958 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1959 for(int i=0;i<nbOfCommon;i++)
1961 int start=commonCellsPtr[commonCellsIPtr[i]];
1962 if(start<thisNbCells)
1964 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1966 int sig=commonCellsPtr[j]>0?1:-1;
1967 int val=std::abs(commonCellsPtr[j])-1;
1968 if(val>=thisNbCells)
1969 arr2Ptr[val-thisNbCells]=sig*(start+1);
1973 arr2->setName(other->getName());
1974 if(arr2->presenceOfValue(0))
1980 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1983 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1984 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1986 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1987 std::vector<const MEDCouplingUMesh *> ms(2);
1990 return MergeUMeshesOnSameCoords(ms);
1994 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1995 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1996 * cellIds is not given explicitely but by a range python like.
1998 * \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.
1999 * \return a newly allocated
2001 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2002 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2004 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2006 if(getMeshDimension()!=-1)
2007 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2010 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2012 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2014 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2016 return const_cast<MEDCouplingUMesh *>(this);
2021 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2022 * The result mesh shares or not the node coordinates array with \a this mesh depending
2023 * on \a keepCoords parameter.
2024 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2025 * to write this mesh to the MED file, its cells must be sorted using
2026 * sortCellsInMEDFileFrmt().
2027 * \param [in] begin - an array of cell ids to include to the new mesh.
2028 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
2029 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2030 * array of \a this mesh, else "free" nodes are removed from the result mesh
2031 * by calling zipCoords().
2032 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2033 * to delete this mesh using decrRef() as it is no more needed.
2034 * \throw If the coordinates array is not set.
2035 * \throw If the nodal connectivity of cells is not defined.
2036 * \throw If any cell id in the array \a begin is not valid.
2038 * \if ENABLE_EXAMPLES
2039 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2040 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
2043 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2045 if(getMeshDimension()!=-1)
2046 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2050 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2052 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2054 return const_cast<MEDCouplingUMesh *>(this);
2059 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2061 * 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.
2062 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2063 * The number of cells of \b this will remain the same with this method.
2065 * \param [in] begin begin of cell ids (included) of cells in this to assign
2066 * \param [in] end end of cell ids (excluded) of cells in this to assign
2067 * \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 ).
2068 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2070 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2072 checkConnectivityFullyDefined();
2073 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2074 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2075 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2076 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2078 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2079 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2080 throw INTERP_KERNEL::Exception(oss.str().c_str());
2082 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2083 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2085 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2086 throw INTERP_KERNEL::Exception(oss.str().c_str());
2088 int nbOfCells=getNumberOfCells();
2089 bool easyAssign=true;
2090 const int *connI=_nodal_connec_index->getConstPointer();
2091 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2092 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2094 if(*it>=0 && *it<nbOfCells)
2096 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2100 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2101 throw INTERP_KERNEL::Exception(oss.str().c_str());
2106 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2111 DataArrayInt *arrOut=0,*arrIOut=0;
2112 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2115 setConnectivity(arrOut,arrIOut,true);
2119 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2121 checkConnectivityFullyDefined();
2122 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2123 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2124 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2125 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2127 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2128 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2129 throw INTERP_KERNEL::Exception(oss.str().c_str());
2131 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2132 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2134 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2135 throw INTERP_KERNEL::Exception(oss.str().c_str());
2137 int nbOfCells=getNumberOfCells();
2138 bool easyAssign=true;
2139 const int *connI=_nodal_connec_index->getConstPointer();
2140 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2142 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2144 if(it>=0 && it<nbOfCells)
2146 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2150 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2151 throw INTERP_KERNEL::Exception(oss.str().c_str());
2156 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2161 DataArrayInt *arrOut=0,*arrIOut=0;
2162 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2165 setConnectivity(arrOut,arrIOut,true);
2170 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2171 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2172 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2173 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2175 * \param [in] begin input start of array of node ids.
2176 * \param [in] end input end of array of node ids.
2177 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2178 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2180 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2183 checkConnectivityFullyDefined();
2185 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2186 std::vector<bool> fastFinder(sz,false);
2187 for(const int *work=begin;work!=end;work++)
2188 if(*work>=0 && *work<sz)
2189 fastFinder[*work]=true;
2190 int nbOfCells=getNumberOfCells();
2191 const int *conn=getNodalConnectivity()->getConstPointer();
2192 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2193 for(int i=0;i<nbOfCells;i++)
2195 int ref=0,nbOfHit=0;
2196 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2200 if(fastFinder[*work2])
2203 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2204 cellIdsKept->pushBackSilent(i);
2206 cellIdsKeptArr=cellIdsKept.retn();
2210 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2211 * this->getMeshDimension(), that bound some cells of \a this mesh.
2212 * The cells of lower dimension to include to the result mesh are selected basing on
2213 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2214 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2215 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2216 * created mesh shares the node coordinates array with \a this mesh.
2217 * \param [in] begin - the array of node ids.
2218 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2219 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2220 * array \a begin are added, else cells whose any node is in the
2221 * array \a begin are added.
2222 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2223 * to delete this mesh using decrRef() as it is no more needed.
2224 * \throw If the coordinates array is not set.
2225 * \throw If the nodal connectivity of cells is not defined.
2226 * \throw If any node id in \a begin is not valid.
2228 * \if ENABLE_EXAMPLES
2229 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2230 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2233 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2236 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2237 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2238 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2239 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2243 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2244 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2245 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2246 * array of \a this mesh, else "free" nodes are removed from the result mesh
2247 * by calling zipCoords().
2248 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2249 * to delete this mesh using decrRef() as it is no more needed.
2250 * \throw If the coordinates array is not set.
2251 * \throw If the nodal connectivity of cells is not defined.
2253 * \if ENABLE_EXAMPLES
2254 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2255 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2258 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2260 DataArrayInt *desc=DataArrayInt::New();
2261 DataArrayInt *descIndx=DataArrayInt::New();
2262 DataArrayInt *revDesc=DataArrayInt::New();
2263 DataArrayInt *revDescIndx=DataArrayInt::New();
2265 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2268 descIndx->decrRef();
2269 int nbOfCells=meshDM1->getNumberOfCells();
2270 const int *revDescIndxC=revDescIndx->getConstPointer();
2271 std::vector<int> boundaryCells;
2272 for(int i=0;i<nbOfCells;i++)
2273 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2274 boundaryCells.push_back(i);
2275 revDescIndx->decrRef();
2276 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2281 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2282 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2283 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2285 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2287 checkFullyDefined();
2288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2293 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2294 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2298 const int *revDescPtr=revDesc->getConstPointer();
2299 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2300 int nbOfCells=getNumberOfCells();
2301 std::vector<bool> ret1(nbOfCells,false);
2303 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2304 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2305 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2307 DataArrayInt *ret2=DataArrayInt::New();
2309 int *ret2Ptr=ret2->getPointer();
2311 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2314 ret2->setName("BoundaryCells");
2319 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2320 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2321 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2322 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2324 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2325 * This method method returns cells ids set s = s1 + s2 where :
2327 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2328 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2330 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2331 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2333 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2334 * \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
2335 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2337 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2339 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2341 checkConnectivityFullyDefined();
2342 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2343 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2350 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2351 DataArrayInt *idsOtherInConsti=0;
2352 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2357 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2358 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2361 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2362 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2364 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2365 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2366 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2367 neighThisPartAuto=0;
2368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2369 const int li[2]={0,1};
2370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2371 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2375 cellIdsRk0=s0arr.retn();
2376 cellIdsRk1=s_renum1.retn();
2380 * 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
2381 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2383 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2385 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2393 revDesc=0; desc=0; descIndx=0;
2394 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2396 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2400 * Finds nodes lying on the boundary of \a this mesh.
2401 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2402 * nodes. The caller is to delete this array using decrRef() as it is no
2404 * \throw If the coordinates array is not set.
2405 * \throw If the nodal connectivity of cells is node defined.
2407 * \if ENABLE_EXAMPLES
2408 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2409 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2412 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2414 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2415 return skin->computeFetchedNodeIds();
2418 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2421 return const_cast<MEDCouplingUMesh *>(this);
2425 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2426 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2427 * 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.
2428 * 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.
2429 * 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.
2431 * \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
2432 * parameter is altered during the call.
2433 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2434 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2435 * \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.
2437 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2439 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2440 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2442 checkFullyDefined();
2443 otherDimM1OnSameCoords.checkFullyDefined();
2444 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2446 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2448 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2449 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2451 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2452 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2453 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2457 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2459 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462 DataArrayInt *idsTmp=0;
2463 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2466 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2467 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2468 DataArrayInt *tmp0=0,*tmp1=0;
2469 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2473 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2474 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2477 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2478 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2479 nodeIdsToDuplicate=s3.retn();
2483 * This method operates a modification of the connectivity and coords in \b this.
2484 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2485 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2486 * 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
2487 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2488 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2490 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2492 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2493 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2495 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2497 int nbOfNodes=getNumberOfNodes();
2498 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2499 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2503 * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2504 * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2506 * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2508 * \sa renumberNodesInConn
2510 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2512 checkConnectivityFullyDefined();
2513 int *conn(getNodalConnectivity()->getPointer());
2514 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2515 int nbOfCells(getNumberOfCells());
2516 for(int i=0;i<nbOfCells;i++)
2517 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2519 int& node=conn[iconn];
2520 if(node>=0)//avoid polyhedron separator
2525 _nodal_connec->declareAsNew();
2530 * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2531 * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2534 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2536 checkConnectivityFullyDefined();
2537 int *conn(getNodalConnectivity()->getPointer());
2538 const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2539 int nbOfCells(getNumberOfCells());
2540 for(int i=0;i<nbOfCells;i++)
2541 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2543 int& node=conn[iconn];
2544 if(node>=0)//avoid polyhedron separator
2546 INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2547 if(it!=newNodeNumbersO2N.end())
2553 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2554 throw INTERP_KERNEL::Exception(oss.str().c_str());
2558 _nodal_connec->declareAsNew();
2563 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2564 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2565 * This method is a generalization of shiftNodeNumbersInConn().
2566 * \warning This method performs no check of validity of new ids. **Use it with care !**
2567 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2568 * this->getNumberOfNodes(), in "Old to New" mode.
2569 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2570 * \throw If the nodal connectivity of cells is not defined.
2572 * \if ENABLE_EXAMPLES
2573 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2574 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2577 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2579 checkConnectivityFullyDefined();
2580 int *conn=getNodalConnectivity()->getPointer();
2581 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2582 int nbOfCells(getNumberOfCells());
2583 for(int i=0;i<nbOfCells;i++)
2584 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2586 int& node=conn[iconn];
2587 if(node>=0)//avoid polyhedron separator
2589 node=newNodeNumbersO2N[node];
2592 _nodal_connec->declareAsNew();
2597 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2598 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2599 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2601 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2603 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2605 checkConnectivityFullyDefined();
2606 int *conn=getNodalConnectivity()->getPointer();
2607 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2608 int nbOfCells=getNumberOfCells();
2609 for(int i=0;i<nbOfCells;i++)
2610 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2612 int& node=conn[iconn];
2613 if(node>=0)//avoid polyhedron separator
2618 _nodal_connec->declareAsNew();
2623 * This method operates a modification of the connectivity in \b this.
2624 * 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.
2625 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2626 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2627 * 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
2628 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2629 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2631 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2632 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2634 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2635 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2636 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2638 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2640 checkConnectivityFullyDefined();
2641 std::map<int,int> m;
2643 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2645 int *conn=getNodalConnectivity()->getPointer();
2646 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2647 int nbOfCells=getNumberOfCells();
2648 for(int i=0;i<nbOfCells;i++)
2649 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2651 int& node=conn[iconn];
2652 if(node>=0)//avoid polyhedron separator
2654 std::map<int,int>::iterator it=m.find(node);
2663 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2665 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2666 * After the call of this method the number of cells remains the same as before.
2668 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2669 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2670 * be strictly in [0;this->getNumberOfCells()).
2672 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2673 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2674 * should be contained in[0;this->getNumberOfCells()).
2676 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2678 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2680 checkConnectivityFullyDefined();
2681 int nbCells=getNumberOfCells();
2682 const int *array=old2NewBg;
2684 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2686 const int *conn=_nodal_connec->getConstPointer();
2687 const int *connI=_nodal_connec_index->getConstPointer();
2688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2690 const int *n2oPtr=n2o->begin();
2691 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2692 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2693 newConn->copyStringInfoFrom(*_nodal_connec);
2694 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2695 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2696 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2698 int *newC=newConn->getPointer();
2699 int *newCI=newConnI->getPointer();
2702 for(int i=0;i<nbCells;i++)
2705 int nbOfElts=connI[pos+1]-connI[pos];
2706 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2711 setConnectivity(newConn,newConnI);
2713 free(const_cast<int *>(array));
2717 * Finds cells whose bounding boxes intersect a given bounding box.
2718 * \param [in] bbox - an array defining the bounding box via coordinates of its
2719 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2721 * \param [in] eps - a factor used to increase size of the bounding box of cell
2722 * before comparing it with \a bbox. This factor is multiplied by the maximal
2723 * extent of the bounding box of cell to produce an addition to this bounding box.
2724 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2725 * cells. The caller is to delete this array using decrRef() as it is no more
2727 * \throw If the coordinates array is not set.
2728 * \throw If the nodal connectivity of cells is not defined.
2730 * \if ENABLE_EXAMPLES
2731 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2732 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2735 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2737 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2738 if(getMeshDimension()==-1)
2740 elems->pushBackSilent(0);
2741 return elems.retn();
2743 int dim=getSpaceDimension();
2744 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2745 const int* conn = getNodalConnectivity()->getConstPointer();
2746 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2747 const double* coords = getCoords()->getConstPointer();
2748 int nbOfCells=getNumberOfCells();
2749 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2751 for (int i=0; i<dim; i++)
2753 elem_bb[i*2]=std::numeric_limits<double>::max();
2754 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2757 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2759 int node= conn[inode];
2760 if(node>=0)//avoid polyhedron separator
2762 for (int idim=0; idim<dim; idim++)
2764 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2766 elem_bb[idim*2] = coords[node*dim+idim] ;
2768 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2770 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2775 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2776 elems->pushBackSilent(ielem);
2778 return elems.retn();
2782 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2783 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2784 * added in 'elems' parameter.
2786 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2789 if(getMeshDimension()==-1)
2791 elems->pushBackSilent(0);
2792 return elems.retn();
2794 int dim=getSpaceDimension();
2795 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2796 const int* conn = getNodalConnectivity()->getConstPointer();
2797 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2798 const double* coords = getCoords()->getConstPointer();
2799 int nbOfCells=getNumberOfCells();
2800 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2802 for (int i=0; i<dim; i++)
2804 elem_bb[i*2]=std::numeric_limits<double>::max();
2805 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2808 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2810 int node= conn[inode];
2811 if(node>=0)//avoid polyhedron separator
2813 for (int idim=0; idim<dim; idim++)
2815 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2817 elem_bb[idim*2] = coords[node*dim+idim] ;
2819 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2821 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2826 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2827 elems->pushBackSilent(ielem);
2829 return elems.retn();
2833 * Returns a type of a cell by its id.
2834 * \param [in] cellId - the id of the cell of interest.
2835 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2836 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2838 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2840 const int *ptI=_nodal_connec_index->getConstPointer();
2841 const int *pt=_nodal_connec->getConstPointer();
2842 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2843 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2846 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2847 throw INTERP_KERNEL::Exception(oss.str().c_str());
2852 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2853 * This method does not throw exception if geometric type \a type is not in \a this.
2854 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2855 * The coordinates array is not considered here.
2857 * \param [in] type the geometric type
2858 * \return cell ids in this having geometric type \a type.
2860 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2863 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2865 checkConnectivityFullyDefined();
2866 int nbCells=getNumberOfCells();
2867 int mdim=getMeshDimension();
2868 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2869 if(mdim!=(int)cm.getDimension())
2870 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2871 const int *ptI=_nodal_connec_index->getConstPointer();
2872 const int *pt=_nodal_connec->getConstPointer();
2873 for(int i=0;i<nbCells;i++)
2875 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2876 ret->pushBackSilent(i);
2882 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2884 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2886 const int *ptI=_nodal_connec_index->getConstPointer();
2887 const int *pt=_nodal_connec->getConstPointer();
2888 int nbOfCells=getNumberOfCells();
2890 for(int i=0;i<nbOfCells;i++)
2891 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2897 * Returns the nodal connectivity of a given cell.
2898 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2899 * all returned node ids can be used in getCoordinatesOfNode().
2900 * \param [in] cellId - an id of the cell of interest.
2901 * \param [in,out] conn - a vector where the node ids are appended. It is not
2902 * cleared before the appending.
2903 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2905 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2907 const int *ptI=_nodal_connec_index->getConstPointer();
2908 const int *pt=_nodal_connec->getConstPointer();
2909 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2914 std::string MEDCouplingUMesh::simpleRepr() const
2916 static const char msg0[]="No coordinates specified !";
2917 std::ostringstream ret;
2918 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2919 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2921 double tt=getTime(tmpp1,tmpp2);
2922 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2923 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2925 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2927 { ret << " Mesh dimension has not been set or is invalid !"; }
2930 const int spaceDim=getSpaceDimension();
2931 ret << spaceDim << "\nInfo attached on space dimension : ";
2932 for(int i=0;i<spaceDim;i++)
2933 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2937 ret << msg0 << "\n";
2938 ret << "Number of nodes : ";
2940 ret << getNumberOfNodes() << "\n";
2942 ret << msg0 << "\n";
2943 ret << "Number of cells : ";
2944 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2945 ret << getNumberOfCells() << "\n";
2947 ret << "No connectivity specified !" << "\n";
2948 ret << "Cell types present : ";
2949 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2951 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2952 ret << cm.getRepr() << " ";
2958 std::string MEDCouplingUMesh::advancedRepr() const
2960 std::ostringstream ret;
2961 ret << simpleRepr();
2962 ret << "\nCoordinates array : \n___________________\n\n";
2964 _coords->reprWithoutNameStream(ret);
2966 ret << "No array set !\n";
2967 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2968 reprConnectivityOfThisLL(ret);
2973 * This method returns a C++ code that is a dump of \a this.
2974 * This method will throw if this is not fully defined.
2976 std::string MEDCouplingUMesh::cppRepr() const
2978 static const char coordsName[]="coords";
2979 static const char connName[]="conn";
2980 static const char connIName[]="connI";
2981 checkFullyDefined();
2982 std::ostringstream ret; ret << "// coordinates" << std::endl;
2983 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2984 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2985 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2986 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2987 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2988 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2989 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2993 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2995 std::ostringstream ret;
2996 reprConnectivityOfThisLL(ret);
3001 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3002 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3003 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3006 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3007 * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
3008 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3010 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3012 int mdim=getMeshDimension();
3014 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3015 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3017 bool needToCpyCT=true;
3020 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3028 if(!_nodal_connec_index)
3030 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3035 tmp2=_nodal_connec_index;
3038 ret->setConnectivity(tmp1,tmp2,false);
3043 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3044 ret->setCoords(coords);
3047 ret->setCoords(_coords);
3051 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3053 if(_nodal_connec!=0 && _nodal_connec_index!=0)
3055 int nbOfCells=getNumberOfCells();
3056 const int *c=_nodal_connec->getConstPointer();
3057 const int *ci=_nodal_connec_index->getConstPointer();
3058 for(int i=0;i<nbOfCells;i++)
3060 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3061 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3062 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3067 stream << "Connectivity not defined !\n";
3070 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3072 const int *ptI=_nodal_connec_index->getConstPointer();
3073 const int *pt=_nodal_connec->getConstPointer();
3074 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3075 return ptI[cellId+1]-ptI[cellId]-1;
3077 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3081 * Returns types of cells of the specified part of \a this mesh.
3082 * This method avoids computing sub-mesh explicitely to get its types.
3083 * \param [in] begin - an array of cell ids of interest.
3084 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3085 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3086 * describing the cell types.
3087 * \throw If the coordinates array is not set.
3088 * \throw If the nodal connectivity of cells is not defined.
3089 * \sa getAllGeoTypes()
3091 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3093 checkFullyDefined();
3094 std::set<INTERP_KERNEL::NormalizedCellType> ret;
3095 const int *conn=_nodal_connec->getConstPointer();
3096 const int *connIndex=_nodal_connec_index->getConstPointer();
3097 for(const int *w=begin;w!=end;w++)
3098 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3103 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3104 * a set of types of cells constituting \a this mesh.
3105 * This method is for advanced users having prepared their connectivity before. For
3106 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3107 * \param [in] conn - the nodal connectivity array.
3108 * \param [in] connIndex - the nodal connectivity index array.
3109 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3112 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3114 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3115 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3116 if(isComputingTypes)
3122 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3123 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3125 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3126 _nodal_connec(0),_nodal_connec_index(0),
3127 _types(other._types)
3129 if(other._nodal_connec)
3130 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3131 if(other._nodal_connec_index)
3132 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3135 MEDCouplingUMesh::~MEDCouplingUMesh()
3138 _nodal_connec->decrRef();
3139 if(_nodal_connec_index)
3140 _nodal_connec_index->decrRef();
3144 * Recomputes a set of cell types of \a this mesh. For more info see
3145 * \ref MEDCouplingUMeshNodalConnectivity.
3147 void MEDCouplingUMesh::computeTypes()
3149 ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3153 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3155 void MEDCouplingUMesh::checkFullyDefined() const
3157 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3158 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3162 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3164 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3166 if(!_nodal_connec_index || !_nodal_connec)
3167 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3171 * Returns a number of cells constituting \a this mesh.
3172 * \return int - the number of cells in \a this mesh.
3173 * \throw If the nodal connectivity of cells is not defined.
3175 int MEDCouplingUMesh::getNumberOfCells() const
3177 if(_nodal_connec_index)
3178 return _nodal_connec_index->getNumberOfTuples()-1;
3183 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3187 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3188 * mesh. For more info see \ref MEDCouplingMeshesPage.
3189 * \return int - the dimension of \a this mesh.
3190 * \throw If the mesh dimension is not defined using setMeshDimension().
3192 int MEDCouplingUMesh::getMeshDimension() const
3195 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3200 * Returns a length of the nodal connectivity array.
3201 * This method is for test reason. Normally the integer returned is not useable by
3202 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3203 * \return int - the length of the nodal connectivity array.
3205 int MEDCouplingUMesh::getMeshLength() const
3207 return _nodal_connec->getNbOfElems();
3211 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3213 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3215 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3216 tinyInfo.push_back(getMeshDimension());
3217 tinyInfo.push_back(getNumberOfCells());
3219 tinyInfo.push_back(getMeshLength());
3221 tinyInfo.push_back(-1);
3225 * First step of unserialization process.
3227 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3229 return tinyInfo[6]<=0;
3233 * Second step of serialization process.
3234 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3236 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3238 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3240 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3244 * Third and final step of serialization process.
3246 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3248 MEDCouplingPointSet::serialize(a1,a2);
3249 if(getMeshDimension()>-1)
3251 a1=DataArrayInt::New();
3252 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3253 int *ptA1=a1->getPointer();
3254 const int *conn=getNodalConnectivity()->getConstPointer();
3255 const int *index=getNodalConnectivityIndex()->getConstPointer();
3256 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3257 std::copy(conn,conn+getMeshLength(),ptA1);
3264 * Second and final unserialization process.
3265 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3267 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3269 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3270 setMeshDimension(tinyInfo[5]);
3274 const int *recvBuffer=a1->getConstPointer();
3275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3276 myConnecIndex->alloc(tinyInfo[6]+1,1);
3277 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3279 myConnec->alloc(tinyInfo[7],1);
3280 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3281 setConnectivity(myConnec, myConnecIndex);
3286 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3287 * CellIds are given using range specified by a start an end and step.
3289 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3291 checkFullyDefined();
3292 int ncell=getNumberOfCells();
3293 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3294 ret->_mesh_dim=_mesh_dim;
3295 ret->setCoords(_coords);
3296 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3298 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3300 const int *conn=_nodal_connec->getConstPointer();
3301 const int *connIndex=_nodal_connec_index->getConstPointer();
3302 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3304 if(work>=0 && work<ncell)
3306 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3310 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3311 throw INTERP_KERNEL::Exception(oss.str().c_str());
3314 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3315 int *newConnPtr=newConn->getPointer();
3316 std::set<INTERP_KERNEL::NormalizedCellType> types;
3318 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3320 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3321 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3323 ret->setConnectivity(newConn,newConnI,false);
3325 ret->copyTinyInfoFrom(this);
3330 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3331 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3332 * The return newly allocated mesh will share the same coordinates as \a this.
3334 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3336 checkConnectivityFullyDefined();
3337 int ncell=getNumberOfCells();
3338 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3339 ret->_mesh_dim=_mesh_dim;
3340 ret->setCoords(_coords);
3341 std::size_t nbOfElemsRet=std::distance(begin,end);
3342 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3344 const int *conn=_nodal_connec->getConstPointer();
3345 const int *connIndex=_nodal_connec_index->getConstPointer();
3347 for(const int *work=begin;work!=end;work++,newNbring++)
3349 if(*work>=0 && *work<ncell)
3350 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3354 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3355 throw INTERP_KERNEL::Exception(oss.str().c_str());
3358 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3359 int *connRetWork=connRet;
3360 std::set<INTERP_KERNEL::NormalizedCellType> types;
3361 for(const int *work=begin;work!=end;work++)
3363 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3364 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3367 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3369 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3370 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3372 ret->copyTinyInfoFrom(this);
3377 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3379 * For 1D cells, the returned field contains lengths.<br>
3380 * For 2D cells, the returned field contains areas.<br>
3381 * For 3D cells, the returned field contains volumes.
3382 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3383 * orientation, i.e. the volume is always positive.
3384 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3385 * and one time . The caller is to delete this field using decrRef() as it is no
3388 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3390 std::string name="MeasureOfMesh_";
3392 int nbelem=getNumberOfCells();
3393 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3394 field->setName(name);
3395 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3396 array->alloc(nbelem,1);
3397 double *area_vol=array->getPointer();
3398 field->setArray(array) ; array=0;
3399 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3400 field->synchronizeTimeWithMesh();
3401 if(getMeshDimension()!=-1)
3404 INTERP_KERNEL::NormalizedCellType type;
3405 int dim_space=getSpaceDimension();
3406 const double *coords=getCoords()->getConstPointer();
3407 const int *connec=getNodalConnectivity()->getConstPointer();
3408 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3409 for(int iel=0;iel<nbelem;iel++)
3411 ipt=connec_index[iel];
3412 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3413 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);
3416 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3420 area_vol[0]=std::numeric_limits<double>::max();
3422 return field.retn();
3426 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3428 * For 1D cells, the returned array contains lengths.<br>
3429 * For 2D cells, the returned array contains areas.<br>
3430 * For 3D cells, the returned array contains volumes.
3431 * This method avoids building explicitly a part of \a this mesh to perform the work.
3432 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3433 * orientation, i.e. the volume is always positive.
3434 * \param [in] begin - an array of cell ids of interest.
3435 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3436 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3437 * delete this array using decrRef() as it is no more needed.
3439 * \if ENABLE_EXAMPLES
3440 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3441 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3443 * \sa getMeasureField()
3445 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3447 std::string name="PartMeasureOfMesh_";
3449 int nbelem=(int)std::distance(begin,end);
3450 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3451 array->setName(name);
3452 array->alloc(nbelem,1);
3453 double *area_vol=array->getPointer();
3454 if(getMeshDimension()!=-1)
3457 INTERP_KERNEL::NormalizedCellType type;
3458 int dim_space=getSpaceDimension();
3459 const double *coords=getCoords()->getConstPointer();
3460 const int *connec=getNodalConnectivity()->getConstPointer();
3461 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3462 for(const int *iel=begin;iel!=end;iel++)
3464 ipt=connec_index[*iel];
3465 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3466 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3469 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3473 area_vol[0]=std::numeric_limits<double>::max();
3475 return array.retn();
3479 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3480 * \a this one. The returned field contains the dual cell volume for each corresponding
3481 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3482 * the dual mesh in P1 sens of \a this.<br>
3483 * For 1D cells, the returned field contains lengths.<br>
3484 * For 2D cells, the returned field contains areas.<br>
3485 * For 3D cells, the returned field contains volumes.
3486 * This method is useful to check "P1*" conservative interpolators.
3487 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3488 * orientation, i.e. the volume is always positive.
3489 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3490 * nodes and one time. The caller is to delete this array using decrRef() as
3491 * it is no more needed.
3493 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3495 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3496 std::string name="MeasureOnNodeOfMesh_";
3498 int nbNodes=getNumberOfNodes();
3499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3500 double cst=1./((double)getMeshDimension()+1.);
3501 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3502 array->alloc(nbNodes,1);
3503 double *valsToFill=array->getPointer();
3504 std::fill(valsToFill,valsToFill+nbNodes,0.);
3505 const double *values=tmp->getArray()->getConstPointer();
3506 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3508 getReverseNodalConnectivity(da,daInd);
3509 const int *daPtr=da->getConstPointer();
3510 const int *daIPtr=daInd->getConstPointer();
3511 for(int i=0;i<nbNodes;i++)
3512 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3513 valsToFill[i]+=cst*values[*cell];
3515 ret->setArray(array);
3520 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3521 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3522 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3523 * and are normalized.
3524 * <br> \a this can be either
3525 * - a 2D mesh in 2D or 3D space or
3526 * - an 1D mesh in 2D space.
3528 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3529 * cells and one time. The caller is to delete this field using decrRef() as
3530 * it is no more needed.
3531 * \throw If the nodal connectivity of cells is not defined.
3532 * \throw If the coordinates array is not set.
3533 * \throw If the mesh dimension is not set.
3534 * \throw If the mesh and space dimension is not as specified above.
3536 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3538 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3539 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3540 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3541 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3542 int nbOfCells=getNumberOfCells();
3543 int nbComp=getMeshDimension()+1;
3544 array->alloc(nbOfCells,nbComp);
3545 double *vals=array->getPointer();
3546 const int *connI=_nodal_connec_index->getConstPointer();
3547 const int *conn=_nodal_connec->getConstPointer();
3548 const double *coords=_coords->getConstPointer();
3549 if(getMeshDimension()==2)
3551 if(getSpaceDimension()==3)
3553 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3554 const double *locPtr=loc->getConstPointer();
3555 for(int i=0;i<nbOfCells;i++,vals+=3)
3557 int offset=connI[i];
3558 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3559 double n=INTERP_KERNEL::norm<3>(vals);
3560 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3565 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3566 const double *isAbsPtr=isAbs->getArray()->begin();
3567 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3568 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3571 else//meshdimension==1
3574 for(int i=0;i<nbOfCells;i++)
3576 int offset=connI[i];
3577 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3578 double n=INTERP_KERNEL::norm<2>(tmp);
3579 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3584 ret->setArray(array);
3586 ret->synchronizeTimeWithSupport();
3591 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3592 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3593 * and are normalized.
3594 * <br> \a this can be either
3595 * - a 2D mesh in 2D or 3D space or
3596 * - an 1D mesh in 2D space.
3598 * This method avoids building explicitly a part of \a this mesh to perform the work.
3599 * \param [in] begin - an array of cell ids of interest.
3600 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3601 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3602 * cells and one time. The caller is to delete this field using decrRef() as
3603 * it is no more needed.
3604 * \throw If the nodal connectivity of cells is not defined.
3605 * \throw If the coordinates array is not set.
3606 * \throw If the mesh dimension is not set.
3607 * \throw If the mesh and space dimension is not as specified above.
3608 * \sa buildOrthogonalField()
3610 * \if ENABLE_EXAMPLES
3611 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3612 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3615 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3617 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3618 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3619 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3620 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3621 std::size_t nbelems=std::distance(begin,end);
3622 int nbComp=getMeshDimension()+1;
3623 array->alloc((int)nbelems,nbComp);
3624 double *vals=array->getPointer();
3625 const int *connI=_nodal_connec_index->getConstPointer();
3626 const int *conn=_nodal_connec->getConstPointer();
3627 const double *coords=_coords->getConstPointer();
3628 if(getMeshDimension()==2)
3630 if(getSpaceDimension()==3)
3632 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3633 const double *locPtr=loc->getConstPointer();
3634 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3636 int offset=connI[*i];
3637 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3638 double n=INTERP_KERNEL::norm<3>(vals);
3639 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3644 for(std::size_t i=0;i<nbelems;i++)
3645 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3648 else//meshdimension==1
3651 for(const int *i=begin;i!=end;i++)
3653 int offset=connI[*i];
3654 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3655 double n=INTERP_KERNEL::norm<2>(tmp);
3656 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3661 ret->setArray(array);
3663 ret->synchronizeTimeWithSupport();
3668 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3669 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3670 * and are \b not normalized.
3671 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3672 * cells and one time. The caller is to delete this field using decrRef() as
3673 * it is no more needed.
3674 * \throw If the nodal connectivity of cells is not defined.
3675 * \throw If the coordinates array is not set.
3676 * \throw If \a this->getMeshDimension() != 1.
3677 * \throw If \a this mesh includes cells of type other than SEG2.
3679 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3681 if(getMeshDimension()!=1)
3682 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3683 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3684 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3685 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3686 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3687 int nbOfCells=getNumberOfCells();
3688 int spaceDim=getSpaceDimension();
3689 array->alloc(nbOfCells,spaceDim);
3690 double *pt=array->getPointer();
3691 const double *coo=getCoords()->getConstPointer();
3692 std::vector<int> conn;
3694 for(int i=0;i<nbOfCells;i++)
3697 getNodeIdsOfCell(i,conn);
3698 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3700 ret->setArray(array);
3702 ret->synchronizeTimeWithSupport();
3707 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3708 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3709 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3710 * from. If a result face is shared by two 3D cells, then the face in included twice in
3712 * \param [in] origin - 3 components of a point defining location of the plane.
3713 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3714 * must be greater than 1e-6.
3715 * \param [in] eps - half-thickness of the plane.
3716 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3717 * producing correspondent 2D cells. The caller is to delete this array
3718 * using decrRef() as it is no more needed.
3719 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3720 * not share the node coordinates array with \a this mesh. The caller is to
3721 * delete this mesh using decrRef() as it is no more needed.
3722 * \throw If the coordinates array is not set.
3723 * \throw If the nodal connectivity of cells is not defined.
3724 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3725 * \throw If magnitude of \a vec is less than 1e-6.
3726 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3727 * \throw If \a this includes quadratic cells.
3729 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3731 checkFullyDefined();
3732 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3733 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3735 if(candidates->empty())
3736 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3737 std::vector<int> nodes;
3738 DataArrayInt *cellIds1D=0;
3739 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3740 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3742 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3744 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3745 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3746 revDesc2=0; revDescIndx2=0;
3747 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3748 revDesc1=0; revDescIndx1=0;
3749 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3750 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3752 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3753 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3755 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3756 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3757 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3758 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3759 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3761 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3762 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3763 if(cellIds2->empty())
3764 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3765 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3766 ret->setCoords(mDesc1->getCoords());
3767 ret->setConnectivity(conn,connI,true);
3768 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3773 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3774 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3775 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3777 * \param [in] origin - 3 components of a point defining location of the plane.
3778 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3779 * must be greater than 1e-6.
3780 * \param [in] eps - half-thickness of the plane.
3781 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3782 * producing correspondent segments. The caller is to delete this array
3783 * using decrRef() as it is no more needed.
3784 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3785 * mesh in 3D space. This mesh does not share the node coordinates array with
3786 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3788 * \throw If the coordinates array is not set.
3789 * \throw If the nodal connectivity of cells is not defined.
3790 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3791 * \throw If magnitude of \a vec is less than 1e-6.
3792 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3793 * \throw If \a this includes quadratic cells.
3795 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3797 checkFullyDefined();
3798 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3799 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3801 if(candidates->empty())
3802 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3803 std::vector<int> nodes;
3804 DataArrayInt *cellIds1D=0;
3805 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3806 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3807 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3811 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3812 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3815 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3816 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3818 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3819 int ncellsSub=subMesh->getNumberOfCells();
3820 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3821 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3822 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3823 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3824 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3826 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3827 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3828 for(int i=0;i<ncellsSub;i++)
3830 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3832 if(cut3DSurf[i].first!=-2)
3834 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3835 connI->pushBackSilent(conn->getNumberOfTuples());
3836 cellIds2->pushBackSilent(i);
3840 int cellId3DSurf=cut3DSurf[i].second;
3841 int offset=nodalI[cellId3DSurf]+1;
3842 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3843 for(int j=0;j<nbOfEdges;j++)
3845 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3846 connI->pushBackSilent(conn->getNumberOfTuples());
3847 cellIds2->pushBackSilent(cellId3DSurf);
3852 if(cellIds2->empty())
3853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3854 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3855 ret->setCoords(mDesc1->getCoords());
3856 ret->setConnectivity(conn,connI,true);
3857 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3862 * Finds cells whose bounding boxes intersect a given plane.
3863 * \param [in] origin - 3 components of a point defining location of the plane.
3864 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3865 * must be greater than 1e-6.
3866 * \param [in] eps - half-thickness of the plane.
3867 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3868 * cells. The caller is to delete this array using decrRef() as it is no more
3870 * \throw If the coordinates array is not set.
3871 * \throw If the nodal connectivity of cells is not defined.
3872 * \throw If \a this->getSpaceDimension() != 3.
3873 * \throw If magnitude of \a vec is less than 1e-6.
3874 * \sa buildSlice3D()
3876 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3878 checkFullyDefined();
3879 if(getSpaceDimension()!=3)
3880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3881 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3883 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3885 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3886 double angle=acos(vec[2]/normm);
3887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3891 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3892 double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3893 if(normm2/normm>1e-6)
3894 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3895 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3897 mw->getBoundingBox(bbox);
3898 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3899 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3903 getBoundingBox(bbox);
3904 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3905 cellIds=getCellsInBoundingBox(bbox,eps);
3907 return cellIds.retn();
3911 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3912 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3913 * No consideration of coordinate is done by this method.
3914 * 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)
3915 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3917 bool MEDCouplingUMesh::isContiguous1D() const
3919 if(getMeshDimension()!=1)
3920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3921 int nbCells=getNumberOfCells();
3923 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3924 const int *connI=_nodal_connec_index->getConstPointer();
3925 const int *conn=_nodal_connec->getConstPointer();
3926 int ref=conn[connI[0]+2];
3927 for(int i=1;i<nbCells;i++)
3929 if(conn[connI[i]+1]!=ref)
3931 ref=conn[connI[i]+2];
3937 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3938 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3939 * \param pt reference point of the line
3940 * \param v normalized director vector of the line
3941 * \param eps max precision before throwing an exception
3942 * \param res output of size this->getNumberOfCells
3944 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3946 if(getMeshDimension()!=1)
3947 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3948 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3949 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3950 if(getSpaceDimension()!=3)
3951 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3952 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3953 const double *fPtr=f->getArray()->getConstPointer();
3955 for(int i=0;i<getNumberOfCells();i++)
3957 const double *tmp1=fPtr+3*i;
3958 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3959 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3960 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3961 double n1=INTERP_KERNEL::norm<3>(tmp);
3962 n1/=INTERP_KERNEL::norm<3>(tmp1);
3964 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3966 const double *coo=getCoords()->getConstPointer();
3967 for(int i=0;i<getNumberOfNodes();i++)
3969 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3970 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3971 res[i]=std::accumulate(tmp,tmp+3,0.);
3976 * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance.
3977 * \a this is expected to be a mesh so that its space dimension is equal to its
3978 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3979 * 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).
3981 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3982 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3983 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3985 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3986 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3988 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3989 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3990 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3991 * \return the positive value of the distance.
3992 * \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
3994 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3996 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3998 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3999 if(meshDim!=spaceDim-1)
4000 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4001 if(meshDim!=2 && meshDim!=1)
4002 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4003 checkFullyDefined();
4004 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4005 { 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()); }
4006 DataArrayInt *ret1=0;
4007 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4008 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4009 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4010 cellId=*ret1Safe->begin();
4011 return *ret0->begin();
4015 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4016 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
4017 * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4018 * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4019 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4021 * \a this is expected to be a mesh so that its space dimension is equal to its
4022 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4023 * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4025 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4026 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4028 * \param [in] pts the list of points in which each tuple represents a point
4029 * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
4030 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4031 * \throw if number of components of \a pts is not equal to the space dimension.
4032 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4033 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4035 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4038 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4039 pts->checkAllocated();
4040 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4041 if(meshDim!=spaceDim-1)
4042 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4043 if(meshDim!=2 && meshDim!=1)
4044 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4045 if(pts->getNumberOfComponents()!=spaceDim)
4047 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4048 throw INTERP_KERNEL::Exception(oss.str().c_str());
4050 checkFullyDefined();
4051 int nbCells=getNumberOfCells();
4053 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4054 int nbOfPts=pts->getNumberOfTuples();
4055 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4056 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4057 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4058 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4059 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4060 const double *bbox(bboxArr->begin());
4065 BBTreeDst<3> myTree(bbox,0,0,nbCells);
4066 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4068 double x=std::numeric_limits<double>::max();
4069 std::vector<int> elems;
4070 myTree.getMinDistanceOfMax(ptsPtr,x);
4071 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4072 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4078 BBTreeDst<2> myTree(bbox,0,0,nbCells);
4079 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4081 double x=std::numeric_limits<double>::max();
4082 std::vector<int> elems;
4083 myTree.getMinDistanceOfMax(ptsPtr,x);
4084 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4085 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4090 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4092 cellIds=ret1.retn();
4097 * \param [in] pt the start pointer (included) of the coordinates of the point
4098 * \param [in] cellIdsBg the start pointer (included) of cellIds
4099 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4100 * \param [in] nc nodal connectivity
4101 * \param [in] ncI nodal connectivity index
4102 * \param [in,out] ret0 the min distance between \a this and the external input point
4103 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4104 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4106 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4109 ret0=std::numeric_limits<double>::max();
4110 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4112 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4114 case INTERP_KERNEL::NORM_TRI3:
4116 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4118 { ret0=tmp; cellId=*zeCell; }
4121 case INTERP_KERNEL::NORM_QUAD4:
4122 case INTERP_KERNEL::NORM_POLYGON:
4124 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4126 { ret0=tmp; cellId=*zeCell; }
4130 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4136 * \param [in] pt the start pointer (included) of the coordinates of the point
4137 * \param [in] cellIdsBg the start pointer (included) of cellIds
4138 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4139 * \param [in] nc nodal connectivity
4140 * \param [in] ncI nodal connectivity index
4141 * \param [in,out] ret0 the min distance between \a this and the external input point
4142 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4143 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4145 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4148 ret0=std::numeric_limits<double>::max();
4149 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4151 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4153 case INTERP_KERNEL::NORM_SEG2:
4155 std::size_t uselessEntry=0;
4156 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4159 { ret0=tmp; cellId=*zeCell; }
4163 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4169 * Finds cells in contact with a ball (i.e. a point with precision).
4170 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4171 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4173 * \warning This method is suitable if the caller intends to evaluate only one
4174 * point, for more points getCellsContainingPoints() is recommended as it is
4176 * \param [in] pos - array of coordinates of the ball central point.
4177 * \param [in] eps - ball radius.
4178 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4179 * if there are no such cells.
4180 * \throw If the coordinates array is not set.
4181 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4183 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4185 std::vector<int> elts;
4186 getCellsContainingPoint(pos,eps,elts);
4189 return elts.front();
4193 * Finds cells in contact with a ball (i.e. a point with precision).
4194 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4195 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4196 * \warning This method is suitable if the caller intends to evaluate only one
4197 * point, for more points getCellsContainingPoints() is recommended as it is
4199 * \param [in] pos - array of coordinates of the ball central point.
4200 * \param [in] eps - ball radius.
4201 * \param [out] elts - vector returning ids of the found cells. It is cleared
4202 * before inserting ids.
4203 * \throw If the coordinates array is not set.
4204 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4206 * \if ENABLE_EXAMPLES
4207 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4208 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4211 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4214 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4215 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4220 namespace ParaMEDMEM
4222 template<const int SPACEDIMM>
4226 static const int MY_SPACEDIM=SPACEDIMM;
4227 static const int MY_MESHDIM=8;
4228 typedef int MyConnType;
4229 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4231 // useless, but for windows compilation ...
4232 const double* getCoordinatesPtr() const { return 0; }
4233 const int* getConnectivityPtr() const { return 0; }
4234 const int* getConnectivityIndexPtr() const { return 0; }
4235 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4239 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4241 INTERP_KERNEL::Edge *ret(0);
4242 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4243 m[n0]=bg[0]; m[n1]=bg[1];
4246 case INTERP_KERNEL::NORM_SEG2:
4248 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4251 case INTERP_KERNEL::NORM_SEG3:
4253 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4254 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4255 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4256 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4257 bool colinearity(inters.areColinears());
4258 delete e1; delete e2;
4260 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4262 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4266 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4271 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4273 INTERP_KERNEL::Edge *ret=0;
4276 case INTERP_KERNEL::NORM_SEG2:
4278 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4281 case INTERP_KERNEL::NORM_SEG3:
4283 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4284 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4285 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4286 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4287 bool colinearity=inters.areColinears();
4288 delete e1; delete e2;
4290 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4292 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4293 mapp2[bg[2]].second=false;
4297 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4303 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4304 * the global mesh 'mDesc'.
4305 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4306 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4308 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4309 std::map<INTERP_KERNEL::Node *,int>& mapp)
4312 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.
4313 const double *coo=mDesc->getCoords()->getConstPointer();
4314 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4315 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4317 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4318 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4319 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4321 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4322 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4324 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4325 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4327 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4328 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4330 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4332 if((*it2).second.second)
4333 mapp[(*it2).second.first]=(*it2).first;
4334 ((*it2).second.first)->decrRef();
4339 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4343 int locId=nodeId-offset2;
4344 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4348 int locId=nodeId-offset1;
4349 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4351 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4355 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4357 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4358 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4359 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4361 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4363 int eltId1=abs(*desc1)-1;
4364 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4366 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4367 if(it==mappRev.end())
4369 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4380 template<int SPACEDIM>
4381 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4382 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4384 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4385 int *eltsIndexPtr(eltsIndex->getPointer());
4386 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4387 const double *bbox(bboxArr->begin());
4388 int nbOfCells=getNumberOfCells();
4389 const int *conn=_nodal_connec->getConstPointer();
4390 const int *connI=_nodal_connec_index->getConstPointer();
4391 double bb[2*SPACEDIM];
4392 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4393 for(int i=0;i<nbOfPoints;i++)
4395 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4396 for(int j=0;j<SPACEDIM;j++)
4398 bb[2*j]=pos[SPACEDIM*i+j];
4399 bb[2*j+1]=pos[SPACEDIM*i+j];
4401 std::vector<int> candidates;
4402 myTree.getIntersectingElems(bb,candidates);
4403 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4405 int sz(connI[(*iter)+1]-connI[*iter]-1);
4406 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4408 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4409 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4414 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4415 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4416 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4417 INTERP_KERNEL::QuadraticPolygon *pol(0);
4418 for(int j=0;j<sz;j++)
4420 int nodeId(conn[connI[*iter]+1+j]);
4421 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4423 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4424 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4426 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4427 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4428 double a(0.),b(0.),c(0.);
4429 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4430 status=pol->isInOrOut2(n);
4431 delete pol; n->decrRef();
4435 eltsIndexPtr[i+1]++;
4436 elts->pushBackSilent(*iter);
4442 * Finds cells in contact with several balls (i.e. points with precision).
4443 * This method is an extension of getCellContainingPoint() and
4444 * getCellsContainingPoint() for the case of multiple points.
4445 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4446 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4447 * \param [in] pos - an array of coordinates of points in full interlace mode :
4448 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4449 * this->getSpaceDimension() * \a nbOfPoints
4450 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4451 * \param [in] eps - radius of balls (i.e. the precision).
4452 * \param [out] elts - vector returning ids of found cells.
4453 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4454 * dividing cell ids in \a elts into groups each referring to one
4455 * point. Its every element (except the last one) is an index pointing to the
4456 * first id of a group of cells. For example cells in contact with the *i*-th
4457 * point are described by following range of indices:
4458 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4459 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4460 * Number of cells in contact with the *i*-th point is
4461 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4462 * \throw If the coordinates array is not set.
4463 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4465 * \if ENABLE_EXAMPLES
4466 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4467 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4470 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4473 int spaceDim=getSpaceDimension();
4474 int mDim=getMeshDimension();
4479 const double *coords=_coords->getConstPointer();
4480 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4487 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4489 else if(spaceDim==2)
4493 const double *coords=_coords->getConstPointer();
4494 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4497 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4499 else if(spaceDim==1)
4503 const double *coords=_coords->getConstPointer();
4504 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4507 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4510 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4514 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4515 * least two its edges intersect each other anywhere except their extremities. An
4516 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4517 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4518 * cleared before filling in.
4519 * \param [in] eps - precision.
4520 * \throw If \a this->getMeshDimension() != 2.
4521 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4523 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4525 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4526 if(getMeshDimension()!=2)
4527 throw INTERP_KERNEL::Exception(msg);
4528 int spaceDim=getSpaceDimension();
4529 if(spaceDim!=2 && spaceDim!=3)
4530 throw INTERP_KERNEL::Exception(msg);
4531 const int *conn=_nodal_connec->getConstPointer();
4532 const int *connI=_nodal_connec_index->getConstPointer();
4533 int nbOfCells=getNumberOfCells();
4534 std::vector<double> cell2DinS2;
4535 for(int i=0;i<nbOfCells;i++)
4537 int offset=connI[i];
4538 int nbOfNodesForCell=connI[i+1]-offset-1;
4539 if(nbOfNodesForCell<=3)
4541 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4542 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4543 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4550 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4552 * 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.
4553 * 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.
4555 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4556 * This convex envelop is computed using Jarvis march algorithm.
4557 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4558 * 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)
4559 * 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.
4561 * \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.
4562 * \sa MEDCouplingUMesh::colinearize2D
4564 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4566 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4568 checkFullyDefined();
4569 const double *coords=getCoords()->getConstPointer();
4570 int nbOfCells=getNumberOfCells();
4571 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4572 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4573 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4574 int *workIndexOut=nodalConnecIndexOut->getPointer();
4576 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4577 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4578 std::set<INTERP_KERNEL::NormalizedCellType> types;
4579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4580 isChanged->alloc(0,1);
4581 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4583 int pos=nodalConnecOut->getNumberOfTuples();
4584 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4585 isChanged->pushBackSilent(i);
4586 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4587 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4589 if(isChanged->empty())
4591 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4593 return isChanged.retn();
4597 * This method is \b NOT const because it can modify \a this.
4598 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4599 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4600 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4601 * \b 1 for translation and rotation around point of 'mesh1D'.
4602 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4604 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4606 checkFullyDefined();
4607 mesh1D->checkFullyDefined();
4608 if(!mesh1D->isContiguous1D())
4609 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4610 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4611 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4612 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4613 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4614 if(mesh1D->getMeshDimension()!=1)
4615 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4617 if(isPresenceOfQuadratic())
4619 if(mesh1D->isFullyQuadratic())
4622 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4624 int oldNbOfNodes(getNumberOfNodes());
4625 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4630 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4635 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4639 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4641 setCoords(newCoords);
4642 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4648 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4649 * If it is not the case an exception will be thrown.
4650 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4651 * intersection of plane defined by ('origin','vec').
4652 * This method has one in/out parameter : 'cut3DCurve'.
4653 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4654 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4655 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4656 * This method will throw an exception if \a this contains a non linear segment.
4658 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4660 checkFullyDefined();
4661 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4662 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4663 int ncells=getNumberOfCells();
4664 int nnodes=getNumberOfNodes();
4665 double vec2[3],vec3[3],vec4[3];
4666 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4668 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4669 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4670 const int *conn=_nodal_connec->getConstPointer();
4671 const int *connI=_nodal_connec_index->getConstPointer();
4672 const double *coo=_coords->getConstPointer();
4673 std::vector<double> addCoo;
4674 for(int i=0;i<ncells;i++)
4676 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4678 if(cut3DCurve[i]==-2)
4680 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4681 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];
4682 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4683 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4684 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4686 const double *st2=coo+3*st;
4687 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4688 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]));
4689 if(pos>eps && pos<1-eps)
4691 int nNode=((int)addCoo.size())/3;
4692 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4693 addCoo.insert(addCoo.end(),vec4,vec4+3);
4694 cut3DCurve[i]=nnodes+nNode;
4700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4704 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4705 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4706 coo2->alloc(newNbOfNodes,3);
4707 double *tmp=coo2->getPointer();
4708 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4709 std::copy(addCoo.begin(),addCoo.end(),tmp);
4710 DataArrayDouble::SetArrayIn(coo2,_coords);
4715 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4716 * \param mesh1D is the input 1D mesh used for translation computation.
4717 * \return newCoords new coords filled by this method.
4719 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4721 int oldNbOfNodes=getNumberOfNodes();
4722 int nbOf1DCells=mesh1D->getNumberOfCells();
4723 int spaceDim=getSpaceDimension();
4724 DataArrayDouble *ret=DataArrayDouble::New();
4725 std::vector<bool> isQuads;
4726 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4727 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4728 double *retPtr=ret->getPointer();
4729 const double *coords=getCoords()->getConstPointer();
4730 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4732 std::vector<double> c;
4736 for(int i=0;i<nbOf1DCells;i++)
4739 mesh1D->getNodeIdsOfCell(i,v);
4741 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4742 mesh1D->getCoordinatesOfNode(v[0],c);
4743 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4744 for(int j=0;j<oldNbOfNodes;j++)
4745 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4749 mesh1D->getCoordinatesOfNode(v[1],c);
4750 mesh1D->getCoordinatesOfNode(v[0],c);
4751 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4752 for(int j=0;j<oldNbOfNodes;j++)
4753 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4756 ret->copyStringInfoFrom(*getCoords());
4761 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4762 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4763 * \return newCoords new coords filled by this method.
4765 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4767 if(mesh1D->getSpaceDimension()==2)
4768 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4769 if(mesh1D->getSpaceDimension()==3)
4770 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4771 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4775 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4776 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4777 * \return newCoords new coords filled by this method.
4779 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4783 int oldNbOfNodes=getNumberOfNodes();
4784 int nbOf1DCells=mesh1D->getNumberOfCells();
4786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4787 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4788 int nbOfLevsInVec=nbOf1DCells+1;
4789 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4790 double *retPtr=ret->getPointer();
4791 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4792 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4793 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4794 tmp->setCoords(tmp2);
4795 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4796 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4797 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4798 for(int i=1;i<nbOfLevsInVec;i++)
4800 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4801 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4802 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4803 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4804 tmp->translate(vec);
4805 double tmp3[2],radius,alpha,alpha0;
4806 const double *p0=i+1<nbOfLevsInVec?begin:third;
4807 const double *p1=i+1<nbOfLevsInVec?end:begin;
4808 const double *p2=i+1<nbOfLevsInVec?third:end;
4809 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4810 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]);
4811 double angle=acos(cosangle/(radius*radius));
4812 tmp->rotate(end,0,angle);
4813 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4819 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4820 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4821 * \return newCoords new coords filled by this method.
4823 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4827 int oldNbOfNodes=getNumberOfNodes();
4828 int nbOf1DCells=mesh1D->getNumberOfCells();
4830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4831 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4832 int nbOfLevsInVec=nbOf1DCells+1;
4833 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4834 double *retPtr=ret->getPointer();
4835 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4836 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4837 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4838 tmp->setCoords(tmp2);
4839 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4840 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4841 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4842 for(int i=1;i<nbOfLevsInVec;i++)
4844 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4845 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4846 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4847 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4848 tmp->translate(vec);
4849 double tmp3[2],radius,alpha,alpha0;
4850 const double *p0=i+1<nbOfLevsInVec?begin:third;
4851 const double *p1=i+1<nbOfLevsInVec?end:begin;
4852 const double *p2=i+1<nbOfLevsInVec?third:end;
4853 double vecPlane[3]={
4854 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4855 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4856 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4858 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4861 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4862 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4863 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4865 double c2=cos(asin(s2));
4867 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4868 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4869 {-vec2[1]*s2, vec2[0]*s2, c2}
4871 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]};
4872 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]};
4873 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]};
4874 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4875 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]);
4876 double angle=acos(cosangle/(radius*radius));
4877 tmp->rotate(end,vecPlane,angle);
4879 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4885 * This method is private because not easy to use for end user. This method is const contrary to
4886 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4887 * the coords sorted slice by slice.
4888 * \param isQuad specifies presence of quadratic cells.
4890 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4892 int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4893 int nbOf2DCells(getNumberOfCells());
4894 int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4895 MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4896 const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4897 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4898 newConnI->alloc(nbOf3DCells+1,1);
4899 int *newConnIPtr(newConnI->getPointer());
4901 std::vector<int> newc;
4902 for(int j=0;j<nbOf2DCells;j++)
4904 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4905 *newConnIPtr++=(int)newc.size();
4907 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4908 int *newConnPtr(newConn->getPointer());
4909 int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4910 newConnIPtr=newConnI->getPointer();
4911 for(int iz=0;iz<nbOf1DCells;iz++)
4914 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4915 const int *posOfTypeOfCell(newConnIPtr);
4916 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4918 int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4919 if(icell!=*posOfTypeOfCell)
4922 *newConnPtr=(*iter)+iz*deltaPerLev;
4933 ret->setConnectivity(newConn,newConnI,true);
4934 ret->setCoords(getCoords());
4939 * Checks if \a this mesh is constituted by only quadratic cells.
4940 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4941 * \throw If the coordinates array is not set.
4942 * \throw If the nodal connectivity of cells is not defined.
4944 bool MEDCouplingUMesh::isFullyQuadratic() const
4946 checkFullyDefined();
4948 int nbOfCells=getNumberOfCells();
4949 for(int i=0;i<nbOfCells && ret;i++)
4951 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4952 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4953 ret=cm.isQuadratic();
4959 * Checks if \a this mesh includes any quadratic cell.
4960 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4961 * \throw If the coordinates array is not set.
4962 * \throw If the nodal connectivity of cells is not defined.
4964 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4966 checkFullyDefined();
4968 int nbOfCells=getNumberOfCells();
4969 for(int i=0;i<nbOfCells && !ret;i++)
4971 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4972 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4973 ret=cm.isQuadratic();
4979 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4980 * this mesh, it remains unchanged.
4981 * \throw If the coordinates array is not set.
4982 * \throw If the nodal connectivity of cells is not defined.
4984 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4986 checkFullyDefined();
4987 int nbOfCells=getNumberOfCells();
4989 const int *iciptr=_nodal_connec_index->getConstPointer();
4990 for(int i=0;i<nbOfCells;i++)
4992 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4993 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4994 if(cm.isQuadratic())
4996 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4997 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4998 if(!cml.isDynamic())
4999 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5001 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5006 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5007 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5008 const int *icptr=_nodal_connec->getConstPointer();
5009 newConn->alloc(getMeshLength()-delta,1);
5010 newConnI->alloc(nbOfCells+1,1);
5011 int *ocptr=newConn->getPointer();
5012 int *ociptr=newConnI->getPointer();
5015 for(int i=0;i<nbOfCells;i++,ociptr++)
5017 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5018 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5019 if(!cm.isQuadratic())
5021 _types.insert(type);
5022 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5023 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5027 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5028 _types.insert(typel);
5029 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5030 int newNbOfNodes=cml.getNumberOfNodes();
5032 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5033 *ocptr++=(int)typel;
5034 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5035 ociptr[1]=ociptr[0]+newNbOfNodes+1;
5038 setConnectivity(newConn,newConnI,false);
5042 * This method converts all linear cell in \a this to quadratic one.
5043 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5044 * 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)
5045 * 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.
5046 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5047 * end of the existing coordinates.
5049 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5050 * corresponding quadratic cells. 1 is those creating the 'most' complex.
5051 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5053 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5055 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5057 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5059 DataArrayInt *conn=0,*connI=0;
5060 DataArrayDouble *coords=0;
5061 std::set<INTERP_KERNEL::NormalizedCellType> types;
5062 checkFullyDefined();
5063 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5065 int meshDim=getMeshDimension();
5066 switch(conversionType)
5072 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5073 connSafe=conn; connISafe=connI; coordsSafe=coords;
5076 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5077 connSafe=conn; connISafe=connI; coordsSafe=coords;
5080 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5081 connSafe=conn; connISafe=connI; coordsSafe=coords;
5084 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5092 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5093 connSafe=conn; connISafe=connI; coordsSafe=coords;
5096 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5097 connSafe=conn; connISafe=connI; coordsSafe=coords;
5100 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5101 connSafe=conn; connISafe=connI; coordsSafe=coords;
5104 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5111 setConnectivity(connSafe,connISafe,false);
5113 setCoords(coordsSafe);
5119 * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5120 * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5121 * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd.
5122 * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5123 * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5124 * This method can be seen as the opposite method of colinearize2D.
5125 * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5126 * to avoid to modify the numbering of existing nodes.
5128 * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5129 * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5130 * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5131 * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5132 * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5133 * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5134 * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5136 * \sa buildDescendingConnectivity2
5138 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5139 const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5141 if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5142 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5143 nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5144 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5145 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5146 if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5147 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5148 //DataArrayInt *out0(0),*outi0(0);
5149 //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5150 //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5151 //out0s=out0s->buildUnique(); out0s->sort(true);
5156 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5157 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5158 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5160 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5162 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5166 int nbOfCells=getNumberOfCells();
5167 int nbOfNodes=getNumberOfNodes();
5168 const int *cPtr=_nodal_connec->getConstPointer();
5169 const int *icPtr=_nodal_connec_index->getConstPointer();
5170 int lastVal=0,offset=nbOfNodes;
5171 for(int i=0;i<nbOfCells;i++,icPtr++)
5173 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5174 if(type==INTERP_KERNEL::NORM_SEG2)
5176 types.insert(INTERP_KERNEL::NORM_SEG3);
5177 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5178 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5179 newConn->pushBackSilent(offset++);
5181 newConnI->pushBackSilent(lastVal);
5182 ret->pushBackSilent(i);
5187 lastVal+=(icPtr[1]-icPtr[0]);
5188 newConnI->pushBackSilent(lastVal);
5189 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5192 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5193 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5197 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
5199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5203 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5204 DataArrayInt *conn1D=0,*conn1DI=0;
5205 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5206 DataArrayDouble *coordsTmp=0;
5207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5208 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5210 const int *c1DPtr=conn1D->begin();
5211 const int *c1DIPtr=conn1DI->begin();
5212 int nbOfCells=getNumberOfCells();
5213 const int *cPtr=_nodal_connec->getConstPointer();
5214 const int *icPtr=_nodal_connec_index->getConstPointer();
5216 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5218 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5219 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5220 if(!cm.isQuadratic())
5222 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5223 types.insert(typ2); newConn->pushBackSilent(typ2);
5224 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5225 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5226 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5227 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5228 newConnI->pushBackSilent(lastVal);
5229 ret->pushBackSilent(i);
5234 lastVal+=(icPtr[1]-icPtr[0]);
5235 newConnI->pushBackSilent(lastVal);
5236 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5239 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5244 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5245 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5246 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5248 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5251 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5252 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5255 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5258 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5264 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5265 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5266 DataArrayInt *conn1D=0,*conn1DI=0;
5267 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5268 DataArrayDouble *coordsTmp=0;
5269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5272 const int *c1DPtr=conn1D->begin();
5273 const int *c1DIPtr=conn1DI->begin();
5274 int nbOfCells=getNumberOfCells();
5275 const int *cPtr=_nodal_connec->getConstPointer();
5276 const int *icPtr=_nodal_connec_index->getConstPointer();
5277 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5278 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5280 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5281 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5282 if(!cm.isQuadratic())
5284 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5285 types.insert(typ2); newConn->pushBackSilent(typ2);
5286 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5287 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5288 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5289 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5290 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5291 newConnI->pushBackSilent(lastVal);
5292 ret->pushBackSilent(i);
5297 lastVal+=(icPtr[1]-icPtr[0]);
5298 newConnI->pushBackSilent(lastVal);
5299 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5302 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5303 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5308 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5309 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5310 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5312 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5314 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5315 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5316 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5319 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5322 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5324 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5326 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5330 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5331 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5332 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5333 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5334 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5337 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5339 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5340 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5341 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5342 int nbOfCells=getNumberOfCells();
5343 const int *cPtr=_nodal_connec->getConstPointer();
5344 const int *icPtr=_nodal_connec_index->getConstPointer();
5345 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5346 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5348 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5349 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5350 if(!cm.isQuadratic())
5352 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5353 if(typ2==INTERP_KERNEL::NORM_ERROR)
5355 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5356 throw INTERP_KERNEL::Exception(oss.str().c_str());
5358 types.insert(typ2); newConn->pushBackSilent(typ2);
5359 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5360 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5361 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5362 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5364 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5365 int tmpPos=newConn->getNumberOfTuples();
5366 newConn->pushBackSilent(nodeId2);
5367 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5369 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5370 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5371 newConnI->pushBackSilent(lastVal);
5372 ret->pushBackSilent(i);
5377 lastVal+=(icPtr[1]-icPtr[0]);
5378 newConnI->pushBackSilent(lastVal);
5379 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5384 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5385 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5386 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5387 int *c=newConn->getPointer();
5388 const int *cI(newConnI->begin());
5389 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5390 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5391 offset=coordsTmp2Safe->getNumberOfTuples();
5392 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5393 c[cI[(*elt)+1]-1]+=offset;
5394 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5399 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5400 * so that the number of cells remains the same. Quadratic faces are converted to
5401 * polygons. This method works only for 2D meshes in
5402 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5403 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5404 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5405 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5406 * a polylinized edge constituting the input polygon.
5407 * \throw If the coordinates array is not set.
5408 * \throw If the nodal connectivity of cells is not defined.
5409 * \throw If \a this->getMeshDimension() != 2.
5410 * \throw If \a this->getSpaceDimension() != 2.
5412 void MEDCouplingUMesh::tessellate2D(double eps)
5414 checkFullyDefined();
5415 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5416 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5417 double epsa=fabs(eps);
5418 if(epsa<std::numeric_limits<double>::min())
5419 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 !");
5420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5422 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5423 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5424 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5425 revDesc1=0; revDescIndx1=0;
5426 mDesc->tessellate2DCurve(eps);
5427 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5428 setCoords(mDesc->getCoords());
5432 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5433 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5434 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5435 * a sub-divided edge.
5436 * \throw If the coordinates array is not set.
5437 * \throw If the nodal connectivity of cells is not defined.
5438 * \throw If \a this->getMeshDimension() != 1.
5439 * \throw If \a this->getSpaceDimension() != 2.
5441 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5443 checkFullyDefined();
5444 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5446 double epsa=fabs(eps);
5447 if(epsa<std::numeric_limits<double>::min())
5448 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 !");
5449 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5450 int nbCells=getNumberOfCells();
5451 int nbNodes=getNumberOfNodes();
5452 const int *conn=_nodal_connec->getConstPointer();
5453 const int *connI=_nodal_connec_index->getConstPointer();
5454 const double *coords=_coords->getConstPointer();
5455 std::vector<double> addCoo;
5456 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5458 newConnI->alloc(nbCells+1,1);
5459 int *newConnIPtr=newConnI->getPointer();
5462 INTERP_KERNEL::Node *tmp2[3];
5463 std::set<INTERP_KERNEL::NormalizedCellType> types;
5464 for(int i=0;i<nbCells;i++,newConnIPtr++)
5466 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5467 if(cm.isQuadratic())
5468 {//assert(connI[i+1]-connI[i]-1==3)
5469 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5470 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5471 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5472 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5473 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5476 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5477 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5479 newConnIPtr[1]=(int)newConn.size();
5483 types.insert(INTERP_KERNEL::NORM_SEG2);
5484 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5485 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5486 newConnIPtr[1]=newConnIPtr[0]+3;
5491 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5492 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5493 newConnIPtr[1]=newConnIPtr[0]+3;
5496 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5499 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5500 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5501 newConnArr->alloc((int)newConn.size(),1);
5502 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5503 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5504 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5505 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5506 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5507 std::copy(addCoo.begin(),addCoo.end(),work);
5508 DataArrayDouble::SetArrayIn(newCoords,_coords);
5513 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5514 * In addition, returns an array mapping new cells to old ones. <br>
5515 * This method typically increases the number of cells in \a this mesh
5516 * but the number of nodes remains \b unchanged.
5517 * That's why the 3D splitting policies
5518 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5519 * \param [in] policy - specifies a pattern used for splitting.
5520 * The semantic of \a policy is:
5521 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5522 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5523 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5524 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5525 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5526 * an id of old cell producing it. The caller is to delete this array using
5527 * decrRef() as it is no more needed.
5528 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5529 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5530 * and \a this->getMeshDimension() != 3.
5531 * \throw If \a policy is not one of the four discussed above.
5532 * \throw If the nodal connectivity of cells is not defined.
5533 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5535 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5540 return simplexizePol0();
5542 return simplexizePol1();
5543 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5544 return simplexizePlanarFace5();
5545 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5546 return simplexizePlanarFace6();
5548 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)");
5553 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5554 * - 1D: INTERP_KERNEL::NORM_SEG2
5555 * - 2D: INTERP_KERNEL::NORM_TRI3
5556 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5558 * This method is useful for users that need to use P1 field services as
5559 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5560 * All these methods need mesh support containing only simplex cells.
5561 * \return bool - \c true if there are only simplex cells in \a this mesh.
5562 * \throw If the coordinates array is not set.
5563 * \throw If the nodal connectivity of cells is not defined.
5564 * \throw If \a this->getMeshDimension() < 1.
5566 bool MEDCouplingUMesh::areOnlySimplexCells() const
5568 checkFullyDefined();
5569 int mdim=getMeshDimension();
5570 if(mdim<1 || mdim>3)
5571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5572 int nbCells=getNumberOfCells();
5573 const int *conn=_nodal_connec->getConstPointer();
5574 const int *connI=_nodal_connec_index->getConstPointer();
5575 for(int i=0;i<nbCells;i++)
5577 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5585 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5587 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5589 checkConnectivityFullyDefined();
5590 if(getMeshDimension()!=2)
5591 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5592 int nbOfCells=getNumberOfCells();
5593 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5594 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5595 ret->alloc(nbOfCells+nbOfCutCells,1);
5596 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5597 int *retPt=ret->getPointer();
5598 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5600 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5601 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5602 int *pt=newConn->getPointer();
5603 int *ptI=newConnI->getPointer();
5605 const int *oldc=_nodal_connec->getConstPointer();
5606 const int *ci=_nodal_connec_index->getConstPointer();
5607 for(int i=0;i<nbOfCells;i++,ci++)
5609 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5611 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5612 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5613 pt=std::copy(tmp,tmp+8,pt);
5622 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5623 ptI[1]=ptI[0]+ci[1]-ci[0];
5628 _nodal_connec->decrRef();
5629 _nodal_connec=newConn.retn();
5630 _nodal_connec_index->decrRef();
5631 _nodal_connec_index=newConnI.retn();
5638 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5640 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5642 checkConnectivityFullyDefined();
5643 if(getMeshDimension()!=2)
5644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5645 int nbOfCells=getNumberOfCells();
5646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5647 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5648 ret->alloc(nbOfCells+nbOfCutCells,1);
5649 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5650 int *retPt=ret->getPointer();
5651 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5652 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5653 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5654 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5655 int *pt=newConn->getPointer();
5656 int *ptI=newConnI->getPointer();
5658 const int *oldc=_nodal_connec->getConstPointer();
5659 const int *ci=_nodal_connec_index->getConstPointer();
5660 for(int i=0;i<nbOfCells;i++,ci++)
5662 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5664 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5665 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5666 pt=std::copy(tmp,tmp+8,pt);
5675 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5676 ptI[1]=ptI[0]+ci[1]-ci[0];
5681 _nodal_connec->decrRef();
5682 _nodal_connec=newConn.retn();
5683 _nodal_connec_index->decrRef();
5684 _nodal_connec_index=newConnI.retn();
5691 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5693 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5695 checkConnectivityFullyDefined();
5696 if(getMeshDimension()!=3)
5697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5698 int nbOfCells=getNumberOfCells();
5699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5700 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5701 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5702 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5703 int *retPt=ret->getPointer();
5704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5706 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5707 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5708 int *pt=newConn->getPointer();
5709 int *ptI=newConnI->getPointer();
5711 const int *oldc=_nodal_connec->getConstPointer();
5712 const int *ci=_nodal_connec_index->getConstPointer();
5713 for(int i=0;i<nbOfCells;i++,ci++)
5715 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5717 for(int j=0;j<5;j++,pt+=5,ptI++)
5719 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5720 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];
5727 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5728 ptI[1]=ptI[0]+ci[1]-ci[0];
5733 _nodal_connec->decrRef();
5734 _nodal_connec=newConn.retn();
5735 _nodal_connec_index->decrRef();
5736 _nodal_connec_index=newConnI.retn();
5743 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5745 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5747 checkConnectivityFullyDefined();
5748 if(getMeshDimension()!=3)
5749 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5750 int nbOfCells=getNumberOfCells();
5751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5752 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5753 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5754 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5755 int *retPt=ret->getPointer();
5756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5758 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5759 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5760 int *pt=newConn->getPointer();
5761 int *ptI=newConnI->getPointer();
5763 const int *oldc=_nodal_connec->getConstPointer();
5764 const int *ci=_nodal_connec_index->getConstPointer();
5765 for(int i=0;i<nbOfCells;i++,ci++)
5767 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5769 for(int j=0;j<6;j++,pt+=5,ptI++)
5771 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5772 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];
5779 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5780 ptI[1]=ptI[0]+ci[1]-ci[0];
5785 _nodal_connec->decrRef();
5786 _nodal_connec=newConn.retn();
5787 _nodal_connec_index->decrRef();
5788 _nodal_connec_index=newConnI.retn();
5795 * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5796 * This method completly ignore coordinates.
5797 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5798 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5799 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5800 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5802 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5804 checkFullyDefined();
5805 if(getMeshDimension()!=2)
5806 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5807 int nbOfCells=getNumberOfCells();
5808 int *connI=_nodal_connec_index->getPointer();
5810 for(int i=0;i<nbOfCells;i++,connI++)
5812 int offset=descIndex[i];
5813 int nbOfEdges=descIndex[i+1]-offset;
5815 bool ddirect=desc[offset+nbOfEdges-1]>0;
5816 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5817 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5818 for(int j=0;j<nbOfEdges;j++)
5820 bool direct=desc[offset+j]>0;
5821 int edgeId=std::abs(desc[offset+j])-1;
5822 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5824 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5825 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5826 int ref2=direct?id1:id2;
5829 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5830 newConnLgth+=nbOfSubNodes-1;
5835 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5836 throw INTERP_KERNEL::Exception(oss.str().c_str());
5841 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5844 newConnLgth++;//+1 is for cell type
5845 connI[1]=newConnLgth;
5848 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5849 newConn->alloc(newConnLgth,1);
5850 int *work=newConn->getPointer();
5851 for(int i=0;i<nbOfCells;i++)
5853 *work++=INTERP_KERNEL::NORM_POLYGON;
5854 int offset=descIndex[i];
5855 int nbOfEdges=descIndex[i+1]-offset;
5856 for(int j=0;j<nbOfEdges;j++)
5858 bool direct=desc[offset+j]>0;
5859 int edgeId=std::abs(desc[offset+j])-1;
5861 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5864 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5865 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5866 work=std::copy(it,it+nbOfSubNodes-1,work);
5870 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5873 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5877 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5878 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5879 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5880 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5881 * so it can be useful to call mergeNodes() before calling this method.
5882 * \throw If \a this->getMeshDimension() <= 1.
5883 * \throw If the coordinates array is not set.
5884 * \throw If the nodal connectivity of cells is not defined.
5886 void MEDCouplingUMesh::convertDegeneratedCells()
5888 checkFullyDefined();
5889 if(getMeshDimension()<=1)
5890 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5891 int nbOfCells=getNumberOfCells();
5894 int initMeshLgth=getMeshLength();
5895 int *conn=_nodal_connec->getPointer();
5896 int *index=_nodal_connec_index->getPointer();
5900 for(int i=0;i<nbOfCells;i++)
5902 lgthOfCurCell=index[i+1]-posOfCurCell;
5903 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5905 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5906 conn+newPos+1,newLgth);
5907 conn[newPos]=newType;
5909 posOfCurCell=index[i+1];
5912 if(newPos!=initMeshLgth)
5913 _nodal_connec->reAlloc(newPos);
5918 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5919 * A cell is considered to be oriented correctly if an angle between its
5920 * normal vector and a given vector is less than \c PI / \c 2.
5921 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5923 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5925 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5926 * is not cleared before filling in.
5927 * \throw If \a this->getMeshDimension() != 2.
5928 * \throw If \a this->getSpaceDimension() != 3.
5930 * \if ENABLE_EXAMPLES
5931 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5932 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5935 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5937 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5938 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5939 int nbOfCells=getNumberOfCells();
5940 const int *conn=_nodal_connec->getConstPointer();
5941 const int *connI=_nodal_connec_index->getConstPointer();
5942 const double *coordsPtr=_coords->getConstPointer();
5943 for(int i=0;i<nbOfCells;i++)
5945 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5946 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5948 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5949 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5956 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5957 * considered to be oriented correctly if an angle between its normal vector and a
5958 * given vector is less than \c PI / \c 2.
5959 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5961 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5963 * \throw If \a this->getMeshDimension() != 2.
5964 * \throw If \a this->getSpaceDimension() != 3.
5966 * \if ENABLE_EXAMPLES
5967 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5968 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5971 * \sa changeOrientationOfCells
5973 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5975 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5976 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5977 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5978 const int *connI(_nodal_connec_index->getConstPointer());
5979 const double *coordsPtr(_coords->getConstPointer());
5980 bool isModified(false);
5981 for(int i=0;i<nbOfCells;i++)
5983 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5984 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5986 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5987 bool isQuadratic(cm.isQuadratic());
5988 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5991 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
5996 _nodal_connec->declareAsNew();
6001 * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6003 * \sa orientCorrectly2DCells
6005 void MEDCouplingUMesh::changeOrientationOfCells()
6007 int mdim(getMeshDimension());
6008 if(mdim!=2 && mdim!=1)
6009 throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6010 int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6011 const int *connI(_nodal_connec_index->getConstPointer());
6014 for(int i=0;i<nbOfCells;i++)
6016 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6017 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6018 cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6023 for(int i=0;i<nbOfCells;i++)
6025 INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6026 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6027 cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6033 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6034 * oriented facets. The normal vector of the facet should point out of the cell.
6035 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6036 * is not cleared before filling in.
6037 * \throw If \a this->getMeshDimension() != 3.
6038 * \throw If \a this->getSpaceDimension() != 3.
6039 * \throw If the coordinates array is not set.
6040 * \throw If the nodal connectivity of cells is not defined.
6042 * \if ENABLE_EXAMPLES
6043 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6044 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6047 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6049 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6050 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6051 int nbOfCells=getNumberOfCells();
6052 const int *conn=_nodal_connec->getConstPointer();
6053 const int *connI=_nodal_connec_index->getConstPointer();
6054 const double *coordsPtr=_coords->getConstPointer();
6055 for(int i=0;i<nbOfCells;i++)
6057 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6058 if(type==INTERP_KERNEL::NORM_POLYHED)
6060 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6067 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6069 * \throw If \a this->getMeshDimension() != 3.
6070 * \throw If \a this->getSpaceDimension() != 3.
6071 * \throw If the coordinates array is not set.
6072 * \throw If the nodal connectivity of cells is not defined.
6073 * \throw If the reparation fails.
6075 * \if ENABLE_EXAMPLES
6076 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6077 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6079 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6081 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6083 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6084 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6085 int nbOfCells=getNumberOfCells();
6086 int *conn=_nodal_connec->getPointer();
6087 const int *connI=_nodal_connec_index->getConstPointer();
6088 const double *coordsPtr=_coords->getConstPointer();
6089 for(int i=0;i<nbOfCells;i++)
6091 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6092 if(type==INTERP_KERNEL::NORM_POLYHED)
6096 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6097 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6099 catch(INTERP_KERNEL::Exception& e)
6101 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6102 throw INTERP_KERNEL::Exception(oss.str().c_str());
6110 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6111 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6112 * according to which the first facet of the cell should be oriented to have the normal vector
6113 * pointing out of cell.
6114 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6115 * cells. The caller is to delete this array using decrRef() as it is no more
6117 * \throw If \a this->getMeshDimension() != 3.
6118 * \throw If \a this->getSpaceDimension() != 3.
6119 * \throw If the coordinates array is not set.
6120 * \throw If the nodal connectivity of cells is not defined.
6122 * \if ENABLE_EXAMPLES
6123 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6124 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6126 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6128 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6130 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6131 if(getMeshDimension()!=3)
6132 throw INTERP_KERNEL::Exception(msg);
6133 int spaceDim=getSpaceDimension();
6135 throw INTERP_KERNEL::Exception(msg);
6137 int nbOfCells=getNumberOfCells();
6138 int *conn=_nodal_connec->getPointer();
6139 const int *connI=_nodal_connec_index->getConstPointer();
6140 const double *coo=getCoords()->getConstPointer();
6141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6142 for(int i=0;i<nbOfCells;i++)
6144 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6145 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6147 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6149 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6150 cells->pushBackSilent(i);
6154 return cells.retn();
6158 * This method is a faster method to correct orientation of all 3D cells in \a this.
6159 * 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.
6160 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6162 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6163 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6165 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6167 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6168 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6169 int nbOfCells=getNumberOfCells();
6170 int *conn=_nodal_connec->getPointer();
6171 const int *connI=_nodal_connec_index->getConstPointer();
6172 const double *coordsPtr=_coords->getConstPointer();
6173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6174 for(int i=0;i<nbOfCells;i++)
6176 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6179 case INTERP_KERNEL::NORM_TETRA4:
6181 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6183 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6184 ret->pushBackSilent(i);
6188 case INTERP_KERNEL::NORM_PYRA5:
6190 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6192 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6193 ret->pushBackSilent(i);
6197 case INTERP_KERNEL::NORM_PENTA6:
6198 case INTERP_KERNEL::NORM_HEXA8:
6199 case INTERP_KERNEL::NORM_HEXGP12:
6201 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6203 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6204 ret->pushBackSilent(i);
6208 case INTERP_KERNEL::NORM_POLYHED:
6210 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6212 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6213 ret->pushBackSilent(i);
6218 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 !");
6226 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6227 * If it is not the case an exception will be thrown.
6228 * This method is fast because the first cell of \a this is used to compute the plane.
6229 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6230 * \param pos output of size at least 3 used to store a point owned of searched plane.
6232 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6234 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6235 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6236 const int *conn=_nodal_connec->getConstPointer();
6237 const int *connI=_nodal_connec_index->getConstPointer();
6238 const double *coordsPtr=_coords->getConstPointer();
6239 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6240 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6244 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6245 * cells. Currently cells of the following types are treated:
6246 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6247 * For a cell of other type an exception is thrown.
6248 * Space dimension of a 2D mesh can be either 2 or 3.
6249 * The Edge Ratio of a cell \f$t\f$ is:
6250 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6251 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6252 * the smallest edge lengths of \f$t\f$.
6253 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6254 * cells and one time, lying on \a this mesh. The caller is to delete this
6255 * field using decrRef() as it is no more needed.
6256 * \throw If the coordinates array is not set.
6257 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6258 * \throw If the connectivity data array has more than one component.
6259 * \throw If the connectivity data array has a named component.
6260 * \throw If the connectivity index data array has more than one component.
6261 * \throw If the connectivity index data array has a named component.
6262 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6263 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6264 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6266 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6269 int spaceDim=getSpaceDimension();
6270 int meshDim=getMeshDimension();
6271 if(spaceDim!=2 && spaceDim!=3)
6272 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6273 if(meshDim!=2 && meshDim!=3)
6274 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6275 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6277 int nbOfCells=getNumberOfCells();
6278 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6279 arr->alloc(nbOfCells,1);
6280 double *pt=arr->getPointer();
6281 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6282 const int *conn=_nodal_connec->getConstPointer();
6283 const int *connI=_nodal_connec_index->getConstPointer();
6284 const double *coo=_coords->getConstPointer();
6286 for(int i=0;i<nbOfCells;i++,pt++)
6288 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6291 case INTERP_KERNEL::NORM_TRI3:
6293 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6294 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6297 case INTERP_KERNEL::NORM_QUAD4:
6299 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6300 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6303 case INTERP_KERNEL::NORM_TETRA4:
6305 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6306 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6312 conn+=connI[i+1]-connI[i];
6314 ret->setName("EdgeRatio");
6315 ret->synchronizeTimeWithSupport();
6320 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6321 * cells. Currently cells of the following types are treated:
6322 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6323 * For a cell of other type an exception is thrown.
6324 * Space dimension of a 2D mesh can be either 2 or 3.
6325 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6326 * cells and one time, lying on \a this mesh. The caller is to delete this
6327 * field using decrRef() as it is no more needed.
6328 * \throw If the coordinates array is not set.
6329 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6330 * \throw If the connectivity data array has more than one component.
6331 * \throw If the connectivity data array has a named component.
6332 * \throw If the connectivity index data array has more than one component.
6333 * \throw If the connectivity index data array has a named component.
6334 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6335 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6336 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6338 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6341 int spaceDim=getSpaceDimension();
6342 int meshDim=getMeshDimension();
6343 if(spaceDim!=2 && spaceDim!=3)
6344 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6345 if(meshDim!=2 && meshDim!=3)
6346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6347 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6349 int nbOfCells=getNumberOfCells();
6350 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6351 arr->alloc(nbOfCells,1);
6352 double *pt=arr->getPointer();
6353 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6354 const int *conn=_nodal_connec->getConstPointer();
6355 const int *connI=_nodal_connec_index->getConstPointer();
6356 const double *coo=_coords->getConstPointer();
6358 for(int i=0;i<nbOfCells;i++,pt++)
6360 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6363 case INTERP_KERNEL::NORM_TRI3:
6365 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6366 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6369 case INTERP_KERNEL::NORM_QUAD4:
6371 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6372 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6375 case INTERP_KERNEL::NORM_TETRA4:
6377 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6378 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6382 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6384 conn+=connI[i+1]-connI[i];
6386 ret->setName("AspectRatio");
6387 ret->synchronizeTimeWithSupport();
6392 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6393 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6394 * treated: INTERP_KERNEL::NORM_QUAD4.
6395 * For a cell of other type an exception is thrown.
6396 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6397 * cells and one time, lying on \a this mesh. The caller is to delete this
6398 * field using decrRef() as it is no more needed.
6399 * \throw If the coordinates array is not set.
6400 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6401 * \throw If the connectivity data array has more than one component.
6402 * \throw If the connectivity data array has a named component.
6403 * \throw If the connectivity index data array has more than one component.
6404 * \throw If the connectivity index data array has a named component.
6405 * \throw If \a this->getMeshDimension() != 2.
6406 * \throw If \a this->getSpaceDimension() != 3.
6407 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6409 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6412 int spaceDim=getSpaceDimension();
6413 int meshDim=getMeshDimension();
6415 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6417 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6418 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6420 int nbOfCells=getNumberOfCells();
6421 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6422 arr->alloc(nbOfCells,1);
6423 double *pt=arr->getPointer();
6424 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6425 const int *conn=_nodal_connec->getConstPointer();
6426 const int *connI=_nodal_connec_index->getConstPointer();
6427 const double *coo=_coords->getConstPointer();
6429 for(int i=0;i<nbOfCells;i++,pt++)
6431 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6434 case INTERP_KERNEL::NORM_QUAD4:
6436 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6437 *pt=INTERP_KERNEL::quadWarp(tmp);
6441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6443 conn+=connI[i+1]-connI[i];
6445 ret->setName("Warp");
6446 ret->synchronizeTimeWithSupport();
6452 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6453 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6454 * treated: INTERP_KERNEL::NORM_QUAD4.
6455 * For a cell of other type an exception is thrown.
6456 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6457 * cells and one time, lying on \a this mesh. The caller is to delete this
6458 * field using decrRef() as it is no more needed.
6459 * \throw If the coordinates array is not set.
6460 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6461 * \throw If the connectivity data array has more than one component.
6462 * \throw If the connectivity data array has a named component.
6463 * \throw If the connectivity index data array has more than one component.
6464 * \throw If the connectivity index data array has a named component.
6465 * \throw If \a this->getMeshDimension() != 2.
6466 * \throw If \a this->getSpaceDimension() != 3.
6467 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6469 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6472 int spaceDim=getSpaceDimension();
6473 int meshDim=getMeshDimension();
6475 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6477 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6478 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6480 int nbOfCells=getNumberOfCells();
6481 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6482 arr->alloc(nbOfCells,1);
6483 double *pt=arr->getPointer();
6484 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6485 const int *conn=_nodal_connec->getConstPointer();
6486 const int *connI=_nodal_connec_index->getConstPointer();
6487 const double *coo=_coords->getConstPointer();
6489 for(int i=0;i<nbOfCells;i++,pt++)
6491 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6494 case INTERP_KERNEL::NORM_QUAD4:
6496 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6497 *pt=INTERP_KERNEL::quadSkew(tmp);
6501 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6503 conn+=connI[i+1]-connI[i];
6505 ret->setName("Skew");
6506 ret->synchronizeTimeWithSupport();
6511 * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
6513 * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6515 * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6517 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6520 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6522 std::set<INTERP_KERNEL::NormalizedCellType> types;
6523 ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6524 int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6525 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6526 arr->alloc(nbCells,1);
6527 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6529 INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6530 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6531 dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6534 ret->setName("Diameter");
6539 * This method aggregate the bbox of each cell and put it into bbox parameter.
6541 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6542 * For all other cases this input parameter is ignored.
6543 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6545 * \throw If \a this is not fully set (coordinates and connectivity).
6546 * \throw If a cell in \a this has no valid nodeId.
6547 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6549 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6551 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6552 if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3)) // Compute refined boundary box for quadratic elements only in 2D.
6553 return getBoundingBoxForBBTreeFast();
6554 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6556 bool presenceOfQuadratic(false);
6557 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6559 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6560 if(cm.isQuadratic())
6561 presenceOfQuadratic=true;
6563 if(!presenceOfQuadratic)
6564 return getBoundingBoxForBBTreeFast();
6565 if(mDim==2 && sDim==2)
6566 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6568 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6570 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6574 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6575 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6577 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6579 * \throw If \a this is not fully set (coordinates and connectivity).
6580 * \throw If a cell in \a this has no valid nodeId.
6582 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6584 checkFullyDefined();
6585 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6586 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6587 double *bbox(ret->getPointer());
6588 for(int i=0;i<nbOfCells*spaceDim;i++)
6590 bbox[2*i]=std::numeric_limits<double>::max();
6591 bbox[2*i+1]=-std::numeric_limits<double>::max();
6593 const double *coordsPtr(_coords->getConstPointer());
6594 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6595 for(int i=0;i<nbOfCells;i++)
6597 int offset=connI[i]+1;
6598 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6599 for(int j=0;j<nbOfNodesForCell;j++)
6601 int nodeId=conn[offset+j];
6602 if(nodeId>=0 && nodeId<nbOfNodes)
6604 for(int k=0;k<spaceDim;k++)
6606 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6607 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6614 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6615 throw INTERP_KERNEL::Exception(oss.str().c_str());
6622 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6623 * useful for 2D meshes having quadratic cells
6624 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6625 * the two extremities of the arc of circle).
6627 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6628 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6629 * \throw If \a this is not fully defined.
6630 * \throw If \a this is not a mesh with meshDimension equal to 2.
6631 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6632 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6634 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6636 checkFullyDefined();
6637 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6638 if(spaceDim!=2 || mDim!=2)
6639 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6640 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6641 double *bbox(ret->getPointer());
6642 const double *coords(_coords->getConstPointer());
6643 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6644 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6646 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6647 int sz(connI[1]-connI[0]-1);
6648 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6649 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6650 INTERP_KERNEL::QuadraticPolygon *pol(0);
6651 for(int j=0;j<sz;j++)
6653 int nodeId(conn[*connI+1+j]);
6654 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6656 if(!cm.isQuadratic())
6657 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6659 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6660 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6661 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6667 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6668 * useful for 2D meshes having quadratic cells
6669 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6670 * the two extremities of the arc of circle).
6672 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6673 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6674 * \throw If \a this is not fully defined.
6675 * \throw If \a this is not a mesh with meshDimension equal to 1.
6676 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6677 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6679 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6681 checkFullyDefined();
6682 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6683 if(spaceDim!=2 || mDim!=1)
6684 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6685 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6686 double *bbox(ret->getPointer());
6687 const double *coords(_coords->getConstPointer());
6688 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6689 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6691 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6692 int sz(connI[1]-connI[0]-1);
6693 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6694 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6695 INTERP_KERNEL::Edge *edge(0);
6696 for(int j=0;j<sz;j++)
6698 int nodeId(conn[*connI+1+j]);
6699 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6701 if(!cm.isQuadratic())
6702 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6704 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6705 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6706 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6713 namespace ParaMEDMEMImpl
6718 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6719 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6728 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6729 bool operator() (const int& pos) { return _conn[pos]==_val; }
6739 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6740 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6741 * \a this is composed in cell types.
6742 * The returned array is of size 3*n where n is the number of different types present in \a this.
6743 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6744 * This parameter is kept only for compatibility with other methode listed above.
6746 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6748 checkConnectivityFullyDefined();
6749 const int *conn=_nodal_connec->getConstPointer();
6750 const int *connI=_nodal_connec_index->getConstPointer();
6751 const int *work=connI;
6752 int nbOfCells=getNumberOfCells();
6753 std::size_t n=getAllGeoTypes().size();
6754 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6755 std::set<INTERP_KERNEL::NormalizedCellType> types;
6756 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6758 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6759 if(types.find(typ)!=types.end())
6761 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6762 oss << " is not contiguous !";
6763 throw INTERP_KERNEL::Exception(oss.str().c_str());
6767 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6768 ret[3*i+1]=(int)std::distance(work,work2);
6775 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6776 * only for types cell, type node is not managed.
6777 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6778 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6779 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6780 * If 2 or more same geometric type is in \a code and exception is thrown too.
6782 * This method firstly checks
6783 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6784 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6785 * an exception is thrown too.
6787 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6788 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6789 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6791 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6795 std::size_t sz=code.size();
6798 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6799 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6801 bool isNoPflUsed=true;
6802 for(std::size_t i=0;i<n;i++)
6803 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6805 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6807 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6809 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6815 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6817 if(types.size()==_types.size())
6820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6822 int *retPtr=ret->getPointer();
6823 const int *connI=_nodal_connec_index->getConstPointer();
6824 const int *conn=_nodal_connec->getConstPointer();
6825 int nbOfCells=getNumberOfCells();
6828 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6830 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6831 int offset=(int)std::distance(connI,i);
6832 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6833 int nbOfCellsOfCurType=(int)std::distance(i,j);
6834 if(code[3*kk+2]==-1)
6835 for(int k=0;k<nbOfCellsOfCurType;k++)
6839 int idInIdsPerType=code[3*kk+2];
6840 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6842 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6845 zePfl->checkAllocated();
6846 if(zePfl->getNumberOfComponents()==1)
6848 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6850 if(*k>=0 && *k<nbOfCellsOfCurType)
6851 *retPtr=(*k)+offset;
6854 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6855 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6856 throw INTERP_KERNEL::Exception(oss.str().c_str());
6861 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6868 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6869 oss << " should be in [0," << idsPerType.size() << ") !";
6870 throw INTERP_KERNEL::Exception(oss.str().c_str());
6879 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6880 * 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.
6881 * 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.
6882 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6884 * \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.
6885 * \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,
6886 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6887 * \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.
6888 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6889 * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6891 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6894 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6895 if(profile->getNumberOfComponents()!=1)
6896 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6897 checkConnectivityFullyDefined();
6898 const int *conn=_nodal_connec->getConstPointer();
6899 const int *connI=_nodal_connec_index->getConstPointer();
6900 int nbOfCells=getNumberOfCells();
6901 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6902 std::vector<int> typeRangeVals(1);
6903 for(const int *i=connI;i!=connI+nbOfCells;)
6905 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6906 if(std::find(types.begin(),types.end(),curType)!=types.end())
6908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6910 types.push_back(curType);
6911 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6912 typeRangeVals.push_back((int)std::distance(connI,i));
6915 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6916 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6918 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6921 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6922 code.resize(3*nbOfCastsFinal);
6923 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6924 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6925 for(int i=0;i<nbOfCastsFinal;i++)
6927 int castId=castsPresent->getIJ(i,0);
6928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6929 idsInPflPerType2.push_back(tmp3);
6930 code[3*i]=(int)types[castId];
6931 code[3*i+1]=tmp3->getNumberOfTuples();
6932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6933 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6935 tmp4->copyStringInfoFrom(*profile);
6936 idsPerType2.push_back(tmp4);
6937 code[3*i+2]=(int)idsPerType2.size()-1;
6944 std::size_t sz2=idsInPflPerType2.size();
6945 idsInPflPerType.resize(sz2);
6946 for(std::size_t i=0;i<sz2;i++)
6948 DataArrayInt *locDa=idsInPflPerType2[i];
6950 idsInPflPerType[i]=locDa;
6952 std::size_t sz=idsPerType2.size();
6953 idsPerType.resize(sz);
6954 for(std::size_t i=0;i<sz;i++)
6956 DataArrayInt *locDa=idsPerType2[i];
6958 idsPerType[i]=locDa;
6963 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6964 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6965 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6966 * 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.
6968 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6970 checkFullyDefined();
6971 nM1LevMesh->checkFullyDefined();
6972 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6973 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6974 if(_coords!=nM1LevMesh->getCoords())
6975 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6978 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6979 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6980 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6981 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6982 tmp->setConnectivity(tmp0,tmp1);
6983 tmp->renumberCells(ret0->getConstPointer(),false);
6984 revDesc=tmp->getNodalConnectivity();
6985 revDescIndx=tmp->getNodalConnectivityIndex();
6986 DataArrayInt *ret=0;
6987 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6990 ret->getMaxValue(tmp2);
6992 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6993 throw INTERP_KERNEL::Exception(oss.str().c_str());
6998 revDescIndx->incrRef();
7001 meshnM1Old2New=ret0;
7006 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7007 * necessary for writing the mesh to MED file. Additionally returns a permutation array
7008 * in "Old to New" mode.
7009 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7010 * this array using decrRef() as it is no more needed.
7011 * \throw If the nodal connectivity of cells is not defined.
7013 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7015 checkConnectivityFullyDefined();
7016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7017 renumberCells(ret->getConstPointer(),false);
7022 * This methods checks that cells are sorted by their types.
7023 * This method makes asumption (no check) that connectivity is correctly set before calling.
7025 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7027 checkFullyDefined();
7028 const int *conn=_nodal_connec->getConstPointer();
7029 const int *connI=_nodal_connec_index->getConstPointer();
7030 int nbOfCells=getNumberOfCells();
7031 std::set<INTERP_KERNEL::NormalizedCellType> types;
7032 for(const int *i=connI;i!=connI+nbOfCells;)
7034 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7035 if(types.find(curType)!=types.end())
7037 types.insert(curType);
7038 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7044 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7045 * The geometric type order is specified by MED file.
7047 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7049 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7051 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7055 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7056 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7057 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7058 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7060 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7062 checkFullyDefined();
7063 const int *conn=_nodal_connec->getConstPointer();
7064 const int *connI=_nodal_connec_index->getConstPointer();
7065 int nbOfCells=getNumberOfCells();
7069 std::set<INTERP_KERNEL::NormalizedCellType> sg;
7070 for(const int *i=connI;i!=connI+nbOfCells;)
7072 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7073 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7074 if(isTypeExists!=orderEnd)
7076 int pos=(int)std::distance(orderBg,isTypeExists);
7080 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7084 if(sg.find(curType)==sg.end())
7086 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7097 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7098 * 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
7099 * 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'.
7101 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7103 checkConnectivityFullyDefined();
7104 int nbOfCells=getNumberOfCells();
7105 const int *conn=_nodal_connec->getConstPointer();
7106 const int *connI=_nodal_connec_index->getConstPointer();
7107 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7109 tmpa->alloc(nbOfCells,1);
7110 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7111 tmpb->fillWithZero();
7112 int *tmp=tmpa->getPointer();
7113 int *tmp2=tmpb->getPointer();
7114 for(const int *i=connI;i!=connI+nbOfCells;i++)
7116 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7119 int pos=(int)std::distance(orderBg,where);
7121 tmp[std::distance(connI,i)]=pos;
7125 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7126 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7127 oss << " has a type " << cm.getRepr() << " not in input array of type !";
7128 throw INTERP_KERNEL::Exception(oss.str().c_str());
7131 nbPerType=tmpb.retn();
7136 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7138 * \return a new object containing the old to new correspondance.
7140 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7142 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7144 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7148 * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
7149 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7150 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7151 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7153 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7155 DataArrayInt *nbPerType=0;
7156 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7157 nbPerType->decrRef();
7158 return tmpa->buildPermArrPerLevel();
7162 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7163 * The number of cells remains unchanged after the call of this method.
7164 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7165 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7167 * \return the array giving the correspondance old to new.
7169 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7171 checkFullyDefined();
7173 const int *conn=_nodal_connec->getConstPointer();
7174 const int *connI=_nodal_connec_index->getConstPointer();
7175 int nbOfCells=getNumberOfCells();
7176 std::vector<INTERP_KERNEL::NormalizedCellType> types;
7177 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7178 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7180 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7181 types.push_back(curType);
7182 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7184 DataArrayInt *ret=DataArrayInt::New();
7185 ret->alloc(nbOfCells,1);
7186 int *retPtr=ret->getPointer();
7187 std::fill(retPtr,retPtr+nbOfCells,-1);
7189 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7191 for(const int *i=connI;i!=connI+nbOfCells;i++)
7192 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7193 retPtr[std::distance(connI,i)]=newCellId++;
7195 renumberCells(retPtr,false);
7200 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7201 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7202 * This method makes asumption that connectivity is correctly set before calling.
7204 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7206 checkConnectivityFullyDefined();
7207 const int *conn=_nodal_connec->getConstPointer();
7208 const int *connI=_nodal_connec_index->getConstPointer();
7209 int nbOfCells=getNumberOfCells();
7210 std::vector<MEDCouplingUMesh *> ret;
7211 for(const int *i=connI;i!=connI+nbOfCells;)
7213 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7214 int beginCellId=(int)std::distance(connI,i);
7215 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7216 int endCellId=(int)std::distance(connI,i);
7217 int sz=endCellId-beginCellId;
7218 int *cells=new int[sz];
7219 for(int j=0;j<sz;j++)
7220 cells[j]=beginCellId+j;
7221 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7229 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7230 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7231 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7233 * \return a newly allocated instance, that the caller must manage.
7234 * \throw If \a this contains more than one geometric type.
7235 * \throw If the nodal connectivity of \a this is not fully defined.
7236 * \throw If the internal data is not coherent.
7238 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7240 checkConnectivityFullyDefined();
7241 if(_types.size()!=1)
7242 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7243 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7244 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7245 ret->setCoords(getCoords());
7246 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7249 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7250 retC->setNodalConnectivity(c);
7254 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7256 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7257 DataArrayInt *c=0,*ci=0;
7258 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7260 retD->setNodalConnectivity(cs,cis);
7265 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7267 checkConnectivityFullyDefined();
7268 if(_types.size()!=1)
7269 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7270 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7271 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7274 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7275 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7276 throw INTERP_KERNEL::Exception(oss.str().c_str());
7278 int nbCells=getNumberOfCells();
7280 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7282 int *outPtr=connOut->getPointer();
7283 const int *conn=_nodal_connec->begin();
7284 const int *connI=_nodal_connec_index->begin();
7286 for(int i=0;i<nbCells;i++,connI++)
7288 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7289 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7292 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
7293 throw INTERP_KERNEL::Exception(oss.str().c_str());
7296 return connOut.retn();
7299 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7301 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7302 checkConnectivityFullyDefined();
7303 if(_types.size()!=1)
7304 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7305 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7307 throw INTERP_KERNEL::Exception(msg0);
7308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7309 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7310 int *cp(c->getPointer()),*cip(ci->getPointer());
7311 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7313 for(int i=0;i<nbCells;i++,cip++,incip++)
7315 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7316 int delta(stop-strt);
7319 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7320 cp=std::copy(incp+strt,incp+stop,cp);
7322 throw INTERP_KERNEL::Exception(msg0);
7325 throw INTERP_KERNEL::Exception(msg0);
7326 cip[1]=cip[0]+delta;
7328 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7332 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7333 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7334 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7335 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7336 * are not used here to avoid the build of big permutation array.
7338 * \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
7339 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7340 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7341 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7342 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7343 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7344 * \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
7345 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7347 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7348 DataArrayInt *&szOfCellGrpOfSameType,
7349 DataArrayInt *&idInMsOfCellGrpOfSameType)
7351 std::vector<const MEDCouplingUMesh *> ms2;
7352 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7355 (*it)->checkConnectivityFullyDefined();
7359 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7360 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7361 int meshDim=ms2[0]->getMeshDimension();
7362 std::vector<const MEDCouplingUMesh *> m1ssm;
7363 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7365 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7366 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7368 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7369 ret1->alloc(0,1); ret2->alloc(0,1);
7370 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7372 if(meshDim!=(*it)->getMeshDimension())
7373 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7374 if(refCoo!=(*it)->getCoords())
7375 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7376 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7377 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7378 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7379 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7381 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7382 m1ssmSingleAuto.push_back(singleCell);
7383 m1ssmSingle.push_back(singleCell);
7384 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7387 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7389 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7390 for(std::size_t i=0;i<m1ssm.size();i++)
7391 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7393 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7394 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7399 * This method returns a newly created DataArrayInt instance.
7400 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7402 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7404 checkFullyDefined();
7405 const int *conn=_nodal_connec->getConstPointer();
7406 const int *connIndex=_nodal_connec_index->getConstPointer();
7407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7408 for(const int *w=begin;w!=end;w++)
7409 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7410 ret->pushBackSilent(*w);
7415 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7416 * are in [0:getNumberOfCells())
7418 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7420 checkFullyDefined();
7421 const int *conn=_nodal_connec->getConstPointer();
7422 const int *connI=_nodal_connec_index->getConstPointer();
7423 int nbOfCells=getNumberOfCells();
7424 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7425 int *tmp=new int[nbOfCells];
7426 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7429 for(const int *i=connI;i!=connI+nbOfCells;i++)
7430 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7431 tmp[std::distance(connI,i)]=j++;
7433 DataArrayInt *ret=DataArrayInt::New();
7434 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7435 ret->copyStringInfoFrom(*da);
7436 int *retPtr=ret->getPointer();
7437 const int *daPtr=da->getConstPointer();
7438 int nbOfElems=da->getNbOfElems();
7439 for(int k=0;k<nbOfElems;k++)
7440 retPtr[k]=tmp[daPtr[k]];
7446 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7447 * This method \b works \b for mesh sorted by type.
7448 * cells whose ids is in 'idsPerGeoType' array.
7449 * This method conserves coords and name of mesh.
7451 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7453 std::vector<int> code=getDistributionOfTypes();
7454 std::size_t nOfTypesInThis=code.size()/3;
7455 int sz=0,szOfType=0;
7456 for(std::size_t i=0;i<nOfTypesInThis;i++)
7461 szOfType=code[3*i+1];
7463 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7464 if(*work<0 || *work>=szOfType)
7466 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7467 oss << ". It should be in [0," << szOfType << ") !";
7468 throw INTERP_KERNEL::Exception(oss.str().c_str());
7470 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7471 int *idsPtr=idsTokeep->getPointer();
7473 for(std::size_t i=0;i<nOfTypesInThis;i++)
7476 for(int j=0;j<code[3*i+1];j++)
7479 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7480 offset+=code[3*i+1];
7482 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7483 ret->copyTinyInfoFrom(this);
7488 * This method returns a vector of size 'this->getNumberOfCells()'.
7489 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7491 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7493 int ncell=getNumberOfCells();
7494 std::vector<bool> ret(ncell);
7495 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7496 const int *c=getNodalConnectivity()->getConstPointer();
7497 for(int i=0;i<ncell;i++)
7499 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7500 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7501 ret[i]=cm.isQuadratic();
7507 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7509 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7511 if(other->getType()!=UNSTRUCTURED)
7512 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7513 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7514 return MergeUMeshes(this,otherC);
7518 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7519 * computed by averaging coordinates of cell nodes, so this method is not a right
7520 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7521 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7522 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7523 * components. The caller is to delete this array using decrRef() as it is
7525 * \throw If the coordinates array is not set.
7526 * \throw If the nodal connectivity of cells is not defined.
7527 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7529 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7531 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7532 int spaceDim=getSpaceDimension();
7533 int nbOfCells=getNumberOfCells();
7534 ret->alloc(nbOfCells,spaceDim);
7535 ret->copyStringInfoFrom(*getCoords());
7536 double *ptToFill=ret->getPointer();
7537 const int *nodal=_nodal_connec->getConstPointer();
7538 const int *nodalI=_nodal_connec_index->getConstPointer();
7539 const double *coor=_coords->getConstPointer();
7540 for(int i=0;i<nbOfCells;i++)
7542 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7543 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7550 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7551 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7553 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7554 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7556 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7557 * \throw If \a this is not fully defined (coordinates and connectivity)
7558 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7560 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7562 checkFullyDefined();
7563 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7564 int spaceDim=getSpaceDimension();
7565 int nbOfCells=getNumberOfCells();
7566 int nbOfNodes=getNumberOfNodes();
7567 ret->alloc(nbOfCells,spaceDim);
7568 double *ptToFill=ret->getPointer();
7569 const int *nodal=_nodal_connec->getConstPointer();
7570 const int *nodalI=_nodal_connec_index->getConstPointer();
7571 const double *coor=_coords->getConstPointer();
7572 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7574 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7575 std::fill(ptToFill,ptToFill+spaceDim,0.);
7576 if(type!=INTERP_KERNEL::NORM_POLYHED)
7578 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7580 if(*conn>=0 && *conn<nbOfNodes)
7581 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7584 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7585 throw INTERP_KERNEL::Exception(oss.str().c_str());
7588 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7589 if(nbOfNodesInCell>0)
7590 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7593 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7594 throw INTERP_KERNEL::Exception(oss.str().c_str());
7599 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7601 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7603 if(*it>=0 && *it<nbOfNodes)
7604 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7607 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7608 throw INTERP_KERNEL::Exception(oss.str().c_str());
7612 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7615 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7616 throw INTERP_KERNEL::Exception(oss.str().c_str());
7624 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7625 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7626 * are specified via an array of cell ids.
7627 * \warning Validity of the specified cell ids is not checked!
7628 * Valid range is [ 0, \a this->getNumberOfCells() ).
7629 * \param [in] begin - an array of cell ids of interest.
7630 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7631 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7632 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7633 * caller is to delete this array using decrRef() as it is no more needed.
7634 * \throw If the coordinates array is not set.
7635 * \throw If the nodal connectivity of cells is not defined.
7637 * \if ENABLE_EXAMPLES
7638 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7639 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7642 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7644 DataArrayDouble *ret=DataArrayDouble::New();
7645 int spaceDim=getSpaceDimension();
7646 int nbOfTuple=(int)std::distance(begin,end);
7647 ret->alloc(nbOfTuple,spaceDim);
7648 double *ptToFill=ret->getPointer();
7649 double *tmp=new double[spaceDim];
7650 const int *nodal=_nodal_connec->getConstPointer();
7651 const int *nodalI=_nodal_connec_index->getConstPointer();
7652 const double *coor=_coords->getConstPointer();
7653 for(const int *w=begin;w!=end;w++)
7655 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7656 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7664 * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7665 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7666 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7667 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7668 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7670 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7671 * \throw If spaceDim!=3 or meshDim!=2.
7672 * \throw If connectivity of \a this is invalid.
7673 * \throw If connectivity of a cell in \a this points to an invalid node.
7675 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7677 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7678 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7679 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7680 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7681 ret->alloc(nbOfCells,4);
7682 double *retPtr(ret->getPointer());
7683 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7684 const double *coor(_coords->begin());
7685 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7687 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7688 if(nodalI[1]-nodalI[0]>=3)
7690 for(int j=0;j<3;j++)
7692 int nodeId(nodal[nodalI[0]+1+j]);
7693 if(nodeId>=0 && nodeId<nbOfNodes)
7694 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7697 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7698 throw INTERP_KERNEL::Exception(oss.str().c_str());
7704 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7705 throw INTERP_KERNEL::Exception(oss.str().c_str());
7707 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7708 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7714 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7717 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7720 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7721 da->checkAllocated();
7722 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7724 int nbOfTuples=da->getNumberOfTuples();
7725 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7726 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7727 c->alloc(2*nbOfTuples,1);
7728 cI->alloc(nbOfTuples+1,1);
7729 int *cp=c->getPointer();
7730 int *cip=cI->getPointer();
7732 for(int i=0;i<nbOfTuples;i++)
7734 *cp++=INTERP_KERNEL::NORM_POINT1;
7738 ret->setConnectivity(c,cI,true);
7742 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7743 * Cells and nodes of
7744 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7745 * \param [in] mesh1 - the first mesh.
7746 * \param [in] mesh2 - the second mesh.
7747 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7748 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7749 * is no more needed.
7750 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7751 * \throw If the coordinates array is not set in none of the meshes.
7752 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7753 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7755 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7757 std::vector<const MEDCouplingUMesh *> tmp(2);
7758 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7759 return MergeUMeshes(tmp);
7763 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7764 * Cells and nodes of
7765 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7766 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7767 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7768 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7769 * is no more needed.
7770 * \throw If \a a.size() == 0.
7771 * \throw If \a a[ *i* ] == NULL.
7772 * \throw If the coordinates array is not set in none of the meshes.
7773 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7774 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7776 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7778 std::size_t sz=a.size();
7780 return MergeUMeshesLL(a);
7781 for(std::size_t ii=0;ii<sz;ii++)
7784 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7785 throw INTERP_KERNEL::Exception(oss.str().c_str());
7787 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7788 std::vector< const MEDCouplingUMesh * > aa(sz);
7790 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7792 const MEDCouplingUMesh *cur=a[i];
7793 const DataArrayDouble *coo=cur->getCoords();
7795 spaceDim=coo->getNumberOfComponents();
7798 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7799 for(std::size_t i=0;i<sz;i++)
7801 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7804 return MergeUMeshesLL(aa);
7809 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7813 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7814 int meshDim=(*it)->getMeshDimension();
7815 int nbOfCells=(*it)->getNumberOfCells();
7816 int meshLgth=(*it++)->getMeshLength();
7817 for(;it!=a.end();it++)
7819 if(meshDim!=(*it)->getMeshDimension())
7820 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7821 nbOfCells+=(*it)->getNumberOfCells();
7822 meshLgth+=(*it)->getMeshLength();
7824 std::vector<const MEDCouplingPointSet *> aps(a.size());
7825 std::copy(a.begin(),a.end(),aps.begin());
7826 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7827 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7828 ret->setCoords(pts);
7829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7830 c->alloc(meshLgth,1);
7831 int *cPtr=c->getPointer();
7832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7833 cI->alloc(nbOfCells+1,1);
7834 int *cIPtr=cI->getPointer();
7838 for(it=a.begin();it!=a.end();it++)
7840 int curNbOfCell=(*it)->getNumberOfCells();
7841 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7842 const int *curC=(*it)->_nodal_connec->getConstPointer();
7843 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7844 for(int j=0;j<curNbOfCell;j++)
7846 const int *src=curC+curCI[j];
7848 for(;src!=curC+curCI[j+1];src++,cPtr++)
7856 offset+=curCI[curNbOfCell];
7857 offset2+=(*it)->getNumberOfNodes();
7860 ret->setConnectivity(c,cI,true);
7867 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7868 * dimension and sharing the node coordinates array.
7869 * All cells of the first mesh precede all cells of the second mesh
7870 * within the result mesh.
7871 * \param [in] mesh1 - the first mesh.
7872 * \param [in] mesh2 - the second mesh.
7873 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7874 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7875 * is no more needed.
7876 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7877 * \throw If the meshes do not share the node coordinates array.
7878 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7879 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7881 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7883 std::vector<const MEDCouplingUMesh *> tmp(2);
7884 tmp[0]=mesh1; tmp[1]=mesh2;
7885 return MergeUMeshesOnSameCoords(tmp);
7889 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7890 * dimension and sharing the node coordinates array.
7891 * All cells of the *i*-th mesh precede all cells of the
7892 * (*i*+1)-th mesh within the result mesh.
7893 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7894 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7895 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7896 * is no more needed.
7897 * \throw If \a a.size() == 0.
7898 * \throw If \a a[ *i* ] == NULL.
7899 * \throw If the meshes do not share the node coordinates array.
7900 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7901 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7903 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7906 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7907 for(std::size_t ii=0;ii<meshes.size();ii++)
7910 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7911 throw INTERP_KERNEL::Exception(oss.str().c_str());
7913 const DataArrayDouble *coords=meshes.front()->getCoords();
7914 int meshDim=meshes.front()->getMeshDimension();
7915 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7917 int meshIndexLgth=0;
7918 for(;iter!=meshes.end();iter++)
7920 if(coords!=(*iter)->getCoords())
7921 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7922 if(meshDim!=(*iter)->getMeshDimension())
7923 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7924 meshLgth+=(*iter)->getMeshLength();
7925 meshIndexLgth+=(*iter)->getNumberOfCells();
7927 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7928 nodal->alloc(meshLgth,1);
7929 int *nodalPtr=nodal->getPointer();
7930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7931 nodalIndex->alloc(meshIndexLgth+1,1);
7932 int *nodalIndexPtr=nodalIndex->getPointer();
7934 for(iter=meshes.begin();iter!=meshes.end();iter++)
7936 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7937 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7938 int nbOfCells=(*iter)->getNumberOfCells();
7939 int meshLgth2=(*iter)->getMeshLength();
7940 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7941 if(iter!=meshes.begin())
7942 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7944 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7947 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7948 ret->setName("merge");
7949 ret->setMeshDimension(meshDim);
7950 ret->setConnectivity(nodal,nodalIndex,true);
7951 ret->setCoords(coords);
7956 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7957 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7958 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7959 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7960 * New" mode are returned for each input mesh.
7961 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7962 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7963 * valid values [0,1,2], see zipConnectivityTraducer().
7964 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7965 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7966 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7968 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7969 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7970 * is no more needed.
7971 * \throw If \a meshes.size() == 0.
7972 * \throw If \a meshes[ *i* ] == NULL.
7973 * \throw If the meshes do not share the node coordinates array.
7974 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7975 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7976 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7977 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7979 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7981 //All checks are delegated to MergeUMeshesOnSameCoords
7982 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7984 corr.resize(meshes.size());
7985 std::size_t nbOfMeshes=meshes.size();
7987 const int *o2nPtr=o2n->getConstPointer();
7988 for(std::size_t i=0;i<nbOfMeshes;i++)
7990 DataArrayInt *tmp=DataArrayInt::New();
7991 int curNbOfCells=meshes[i]->getNumberOfCells();
7992 tmp->alloc(curNbOfCells,1);
7993 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7994 offset+=curNbOfCells;
7995 tmp->setName(meshes[i]->getName());
8002 * Makes all given meshes share the nodal connectivity array. The common connectivity
8003 * array is created by concatenating the connectivity arrays of all given meshes. All
8004 * the given meshes must be of the same space dimension but dimension of cells **can
8005 * differ**. This method is particulary useful in MEDLoader context to build a \ref
8006 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8007 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8008 * \param [in,out] meshes - a vector of meshes to update.
8009 * \throw If any of \a meshes is NULL.
8010 * \throw If the coordinates array is not set in any of \a meshes.
8011 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8012 * \throw If \a meshes are of different space dimension.
8014 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8016 std::size_t sz=meshes.size();
8019 std::vector< const DataArrayDouble * > coords(meshes.size());
8020 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8021 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8025 (*it)->checkConnectivityFullyDefined();
8026 const DataArrayDouble *coo=(*it)->getCoords();
8031 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8032 oss << " has no coordinate array defined !";
8033 throw INTERP_KERNEL::Exception(oss.str().c_str());
8038 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8039 oss << " is null !";
8040 throw INTERP_KERNEL::Exception(oss.str().c_str());
8043 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8044 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8045 int offset=(*it)->getNumberOfNodes();
8046 (*it++)->setCoords(res);
8047 for(;it!=meshes.end();it++)
8049 int oldNumberOfNodes=(*it)->getNumberOfNodes();
8050 (*it)->setCoords(res);
8051 (*it)->shiftNodeNumbersInConn(offset);
8052 offset+=oldNumberOfNodes;
8057 * Merges nodes coincident with a given precision within all given meshes that share
8058 * the nodal connectivity array. The given meshes **can be of different** mesh
8059 * dimension. This method is particulary useful in MEDLoader context to build a \ref
8060 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8061 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8062 * \param [in,out] meshes - a vector of meshes to update.
8063 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8064 * \throw If any of \a meshes is NULL.
8065 * \throw If the \a meshes do not share the same node coordinates array.
8066 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8068 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8072 std::set<const DataArrayDouble *> s;
8073 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8076 s.insert((*it)->getCoords());
8079 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 !";
8080 throw INTERP_KERNEL::Exception(oss.str().c_str());
8085 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 !";
8086 throw INTERP_KERNEL::Exception(oss.str().c_str());
8088 const DataArrayDouble *coo=*(s.begin());
8092 DataArrayInt *comm,*commI;
8093 coo->findCommonTuples(eps,-1,comm,commI);
8094 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8095 int oldNbOfNodes=coo->getNumberOfTuples();
8097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8098 if(oldNbOfNodes==newNbOfNodes)
8100 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8101 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8103 (*it)->renumberNodesInConn(o2n->getConstPointer());
8104 (*it)->setCoords(newCoords);
8109 * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
8110 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8111 * \param isQuad specifies the policy of connectivity.
8112 * @ret in/out parameter in which the result will be append
8114 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8116 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8117 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8118 ret.push_back(cm.getExtrudedType());
8119 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8122 case INTERP_KERNEL::NORM_POINT1:
8124 ret.push_back(connBg[1]);
8125 ret.push_back(connBg[1]+nbOfNodesPerLev);
8128 case INTERP_KERNEL::NORM_SEG2:
8130 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8131 ret.insert(ret.end(),conn,conn+4);
8134 case INTERP_KERNEL::NORM_SEG3:
8136 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8137 ret.insert(ret.end(),conn,conn+8);
8140 case INTERP_KERNEL::NORM_QUAD4:
8142 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8143 ret.insert(ret.end(),conn,conn+8);
8146 case INTERP_KERNEL::NORM_TRI3:
8148 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8149 ret.insert(ret.end(),conn,conn+6);
8152 case INTERP_KERNEL::NORM_TRI6:
8154 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,
8155 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8156 ret.insert(ret.end(),conn,conn+15);
8159 case INTERP_KERNEL::NORM_QUAD8:
8162 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8163 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8164 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8166 ret.insert(ret.end(),conn,conn+20);
8169 case INTERP_KERNEL::NORM_POLYGON:
8171 std::back_insert_iterator< std::vector<int> > ii(ret);
8172 std::copy(connBg+1,connEnd,ii);
8174 std::reverse_iterator<const int *> rConnBg(connEnd);
8175 std::reverse_iterator<const int *> rConnEnd(connBg+1);
8176 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8177 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8178 for(std::size_t i=0;i<nbOfRadFaces;i++)
8181 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8182 std::copy(conn,conn+4,ii);
8187 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8192 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8194 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8197 double v[3]={0.,0.,0.};
8198 std::size_t sz=std::distance(begin,end);
8203 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];
8204 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8205 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8207 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8209 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8210 // SEG3 forming a circle):
8211 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8213 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8214 for(std::size_t j=0;j<sz;j++)
8216 if (j%2) // current point i is quadratic, next point i+1 is standard
8219 ip1 = (j+1)%sz; // ip1 = "i+1"
8221 else // current point i is standard, next point i+1 is quadratic
8226 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8227 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8228 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8230 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8236 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8238 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8240 std::vector<std::pair<int,int> > edges;
8241 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8242 const int *bgFace=begin;
8243 for(std::size_t i=0;i<nbOfFaces;i++)
8245 const int *endFace=std::find(bgFace+1,end,-1);
8246 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8247 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8249 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8250 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8252 edges.push_back(p1);
8256 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8260 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8262 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8264 double vec0[3],vec1[3];
8265 std::size_t sz=std::distance(begin,end);
8267 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8268 int nbOfNodes=(int)sz/2;
8269 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8270 const double *pt0=coords+3*begin[0];
8271 const double *pt1=coords+3*begin[nbOfNodes];
8272 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8273 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8276 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8278 std::size_t sz=std::distance(begin,end);
8279 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8280 std::size_t nbOfNodes(sz/2);
8281 std::copy(begin,end,(int *)tmp);
8282 for(std::size_t j=1;j<nbOfNodes;j++)
8284 begin[j]=tmp[nbOfNodes-j];
8285 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8289 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8291 std::size_t sz=std::distance(begin,end);
8293 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8294 double vec0[3],vec1[3];
8295 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8296 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];
8297 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;
8300 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8302 std::size_t sz=std::distance(begin,end);
8304 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8306 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8307 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8308 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8312 * 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 )
8313 * 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
8316 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8317 * \param [in] coords the coordinates with nb of components exactly equal to 3
8318 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8319 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8320 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8322 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8324 int nbFaces=std::count(begin+1,end,-1)+1;
8325 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8326 double *vPtr=v->getPointer();
8327 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8328 double *pPtr=p->getPointer();
8329 const int *stFaceConn=begin+1;
8330 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8332 const int *endFaceConn=std::find(stFaceConn,end,-1);
8333 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8334 stFaceConn=endFaceConn+1;
8336 pPtr=p->getPointer(); vPtr=v->getPointer();
8337 DataArrayInt *comm1=0,*commI1=0;
8338 v->findCommonTuples(eps,-1,comm1,commI1);
8339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8340 const int *comm1Ptr=comm1->getConstPointer();
8341 const int *commI1Ptr=commI1->getConstPointer();
8342 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8343 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8345 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8346 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8347 mm->finishInsertingCells();
8349 for(int i=0;i<nbOfGrps1;i++)
8351 int vecId=comm1Ptr[commI1Ptr[i]];
8352 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8353 DataArrayInt *comm2=0,*commI2=0;
8354 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8356 const int *comm2Ptr=comm2->getConstPointer();
8357 const int *commI2Ptr=commI2->getConstPointer();
8358 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8359 for(int j=0;j<nbOfGrps2;j++)
8361 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8363 res->insertAtTheEnd(begin,end);
8364 res->pushBackSilent(-1);
8368 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8370 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8371 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8372 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8373 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8374 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8375 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8376 const int *idsNodePtr=idsNode->getConstPointer();
8377 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];
8378 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8379 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8380 if(std::abs(norm)>eps)
8382 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8383 mm3->rotate(center,vec,angle);
8385 mm3->changeSpaceDimension(2);
8386 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8387 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8388 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8389 int nbOfCells=mm4->getNumberOfCells();
8390 for(int k=0;k<nbOfCells;k++)
8393 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8394 res->pushBackSilent(idsNodePtr[*work]);
8395 res->pushBackSilent(-1);
8400 res->popBackSilent();
8404 * 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
8405 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8407 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8408 * \param [in] coords coordinates expected to have 3 components.
8409 * \param [in] begin start of the nodal connectivity of the face.
8410 * \param [in] end end of the nodal connectivity (excluded) of the face.
8411 * \param [out] v the normalized vector of size 3
8412 * \param [out] p the pos of plane
8414 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8416 std::size_t nbPoints=std::distance(begin,end);
8418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8419 double vec[3]={0.,0.,0.};
8421 bool refFound=false;
8422 for(;j<nbPoints-1 && !refFound;j++)
8424 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8425 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8426 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8427 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8431 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8434 for(std::size_t i=j;i<nbPoints-1;i++)
8437 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8438 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8439 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8440 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8443 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8444 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];
8445 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8448 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8449 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8453 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8457 * This method tries to obtain a well oriented polyhedron.
8458 * If the algorithm fails, an exception will be thrown.
8460 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8462 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8463 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8464 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8466 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8467 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8468 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8470 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8473 std::size_t smthChanged=0;
8474 for(std::size_t i=0;i<nbOfFaces;i++)
8476 endFace=std::find(bgFace+1,end,-1);
8477 nbOfEdgesInFace=std::distance(bgFace,endFace);
8481 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8483 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8484 std::pair<int,int> p2(p1.second,p1.first);
8485 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8486 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8487 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8492 std::reverse(bgFace+1,endFace);
8493 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8495 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8496 std::pair<int,int> p2(p1.second,p1.first);
8497 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8498 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8499 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8500 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8501 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8502 if(it!=edgesOK.end())
8505 edgesFinished.push_back(p1);
8508 edgesOK.push_back(p1);
8515 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8517 if(!edgesOK.empty())
8518 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8519 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8520 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8522 for(std::size_t i=0;i<nbOfFaces;i++)
8524 endFace=std::find(bgFace+1,end,-1);
8525 std::reverse(bgFace+1,endFace);
8531 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8533 int nbOfNodesExpected(skin->getNumberOfNodes());
8534 const int *n2oPtr(n2o->getConstPointer());
8535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8536 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8537 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8538 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8539 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8540 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8541 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8542 if(nbOfNodesExpected<1)
8544 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8545 *work++=n2oPtr[prevNode];
8546 for(int i=1;i<nbOfNodesExpected;i++)
8548 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8550 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8551 conn.erase(prevNode);
8554 int curNode(*(conn.begin()));
8555 *work++=n2oPtr[curNode];
8556 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8557 shar.erase(prevCell);
8560 prevCell=*(shar.begin());
8564 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8570 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8575 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8577 int nbOfNodesExpected(skin->getNumberOfNodes());
8578 int nbOfTurn(nbOfNodesExpected/2);
8579 const int *n2oPtr(n2o->getConstPointer());
8580 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8581 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8582 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8583 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8584 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8585 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8586 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8587 if(nbOfNodesExpected<1)
8589 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8590 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8591 for(int i=1;i<nbOfTurn;i++)
8593 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8595 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8596 conn.erase(prevNode);
8599 int curNode(*(conn.begin()));
8600 *work=n2oPtr[curNode];
8601 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8602 shar.erase(prevCell);
8605 int curCell(*(shar.begin()));
8606 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8615 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8618 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8624 * This method makes the assumption spacedimension == meshdimension == 2.
8625 * This method works only for linear cells.
8627 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8629 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8631 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8632 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8633 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8634 int oldNbOfNodes(skin->getNumberOfNodes());
8635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8636 int nbOfNodesExpected(skin->getNumberOfNodes());
8637 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8638 int nbCells(skin->getNumberOfCells());
8639 if(nbCells==nbOfNodesExpected)
8640 return buildUnionOf2DMeshLinear(skin,n2o);
8641 else if(2*nbCells==nbOfNodesExpected)
8642 return buildUnionOf2DMeshQuadratic(skin,n2o);
8644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8648 * This method makes the assumption spacedimension == meshdimension == 3.
8649 * This method works only for linear cells.
8651 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8653 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8655 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8657 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8658 const int *conn=m->getNodalConnectivity()->getConstPointer();
8659 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8660 int nbOfCells=m->getNumberOfCells();
8661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8662 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8665 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8666 for(int i=1;i<nbOfCells;i++)
8669 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8675 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8676 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8678 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8682 for(int i=0;i<nbOfNodesInCell;i++)
8683 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8684 else if(spaceDim==2)
8686 for(int i=0;i<nbOfNodesInCell;i++)
8688 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8693 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8696 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8698 int nbOfCells=getNumberOfCells();
8700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8701 static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4};
8702 ofs << " <" << getVTKDataSetType() << ">\n";
8703 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8704 ofs << " <PointData>\n" << pointData << std::endl;
8705 ofs << " </PointData>\n";
8706 ofs << " <CellData>\n" << cellData << std::endl;
8707 ofs << " </CellData>\n";
8708 ofs << " <Points>\n";
8709 if(getSpaceDimension()==3)
8710 _coords->writeVTK(ofs,8,"Points",byteData);
8713 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8714 coo->writeVTK(ofs,8,"Points",byteData);
8716 ofs << " </Points>\n";
8717 ofs << " <Cells>\n";
8718 const int *cPtr=_nodal_connec->getConstPointer();
8719 const int *cIPtr=_nodal_connec_index->getConstPointer();
8720 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8722 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8724 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8725 int szFaceOffsets=0,szConn=0;
8726 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8729 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8732 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8733 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8737 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8738 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8739 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8740 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8741 w4=std::copy(c.begin(),c.end(),w4);
8744 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8745 types->writeVTK(ofs,8,"UInt8","types",byteData);
8746 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8747 if(szFaceOffsets!=0)
8748 {//presence of Polyhedra
8749 connectivity->reAlloc(szConn);
8750 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8752 w1=faces->getPointer();
8753 for(int i=0;i<nbOfCells;i++)
8754 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8756 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8758 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8759 for(int j=0;j<nbFaces;j++)
8761 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8762 *w1++=(int)std::distance(w6,w5);
8763 w1=std::copy(w6,w5,w1);
8767 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8769 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8770 ofs << " </Cells>\n";
8771 ofs << " </Piece>\n";
8772 ofs << " </" << getVTKDataSetType() << ">\n";
8775 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8777 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8779 { stream << " Not set !"; return ; }
8780 stream << " Mesh dimension : " << _mesh_dim << ".";
8784 { stream << " No coordinates set !"; return ; }
8785 if(!_coords->isAllocated())
8786 { stream << " Coordinates set but not allocated !"; return ; }
8787 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8788 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8789 if(!_nodal_connec_index)
8790 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8791 if(!_nodal_connec_index->isAllocated())
8792 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8793 int lgth=_nodal_connec_index->getNumberOfTuples();
8794 int cpt=_nodal_connec_index->getNumberOfComponents();
8795 if(cpt!=1 || lgth<1)
8797 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8800 std::string MEDCouplingUMesh::getVTKDataSetType() const
8802 return std::string("UnstructuredGrid");
8805 std::string MEDCouplingUMesh::getVTKFileExtension() const
8807 return std::string("vtu");
8811 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8812 * returns a result mesh constituted by polygons.
8813 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8814 * all nodes from m2.
8815 * The meshes should be in 2D space. In
8816 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8818 * \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8819 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8820 * \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
8821 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8822 * \param [in] eps - precision used to detect coincident mesh entities.
8823 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8824 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8825 * this array using decrRef() as it is no more needed.
8826 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8827 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8828 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8829 * any cell of \a m2. The caller is to delete this array using decrRef() as
8830 * it is no more needed.
8831 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8832 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8833 * is no more needed.
8834 * \throw If the coordinates array is not set in any of the meshes.
8835 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8836 * \throw If any of the meshes is not a 2D mesh in 2D space.
8838 * \sa conformize2D, mergeNodes
8840 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8841 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8844 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8845 m1->checkFullyDefined();
8846 m2->checkFullyDefined();
8847 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8850 // Step 1: compute all edge intersections (new nodes)
8851 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8852 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8853 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8854 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8855 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8856 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8857 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8858 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8860 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8862 // Step 2: re-order newly created nodes according to the ordering found in m2
8863 std::vector< std::vector<int> > intersectEdge2;
8864 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8865 subDiv2.clear(); dd5=0; dd6=0;
8868 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8869 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8870 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8871 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8873 // Step 4: Prepare final result:
8874 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8875 addCooDa->alloc((int)(addCoo.size())/2,2);
8876 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8877 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8878 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8879 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8880 std::vector<const DataArrayDouble *> coordss(4);
8881 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8882 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8883 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8885 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8888 ret->setConnectivity(conn,connI,true);
8889 ret->setCoords(coo);
8890 cellNb1=c1.retn(); cellNb2=c2.retn();
8896 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8898 if(candidates.empty())
8900 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8902 const std::vector<int>& pool(intersectEdge1[*it]);
8903 int tmp[2]; tmp[0]=start; tmp[1]=stop;
8904 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8909 tmp[0]=stop; tmp[1]=start;
8910 if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8919 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo, const std::map<int,int>& mergedNodes, const std::vector< std::vector<int> >& colinear2, const std::vector< std::vector<int> >& intersectEdge1,
8920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8922 idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8923 idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8924 int nCells(mesh1D->getNumberOfCells());
8925 if(nCells!=(int)intersectEdge2.size())
8926 throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8927 const DataArrayDouble *coo2(mesh1D->getCoords());
8928 const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8929 const double *coo2Ptr(coo2->begin());
8930 int offset1(coords1->getNumberOfTuples());
8931 int offset2(offset1+coo2->getNumberOfTuples());
8932 int offset3(offset2+addCoo.size()/2);
8933 std::vector<double> addCooQuad;
8934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8935 int tmp[4],cicnt(0),kk(0);
8936 for(int i=0;i<nCells;i++)
8938 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8939 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8940 const std::vector<int>& subEdges(intersectEdge2[i]);
8941 int nbSubEdge(subEdges.size()/2);
8942 for(int j=0;j<nbSubEdge;j++,kk++)
8944 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
8945 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8946 INTERP_KERNEL::Edge *e2Ptr(e2);
8947 std::map<int,int>::const_iterator itm;
8948 if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8950 tmp[0]=INTERP_KERNEL::NORM_SEG3;
8951 itm=mergedNodes.find(subEdges[2*j]);
8952 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8953 itm=mergedNodes.find(subEdges[2*j+1]);
8954 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8955 tmp[3]=offset3+(int)addCooQuad.size()/2;
8957 e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8959 cOut->insertAtTheEnd(tmp,tmp+4);
8960 ciOut->pushBackSilent(cicnt);
8964 tmp[0]=INTERP_KERNEL::NORM_SEG2;
8965 itm=mergedNodes.find(subEdges[2*j]);
8966 tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8967 itm=mergedNodes.find(subEdges[2*j+1]);
8968 tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8970 cOut->insertAtTheEnd(tmp,tmp+3);
8971 ciOut->pushBackSilent(cicnt);
8974 if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8976 idsInRetColinear->pushBackSilent(kk);
8977 idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8982 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8983 ret->setConnectivity(cOut,ciOut,true);
8984 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8985 arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8986 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8987 std::vector<const DataArrayDouble *> coordss(4);
8988 coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8989 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8990 ret->setCoords(arr);
8994 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8996 std::vector<int> allEdges;
8997 for(const int *it2(descBg);it2!=descEnd;it2++)
8999 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9001 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9003 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9005 std::size_t nb(allEdges.size());
9007 throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9008 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9009 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9010 ret->setCoords(coords);
9011 ret->allocateCells(1);
9012 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9013 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9014 connOut[kk]=allEdges[2*kk];
9015 ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9019 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9021 const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9022 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9024 unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9025 if(sz!=std::distance(descBg,descEnd))
9026 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9027 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9028 std::vector<int> allEdges,centers;
9029 const double *coordsPtr(coords->begin());
9030 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9031 int offset(coords->getNumberOfTuples());
9032 for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9034 INTERP_KERNEL::NormalizedCellType typeOfSon;
9035 cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9036 const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9038 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9040 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9042 centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9044 {//the current edge has been subsplit -> create corresponding centers.
9045 std::size_t nbOfCentersToAppend(edge1.size()/2);
9046 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9047 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9048 std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9049 for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9052 const double *aa(coordsPtr+2*(*it3++));
9053 const double *bb(coordsPtr+2*(*it3++));
9054 ee->getMiddleOfPoints(aa,bb,tmpp);
9055 addCoo->insertAtTheEnd(tmpp,tmpp+2);
9056 centers.push_back(offset+k);
9060 std::size_t nb(allEdges.size());
9062 throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9063 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9064 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9066 ret->setCoords(coords);
9069 addCoo->rearrange(2);
9070 addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9071 ret->setCoords(addCoo);
9073 ret->allocateCells(1);
9074 std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9075 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9076 connOut[kk]=allEdges[2*kk];
9077 connOut.insert(connOut.end(),centers.begin(),centers.end());
9078 ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9083 * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9086 * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9088 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9090 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9091 if(!cm.isQuadratic())
9092 return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9094 return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9097 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9100 for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9102 const INTERP_KERNEL::Edge *ee(*it);
9103 if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9107 mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9110 const double *coo(mesh2D->getCoords()->begin());
9111 std::size_t sz(conn.size());
9112 std::vector<double> addCoo;
9113 std::vector<int> conn2(conn);
9114 int offset(mesh2D->getNumberOfNodes());
9115 for(std::size_t i=0;i<sz;i++)
9118 edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9119 addCoo.insert(addCoo.end(),tmp,tmp+2);
9120 conn2.push_back(offset+(int)i);
9122 mesh2D->getCoords()->rearrange(1);
9123 mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9124 mesh2D->getCoords()->rearrange(2);
9125 mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9130 * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9132 * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9133 * a set of edges defined in \a splitMesh1D.
9135 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9136 std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9138 std::size_t nb(edge1Bis.size()/2);
9139 std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9140 int iEnd(splitMesh1D->getNumberOfCells());
9142 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9144 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9145 for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9146 for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9149 {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9150 out0.resize(1); out1.resize(1);
9151 std::vector<int>& connOut(out0[0]);
9152 connOut.resize(nbOfEdgesOf2DCellSplit);
9153 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9154 edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9155 for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9157 connOut[kk]=edge1Bis[2*kk];
9158 edgesPtr[kk]=edge1BisPtr[2*kk];
9163 // [i,iEnd[ contains the
9164 out0.resize(2); out1.resize(2);
9165 std::vector<int>& connOutLeft(out0[0]);
9166 std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9167 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9168 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9169 for(std::size_t k=ii;k<jj+1;k++)
9170 { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9171 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9172 for(int ik=0;ik<iEnd;ik++)
9174 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9175 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9178 for(int ik=iEnd-1;ik>=0;ik--)
9179 connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9180 for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9181 { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9182 eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9183 for(int ik=0;ik<iEnd;ik++)
9184 connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9185 eright.insert(eright.end(),ees.begin(),ees.end());
9197 CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9199 std::vector<int> _edges;
9200 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9203 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9205 std::size_t nbe(edges.size());
9206 std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9207 for(std::size_t i=0;i<nbe;i++)
9209 edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9210 edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9212 _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9213 std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9214 std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9220 EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9221 EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9222 bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9223 void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9224 void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9228 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9229 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9234 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9236 const MEDCouplingUMesh *mesh(_mesh);
9242 { _left++; _right++; return ; }
9245 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9246 if((isLeft && isRight) || (!isLeft && !isRight))
9247 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9258 bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9259 if((isLeft && isRight) || (!isLeft && !isRight))
9260 throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9275 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9277 const MEDCouplingUMesh *mesh(_mesh);
9280 neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9283 {// not fully splitting cell case
9284 if(mesh2D->getNumberOfCells()==1)
9285 {//little optimization. 1 cell no need to find in which cell mesh is !
9286 neighbors[0]=offset; neighbors[1]=offset;
9291 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9292 int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9294 throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9295 neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9300 class VectorOfCellInfo
9303 VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9304 std::size_t size() const { return _pool.size(); }
9305 int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9306 void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9307 const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9308 const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9309 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9310 void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9312 int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9313 void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9314 const CellInfo& get(int pos) const;
9315 CellInfo& get(int pos);
9317 std::vector<CellInfo> _pool;
9318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9319 std::vector<EdgeInfo> _edge_info;
9322 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9324 _pool[0]._edges=edges;
9325 _pool[0]._edges_ptr=edgesPtr;
9328 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9331 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9334 const MEDCouplingUMesh *zeMesh(_ze_mesh);
9336 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9337 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9338 return zeMesh->getCellContainingPoint(barys->begin(),eps);
9341 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9343 get(pos);//to check pos
9344 bool isFast(pos==0 && _pool.size()==1);
9345 std::size_t sz(edges.size());
9346 // dealing with edges
9348 _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9350 _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9352 std::vector<CellInfo> pool(_pool.size()-1+sz);
9353 for(int i=0;i<pos;i++)
9355 for(std::size_t j=0;j<sz;j++)
9356 pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9357 for(int i=pos+1;i<(int)_pool.size();i++)
9358 pool[i+sz-1]=_pool[i];
9362 updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9370 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9373 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9377 if(pos<_ze_mesh->getNumberOfCells()-1)
9379 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9382 std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9383 for(std::size_t j=0;j<ms2.size();j++)
9385 _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9388 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9390 _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9393 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9396 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9398 for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9400 if((*it).isInMyRange(pos))
9403 throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9406 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9408 get(pos);//to check;
9409 if(_edge_info.empty())
9411 std::size_t sz(_edge_info.size()-1);
9412 for(std::size_t i=0;i<sz;i++)
9413 _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9416 const CellInfo& VectorOfCellInfo::get(int pos) const
9418 if(pos<0 || pos>=(int)_pool.size())
9419 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9423 CellInfo& VectorOfCellInfo::get(int pos)
9425 if(pos<0 || pos>=(int)_pool.size())
9426 throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9432 * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9433 * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9435 * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9437 * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9439 * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9441 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9442 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9444 int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9445 if(nbCellsInSplitMesh1D==0)
9446 throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9447 const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9448 std::size_t nb(allEdges.size()),jj;
9450 throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9451 std::vector<int> edge1Bis(nb*2);
9452 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9453 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9454 std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9455 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9456 std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9458 idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9459 int *idsLeftRightPtr(idsLeftRight->getPointer());
9460 VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9461 for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9462 {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9464 for(;iEnd<nbCellsInSplitMesh1D;)
9466 for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9472 if(iEnd<nbCellsInSplitMesh1D)
9475 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9476 int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9478 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9479 retTmp->setCoords(splitMesh1D->getCoords());
9480 retTmp->allocateCells();
9482 std::vector< std::vector<int> > out0;
9483 std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9485 BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9486 for(std::size_t cnt=0;cnt<out0.size();cnt++)
9487 AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9488 pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9492 for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9493 pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9494 return pool.getZeMesh().retn();
9497 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9498 const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9499 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9501 const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9503 std::vector<int> allEdges;
9504 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9505 for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9507 int edgeId(std::abs(*it)-1);
9508 std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9509 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9510 const std::vector<int>& edge1(intersectEdge1[edgeId]);
9512 allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9514 allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9515 std::size_t sz(edge1.size());
9516 for(std::size_t cnt=0;cnt<sz;cnt++)
9517 allEdgesPtr.push_back(ee);
9520 return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9523 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9525 if(!typ1.isQuadratic() && !typ2.isQuadratic())
9526 {//easy case comparison not
9527 return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9529 else if(typ1.isQuadratic() && typ2.isQuadratic())
9531 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9534 if(conn1[2]==conn2[2])
9536 const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9537 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9541 {//only one is quadratic
9542 bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9545 const double *a(0),*bb(0),*be(0);
9546 if(typ1.isQuadratic())
9548 a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9552 a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9554 double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9555 double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9561 * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9562 * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9564 * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9566 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9568 if(candidatesIn2DEnd==candidatesIn2DBg)
9569 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9570 const double *coo(mesh2DSplit->getCoords()->begin());
9571 if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9572 return *candidatesIn2DBg;
9573 int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9574 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9575 if(cellIdInMesh1DSplitRelative<0)
9576 cur1D->changeOrientationOfCells();
9577 const int *c1D(cur1D->getNodalConnectivity()->begin());
9578 const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9579 for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9581 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9582 const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9583 const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9584 unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9585 INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9586 for(unsigned it2=0;it2<sz;it2++)
9588 INTERP_KERNEL::NormalizedCellType typeOfSon;
9589 cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9590 const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9591 if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9595 throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9601 * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9602 * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9603 * and finaly, in case of quadratic polygon the centers of edges new nodes.
9604 * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9606 * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9607 * must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9608 * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9609 * you can invoke orderConsecutiveCells1D on \a mesh1D.
9610 * \param [in] eps - precision used to perform intersections and localization operations.
9611 * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9612 * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9613 * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9614 * So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
9615 * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9616 * and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9617 * So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
9619 * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9621 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9623 if(!mesh2D || !mesh1D)
9624 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9625 mesh2D->checkFullyDefined();
9626 mesh1D->checkFullyDefined();
9627 const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9628 if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9629 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9630 // Step 1: compute all edge intersections (new nodes)
9631 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9632 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
9633 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9634 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9636 // Build desc connectivity
9637 DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9639 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9640 std::map<int,int> mergedNodes;
9641 Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9642 // use mergeNodes to fix intersectEdge1
9643 for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9645 std::size_t n((*it0).size()/2);
9646 int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9647 std::map<int,int>::const_iterator it1;
9648 it1=mergedNodes.find(eltStart);
9649 if(it1!=mergedNodes.end())
9650 (*it0)[0]=(*it1).second;
9651 it1=mergedNodes.find(eltEnd);
9652 if(it1!=mergedNodes.end())
9653 (*it0)[2*n-1]=(*it1).second;
9656 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9657 addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9658 // Step 2: re-order newly created nodes according to the ordering found in m2
9659 std::vector< std::vector<int> > intersectEdge2;
9660 BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9662 // Step 3: compute splitMesh1D
9663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9664 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9665 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9666 idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9669 // deal with cells in mesh2D that are not cut but only some of their edges are
9670 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9671 idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9672 idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9673 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9674 if(!idsInDesc2DToBeRefined->empty())
9676 DataArrayInt *out0(0),*outi0(0);
9677 MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9678 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9680 out0s=out0s->buildUnique();
9684 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9685 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9687 mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9690 if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9691 throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9692 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9693 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9694 if((DataArrayInt *)out0s)
9695 untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9696 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9697 // OK all is ready to insert in ret2 mesh
9698 if(!untouchedCells->empty())
9699 {// the most easy part, cells in mesh2D not impacted at all
9700 outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9701 outMesh2DSplit.back()->setCoords(ret1->getCoords());
9702 ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9704 if((DataArrayInt *)out0s)
9705 {// here dealing with cells in out0s but not in cellsToBeModified
9706 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9707 const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9708 for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9710 outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9711 ret1->setCoords(outMesh2DSplit.back()->getCoords());
9713 int offset(ret2->getNumberOfTuples());
9714 ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9715 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9716 partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9717 int kk(0),*ret3ptr(partOfRet3->getPointer());
9718 for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9720 int faceId(std::abs(*it)-1);
9721 for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9723 int tmp(fewModifiedCells->locateValue(*it2));
9726 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9727 ret3ptr[2*kk]=tmp+offset;
9728 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9729 ret3ptr[2*kk+1]=tmp+offset;
9732 {//the current edge is shared by a 2D cell that will be split just after
9733 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9734 ret3ptr[2*kk]=-(*it2+1);
9735 if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9736 ret3ptr[2*kk+1]=-(*it2+1);
9740 m1Desc->setCoords(ret1->getCoords());
9741 ret1NonCol->setCoords(ret1->getCoords());
9742 ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9743 if(!outMesh2DSplit.empty())
9745 DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9746 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9747 (*itt)->setCoords(da);
9750 cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9751 for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9754 idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9756 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9757 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9758 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9759 ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9760 outMesh2DSplit.push_back(splitOfOneCell);
9761 for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9762 ret2->pushBackSilent(*it);
9765 std::size_t nbOfMeshes(outMesh2DSplit.size());
9766 std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9767 for(std::size_t i=0;i<nbOfMeshes;i++)
9768 tmp[i]=outMesh2DSplit[i];
9770 ret1->getCoords()->setInfoOnComponents(compNames);
9771 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9772 // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9775 for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9777 int old2DCellId(-ret3->getIJ(*it,0)-1);
9778 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9779 ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9781 ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9784 splitMesh1D=ret1.retn();
9785 splitMesh2D=ret2D.retn();
9786 cellIdInMesh2D=ret2.retn();
9787 cellIdInMesh1D=ret3.retn();
9791 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9792 * (newly created) nodes corresponding to the edge intersections.
9794 * @param[out] cr, crI connectivity of the resulting mesh
9795 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9796 * TODO: describe input parameters
9798 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9799 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9800 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9801 const std::vector<double>& addCoords,
9802 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9804 static const int SPACEDIM=2;
9805 const double *coo1(m1->getCoords()->getConstPointer());
9806 const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9807 int offset1(m1->getNumberOfNodes());
9808 const double *coo2(m2->getCoords()->getConstPointer());
9809 const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9810 int offset2(offset1+m2->getNumberOfNodes());
9811 int offset3(offset2+((int)addCoords.size())/2);
9812 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9813 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9814 // Here a BBTree on 2D-cells, not on segments:
9815 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9816 int ncell1(m1->getNumberOfCells());
9818 for(int i=0;i<ncell1;i++)
9820 std::vector<int> candidates2;
9821 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9822 std::map<INTERP_KERNEL::Node *,int> mapp;
9823 std::map<int,INTERP_KERNEL::Node *> mappRev;
9824 INTERP_KERNEL::QuadraticPolygon pol1;
9825 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9826 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9827 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9828 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9829 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9830 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9831 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9833 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
9834 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9835 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9836 for(it1.first();!it1.finished();it1.next())
9837 edges1.insert(it1.current()->getPtr());
9839 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9840 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9842 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9844 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9845 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9846 // Complete mapping with elements coming from the current cell it2 in mesh2:
9847 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9848 // pol2 is the new QP in the final merged result.
9849 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9850 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9853 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9855 INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9856 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9857 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9858 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9860 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9861 // by m2 but that we still want to keep in the final result.
9866 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9868 catch(INTERP_KERNEL::Exception& e)
9870 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();
9871 throw INTERP_KERNEL::Exception(oss.str().c_str());
9874 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9875 (*it).second->decrRef();
9880 * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9881 * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9882 * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9883 * The caller is to deal with the resulting DataArrayInt.
9884 * \throw If the coordinate array is not set.
9885 * \throw If the nodal connectivity of the cells is not defined.
9886 * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9887 * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9889 * \sa DataArrayInt::sortEachPairToMakeALinkedList
9891 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9893 checkFullyDefined();
9894 if(getMeshDimension()!=1)
9895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9897 // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9900 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9901 const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9902 const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9904 const int * dsi(_dsi->getConstPointer());
9905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9907 if (dsii->getNumberOfTuples())
9908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9910 int nc(getNumberOfCells());
9911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9912 result->alloc(nc,1);
9914 // set of edges not used so far
9915 std::set<int> edgeSet;
9916 for (int i=0; i<nc; edgeSet.insert(i), i++);
9920 // while we have points with only one neighbor segments
9923 std::list<int> linePiece;
9924 // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9925 for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9927 // Fill the list forward (resp. backward) from the start segment:
9928 int activeSeg = startSeg;
9929 int prevPointId = -20;
9931 while (!edgeSet.empty())
9933 if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9936 linePiece.push_back(activeSeg);
9938 linePiece.push_front(activeSeg);
9939 edgeSet.erase(activeSeg);
9942 int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9943 ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9944 if (dsi[ptId] == 1) // hitting the end of the line
9947 int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9948 activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9951 // Done, save final piece into DA:
9952 std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9953 newIdx += linePiece.size();
9955 // identify next valid start segment (one which is not consumed)
9956 if(!edgeSet.empty())
9957 startSeg = *(edgeSet.begin());
9959 while (!edgeSet.empty());
9960 return result.retn();
9965 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9967 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9968 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9970 throw INTERP_KERNEL::Exception("Internal error in remapping !");
9971 int v((*it).second);
9972 if(v==forbVal0 || v==forbVal1)
9974 if(std::find(isect.begin(),isect.end(),v)==isect.end())
9978 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9983 bool presenceOfOn(false);
9984 for(int i=0;i<sz;i++)
9986 INTERP_KERNEL::ElementaryEdge *e(c[i]);
9987 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9989 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9990 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9992 return presenceOfOn;
9998 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
9999 * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
10000 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
10001 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10003 * \return int - the number of new nodes created (in most of cases 0).
10005 * \throw If \a this is not coherent.
10006 * \throw If \a this has not spaceDim equal to 2.
10007 * \throw If \a this has not meshDim equal to 2.
10008 * \throw If some subcells needed to be split are orphan.
10009 * \sa MEDCouplingUMesh::conformize2D
10011 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10013 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10014 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10015 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10016 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10017 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10018 if(midOpt==0 && midOptI==0)
10020 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10023 else if(midOpt!=0 && midOptI!=0)
10024 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10026 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10030 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10031 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10032 * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
10033 * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
10034 * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
10036 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10037 * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10039 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10040 * This method expects that all nodes in \a this are not closer than \a eps.
10041 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10043 * \param [in] eps the relative error to detect merged edges.
10044 * \return DataArrayInt * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
10045 * that the user is expected to deal with.
10047 * \throw If \a this is not coherent.
10048 * \throw If \a this has not spaceDim equal to 2.
10049 * \throw If \a this has not meshDim equal to 2.
10050 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10052 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10054 static const int SPACEDIM=2;
10056 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10057 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10059 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10060 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10061 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10062 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10063 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10064 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10065 std::vector<double> addCoo;
10066 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10067 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10068 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10069 for(int i=0;i<nDescCell;i++)
10071 std::vector<int> candidates;
10072 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10073 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10076 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10077 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10078 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10079 INTERP_KERNEL::MergePoints merge;
10080 INTERP_KERNEL::QuadraticPolygon c1,c2;
10081 e1->intersectWith(e2,merge,c1,c2);
10082 e1->decrRef(); e2->decrRef();
10083 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10084 overlapEdge[i].push_back(*it);
10085 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10086 overlapEdge[*it].push_back(i);
10089 // splitting done. sort intersect point in intersectEdge.
10090 std::vector< std::vector<int> > middle(nDescCell);
10091 int nbOf2DCellsToBeSplit(0);
10092 bool middleNeedsToBeUsed(false);
10093 std::vector<bool> cells2DToTreat(nDescCell,false);
10094 for(int i=0;i<nDescCell;i++)
10096 std::vector<int>& isect(intersectEdge[i]);
10097 int sz((int)isect.size());
10100 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10101 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10102 e->sortSubNodesAbs(coords,isect);
10107 int idx0(rdi[i]),idx1(rdi[i+1]);
10109 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10110 if(!cells2DToTreat[rd[idx0]])
10112 cells2DToTreat[rd[idx0]]=true;
10113 nbOf2DCellsToBeSplit++;
10115 // try to reuse at most eventual 'middle' of SEG3
10116 std::vector<int>& mid(middle[i]);
10117 mid.resize(sz+1,-1);
10118 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10120 middleNeedsToBeUsed=true;
10121 const std::vector<int>& candidates(overlapEdge[i]);
10122 std::vector<int> trueCandidates;
10123 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10124 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10125 trueCandidates.push_back(*itc);
10126 int stNode(c[ci[i]+1]),endNode(isect[0]);
10127 for(int j=0;j<sz+1;j++)
10129 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10131 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10132 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10133 { mid[j]=*itc; break; }
10136 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10142 if(nbOf2DCellsToBeSplit==0)
10145 int *retPtr(ret->getPointer());
10146 for(int i=0;i<nCell;i++)
10147 if(cells2DToTreat[i])
10150 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10151 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10152 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10153 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10154 if(middleNeedsToBeUsed)
10155 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10156 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10157 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10158 setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
10159 setPartOfMySelf(ret->begin(),ret->end(),*modif);
10161 bool areNodesMerged; int newNbOfNodes;
10162 if(nbOfNodesCreated!=0)
10163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10169 * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
10170 * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
10171 * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
10172 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10173 * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
10174 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10176 * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
10177 * using new instance, idem for coordinates.
10179 * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
10181 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
10183 * \throw If \a this is not coherent.
10184 * \throw If \a this has not spaceDim equal to 2.
10185 * \throw If \a this has not meshDim equal to 2.
10187 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10189 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10193 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10194 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10195 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10196 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10197 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10198 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10200 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10201 const double *coords(_coords->begin());
10202 int *newciptr(newci->getPointer());
10203 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10205 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10206 ret->pushBackSilent(i);
10207 newciptr[1]=newc->getNumberOfTuples();
10212 if(!appendedCoords->empty())
10214 appendedCoords->rearrange(2);
10215 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10217 setCoords(newCoords);
10220 setConnectivity(newc,newci,true);
10225 * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
10226 * So for all edge \a i in \a m1Desc \a intersectEdge1[i] is of length 2*n where n is the number of sub edges.
10227 * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10228 * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10229 * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10230 * \param [out] addCoo - nodes to be append at the end
10231 * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc.
10233 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10234 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
10236 static const int SPACEDIM=2;
10237 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10238 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10239 const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10240 // Build BB tree of all edges in the tool mesh (second mesh)
10241 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10242 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10243 int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10244 intersectEdge1.resize(nDescCell1);
10245 colinear2.resize(nDescCell2);
10246 subDiv2.resize(nDescCell2);
10247 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10249 std::vector<int> candidates1(1);
10250 int offset1(m1Desc->getNumberOfNodes());
10251 int offset2(offset1+m2Desc->getNumberOfNodes());
10252 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
10254 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10255 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10256 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10258 std::map<INTERP_KERNEL::Node *,int> map1,map2;
10259 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10260 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10262 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10263 // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
10264 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10265 std::set<INTERP_KERNEL::Node *> nodes;
10266 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10267 std::size_t szz(nodes.size());
10268 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10269 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10270 for(std::size_t iii=0;iii<szz;iii++,itt++)
10271 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10272 // end of protection
10273 // Performs egde cutting:
10274 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10279 // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10280 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10285 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10286 * It builds the descending connectivity of the two meshes, and then using a binary tree
10287 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10288 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10290 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10291 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10292 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10293 std::vector<double>& addCoo,
10294 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10296 // Build desc connectivity
10297 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10298 desc2=DataArrayInt::New();
10299 descIndx2=DataArrayInt::New();
10300 revDesc2=DataArrayInt::New();
10301 revDescIndx2=DataArrayInt::New();
10302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10303 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10304 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10305 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10306 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10307 std::map<int,int> notUsedMap;
10308 Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10309 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10310 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10314 * This method performs the 2nd step of Partition of 2D mesh.
10315 * This method has 4 inputs :
10316 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10317 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10318 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10319 * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
10320 * Nodes end up lying consecutively on a cutted edge.
10321 * \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.
10322 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10323 * \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.
10324 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10325 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10327 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10328 const std::vector<double>& addCoo,
10329 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10331 int offset1=m1->getNumberOfNodes();
10332 int ncell=m2->getNumberOfCells();
10333 const int *c=m2->getNodalConnectivity()->getConstPointer();
10334 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10335 const double *coo=m2->getCoords()->getConstPointer();
10336 const double *cooBis=m1->getCoords()->getConstPointer();
10337 int offset2=offset1+m2->getNumberOfNodes();
10338 intersectEdge.resize(ncell);
10339 for(int i=0;i<ncell;i++,cI++)
10341 const std::vector<int>& divs=subDiv[i];
10342 int nnode=cI[1]-cI[0]-1;
10343 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10344 std::map<INTERP_KERNEL::Node *, int> mapp22;
10345 for(int j=0;j<nnode;j++)
10347 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10348 int nnid=c[(*cI)+j+1];
10349 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10350 mapp22[nn]=nnid+offset1;
10352 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10353 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10354 ((*it).second.first)->decrRef();
10355 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10356 std::map<INTERP_KERNEL::Node *,int> mapp3;
10357 for(std::size_t j=0;j<divs.size();j++)
10360 INTERP_KERNEL::Node *tmp=0;
10362 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10363 else if(id<offset2)
10364 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10366 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10370 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10371 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10378 * 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).
10379 * 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
10380 * with a plane. The result will be put in 'cut3DSuf' out parameter.
10381 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10382 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10383 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10384 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10385 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10386 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10387 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10388 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10389 * \param [out] cut3DSuf input/output param.
10391 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10392 const int *nodal3DCurve, const int *nodalIndx3DCurve,
10393 const int *desc, const int *descIndx,
10394 std::vector< std::pair<int,int> >& cut3DSurf)
10396 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10397 int nbOf3DSurfCell=(int)cut3DSurf.size();
10398 for(int i=0;i<nbOf3DSurfCell;i++)
10400 std::vector<int> res;
10401 int offset=descIndx[i];
10402 int nbOfSeg=descIndx[i+1]-offset;
10403 for(int j=0;j<nbOfSeg;j++)
10405 int edgeId=desc[offset+j];
10406 int status=cut3DCurve[edgeId];
10410 res.push_back(status);
10413 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10414 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10422 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10428 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10429 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10432 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10436 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10441 {// case when plane is on a multi colinear edge of a polyhedron
10442 if((int)res.size()==2*nbOfSeg)
10444 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10454 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10455 * 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).
10456 * 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
10457 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10458 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10459 * \param desc is the descending connectivity 3D->3DSurf
10460 * \param descIndx is the descending connectivity index 3D->3DSurf
10462 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10463 const int *desc, const int *descIndx,
10464 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10466 checkFullyDefined();
10467 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10469 const int *nodal3D=_nodal_connec->getConstPointer();
10470 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10471 int nbOfCells=getNumberOfCells();
10472 for(int i=0;i<nbOfCells;i++)
10474 std::map<int, std::set<int> > m;
10475 int offset=descIndx[i];
10476 int nbOfFaces=descIndx[i+1]-offset;
10479 for(int j=0;j<nbOfFaces;j++)
10481 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10482 if(p.first!=-1 && p.second!=-1)
10486 start=p.first; end=p.second;
10487 m[p.first].insert(p.second);
10488 m[p.second].insert(p.first);
10492 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10493 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10494 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10495 INTERP_KERNEL::NormalizedCellType cmsId;
10496 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10497 start=tmp[0]; end=tmp[nbOfNodesSon-1];
10498 for(unsigned k=0;k<nbOfNodesSon;k++)
10500 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10501 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10508 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10512 std::map<int, std::set<int> >::const_iterator it=m.find(start);
10513 const std::set<int>& s=(*it).second;
10514 std::set<int> s2; s2.insert(prev);
10516 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10519 int val=*s3.begin();
10520 conn.push_back(start);
10527 conn.push_back(end);
10530 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10531 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10532 cellIds->pushBackSilent(i);
10538 * 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
10539 * 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
10540 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10541 * 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
10542 * 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.
10544 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10546 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10548 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10551 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10552 if(cm.getDimension()==2)
10554 const int *node=nodalConnBg+1;
10555 int startNode=*node++;
10556 double refX=coords[2*startNode];
10557 for(;node!=nodalConnEnd;node++)
10559 if(coords[2*(*node)]<refX)
10562 refX=coords[2*startNode];
10565 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10569 double angle0=-M_PI/2;
10574 double angleNext=0.;
10575 while(nextNode!=startNode)
10579 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10581 if(*node!=tmpOut.back() && *node!=prevNode)
10583 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10584 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10589 res=angle0-angleM+2.*M_PI;
10598 if(nextNode!=startNode)
10600 angle0=angleNext-M_PI;
10603 prevNode=tmpOut.back();
10604 tmpOut.push_back(nextNode);
10607 std::vector<int> tmp3(2*(sz-1));
10608 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10609 std::copy(nodalConnBg+1,nodalConnEnd,it);
10610 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10612 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10615 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10617 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10622 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10623 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10631 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10635 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10636 * 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.
10638 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10639 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10640 * \param [in,out] arr array in which the remove operation will be done.
10641 * \param [in,out] arrIndx array in the remove operation will modify
10642 * \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])
10643 * \return true if \b arr and \b arrIndx have been modified, false if not.
10645 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10647 if(!arrIndx || !arr)
10648 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10649 if(offsetForRemoval<0)
10650 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10651 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10652 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10653 int *arrIPtr=arrIndx->getPointer();
10655 int previousArrI=0;
10656 const int *arrPtr=arr->getConstPointer();
10657 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10658 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10660 if(*arrIPtr-previousArrI>offsetForRemoval)
10662 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10664 if(s.find(*work)==s.end())
10665 arrOut.push_back(*work);
10668 previousArrI=*arrIPtr;
10669 *arrIPtr=(int)arrOut.size();
10671 if(arr->getNumberOfTuples()==(int)arrOut.size())
10673 arr->alloc((int)arrOut.size(),1);
10674 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10679 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10680 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10681 * The selection of extraction is done standardly in new2old format.
10682 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10684 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10685 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10686 * \param [in] arrIn arr origin array from which the extraction will be done.
10687 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10688 * \param [out] arrOut the resulting array
10689 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10690 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10692 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10693 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10695 if(!arrIn || !arrIndxIn)
10696 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10697 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10698 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10699 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10700 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10701 const int *arrInPtr=arrIn->getConstPointer();
10702 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10703 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10706 int maxSizeOfArr=arrIn->getNumberOfTuples();
10707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10708 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10709 arrIo->alloc((int)(sz+1),1);
10710 const int *idsIt=idsOfSelectBg;
10711 int *work=arrIo->getPointer();
10714 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10716 if(*idsIt>=0 && *idsIt<nbOfGrps)
10717 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10720 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10721 throw INTERP_KERNEL::Exception(oss.str().c_str());
10727 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10728 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10729 throw INTERP_KERNEL::Exception(oss.str().c_str());
10732 arro->alloc(lgth,1);
10733 work=arro->getPointer();
10734 idsIt=idsOfSelectBg;
10735 for(std::size_t i=0;i<sz;i++,idsIt++)
10737 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10738 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10741 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10742 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10743 throw INTERP_KERNEL::Exception(oss.str().c_str());
10746 arrOut=arro.retn();
10747 arrIndexOut=arrIo.retn();
10751 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10752 * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
10753 * The selection of extraction is done standardly in new2old format.
10754 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10756 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10757 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10758 * \param [in] arrIn arr origin array from which the extraction will be done.
10759 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10760 * \param [out] arrOut the resulting array
10761 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10762 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10764 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10765 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10767 if(!arrIn || !arrIndxIn)
10768 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10769 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10770 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10771 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10772 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10773 const int *arrInPtr=arrIn->getConstPointer();
10774 const int *arrIndxPtr=arrIndxIn->getConstPointer();
10775 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10778 int maxSizeOfArr=arrIn->getNumberOfTuples();
10779 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10780 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10781 arrIo->alloc((int)(sz+1),1);
10782 int idsIt=idsOfSelectStart;
10783 int *work=arrIo->getPointer();
10786 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10788 if(idsIt>=0 && idsIt<nbOfGrps)
10789 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10792 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10793 throw INTERP_KERNEL::Exception(oss.str().c_str());
10799 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10800 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10801 throw INTERP_KERNEL::Exception(oss.str().c_str());
10804 arro->alloc(lgth,1);
10805 work=arro->getPointer();
10806 idsIt=idsOfSelectStart;
10807 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10809 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10810 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10813 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10814 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10815 throw INTERP_KERNEL::Exception(oss.str().c_str());
10818 arrOut=arro.retn();
10819 arrIndexOut=arrIo.retn();
10823 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10824 * 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
10825 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10826 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10828 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10829 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10830 * \param [in] arrIn arr origin array from which the extraction will be done.
10831 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10832 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10833 * \param [in] srcArrIndex index array of \b srcArr
10834 * \param [out] arrOut the resulting array
10835 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10837 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10839 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10840 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10841 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10843 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10844 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10845 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10847 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10848 std::vector<bool> v(nbOfTuples,true);
10850 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10851 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10852 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10854 if(*it>=0 && *it<nbOfTuples)
10857 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10861 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10862 throw INTERP_KERNEL::Exception(oss.str().c_str());
10865 srcArrIndexPtr=srcArrIndex->getConstPointer();
10866 arrIo->alloc(nbOfTuples+1,1);
10867 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10868 const int *arrInPtr=arrIn->getConstPointer();
10869 const int *srcArrPtr=srcArr->getConstPointer();
10870 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10871 int *arroPtr=arro->getPointer();
10872 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10876 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10877 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10881 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10882 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10883 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10886 arrOut=arro.retn();
10887 arrIndexOut=arrIo.retn();
10891 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10892 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10894 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10895 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10896 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10897 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10898 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10899 * \param [in] srcArrIndex index array of \b srcArr
10901 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10903 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10904 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10906 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10908 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10909 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10910 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10911 int *arrInOutPtr=arrInOut->getPointer();
10912 const int *srcArrPtr=srcArr->getConstPointer();
10913 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10915 if(*it>=0 && *it<nbOfTuples)
10917 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10918 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10921 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] !";
10922 throw INTERP_KERNEL::Exception(oss.str().c_str());
10927 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10928 throw INTERP_KERNEL::Exception(oss.str().c_str());
10934 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10935 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10936 * 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]].
10937 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10938 * A negative value in \b arrIn means that it is ignored.
10939 * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
10941 * \param [in] arrIn arr origin array from which the extraction will be done.
10942 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10943 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10944 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10946 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10948 int seed=0,nbOfDepthPeelingPerformed=0;
10949 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10953 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10954 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10955 * 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]].
10956 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10957 * A negative value in \b arrIn means that it is ignored.
10958 * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
10959 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10960 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10961 * \param [in] arrIn arr origin array from which the extraction will be done.
10962 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10963 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10964 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10965 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10966 * \sa MEDCouplingUMesh::partitionBySpreadZone
10968 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10970 nbOfDepthPeelingPerformed=0;
10972 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10973 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10976 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10980 std::vector<bool> fetched(nbOfTuples,false);
10981 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10984 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10986 nbOfDepthPeelingPerformed=0;
10987 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10988 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10989 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10990 std::vector<bool> fetched2(nbOfTuples,false);
10992 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10994 if(*seedElt>=0 && *seedElt<nbOfTuples)
10995 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10997 { 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()); }
10999 const int *arrInPtr=arrIn->getConstPointer();
11000 const int *arrIndxPtr=arrIndxIn->getConstPointer();
11001 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11002 std::vector<int> idsToFetch1(seedBg,seedEnd);
11003 std::vector<int> idsToFetch2;
11004 std::vector<int> *idsToFetch=&idsToFetch1;
11005 std::vector<int> *idsToFetchOther=&idsToFetch2;
11006 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11008 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11009 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11011 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11012 std::swap(idsToFetch,idsToFetchOther);
11013 idsToFetchOther->clear();
11014 nbOfDepthPeelingPerformed++;
11016 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11019 int *retPtr=ret->getPointer();
11020 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11027 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11028 * 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
11029 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11030 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11032 * \param [in] start begin of set of ids of the input extraction (included)
11033 * \param [in] end end of set of ids of the input extraction (excluded)
11034 * \param [in] step step of the set of ids in range mode.
11035 * \param [in] arrIn arr origin array from which the extraction will be done.
11036 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11037 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11038 * \param [in] srcArrIndex index array of \b srcArr
11039 * \param [out] arrOut the resulting array
11040 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11042 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11044 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11045 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11046 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11048 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11052 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11054 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11055 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11056 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11058 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11060 if(it>=0 && it<nbOfTuples)
11061 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11064 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11065 throw INTERP_KERNEL::Exception(oss.str().c_str());
11068 srcArrIndexPtr=srcArrIndex->getConstPointer();
11069 arrIo->alloc(nbOfTuples+1,1);
11070 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11071 const int *arrInPtr=arrIn->getConstPointer();
11072 const int *srcArrPtr=srcArr->getConstPointer();
11073 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11074 int *arroPtr=arro->getPointer();
11075 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11077 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11080 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11081 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11085 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11086 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11089 arrOut=arro.retn();
11090 arrIndexOut=arrIo.retn();
11094 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11095 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11097 * \param [in] start begin of set of ids of the input extraction (included)
11098 * \param [in] end end of set of ids of the input extraction (excluded)
11099 * \param [in] step step of the set of ids in range mode.
11100 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11101 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11102 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11103 * \param [in] srcArrIndex index array of \b srcArr
11105 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11107 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11108 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11110 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11112 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11113 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11114 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11115 int *arrInOutPtr=arrInOut->getPointer();
11116 const int *srcArrPtr=srcArr->getConstPointer();
11117 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11119 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11121 if(it>=0 && it<nbOfTuples)
11123 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11124 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11127 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11128 throw INTERP_KERNEL::Exception(oss.str().c_str());
11133 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11134 throw INTERP_KERNEL::Exception(oss.str().c_str());
11140 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11141 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11142 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11143 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11144 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11146 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11148 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11150 checkFullyDefined();
11151 int mdim=getMeshDimension();
11152 int spaceDim=getSpaceDimension();
11154 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11155 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11156 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11157 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11158 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11159 ret->setCoords(getCoords());
11160 ret->allocateCells((int)partition.size());
11162 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11164 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11165 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11169 cell=tmp->buildUnionOf2DMesh();
11172 cell=tmp->buildUnionOf3DMesh();
11175 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11178 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11181 ret->finishInsertingCells();
11186 * This method partitions \b this into contiguous zone.
11187 * This method only needs a well defined connectivity. Coordinates are not considered here.
11188 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11190 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11192 int nbOfCellsCur=getNumberOfCells();
11193 std::vector<DataArrayInt *> ret;
11194 if(nbOfCellsCur<=0)
11196 DataArrayInt *neigh=0,*neighI=0;
11197 computeNeighborsOfCells(neigh,neighI);
11198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11199 std::vector<bool> fetchedCells(nbOfCellsCur,false);
11200 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11202 while(seed<nbOfCellsCur)
11204 int nbOfPeelPerformed=0;
11205 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11206 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11208 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11209 ret.push_back((*it).retn());
11214 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11215 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11217 * \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.
11218 * \return a newly allocated DataArrayInt to be managed by the caller.
11219 * \throw In case of \a code has not the right format (typically of size 3*n)
11221 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11223 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11224 std::size_t nb=code.size()/3;
11225 if(code.size()%3!=0)
11226 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11227 ret->alloc((int)nb,2);
11228 int *retPtr=ret->getPointer();
11229 for(std::size_t i=0;i<nb;i++,retPtr+=2)
11231 retPtr[0]=code[3*i+2];
11232 retPtr[1]=code[3*i+2]+code[3*i+1];
11238 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11239 * All cells in \a this are expected to be linear 3D cells.
11240 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11241 * It leads to an increase to number of cells.
11242 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11243 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
11244 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11246 * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
11247 * For all other cells, the splitting policy will be ignored.
11248 * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added.
11249 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11250 * an id of old cell producing it. The caller is to delete this array using
11251 * decrRef() as it is no more needed.
11252 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11254 * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
11255 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11257 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11258 * \throw If \a this is not fully constituted with linear 3D cells.
11259 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11261 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11263 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11264 checkConnectivityFullyDefined();
11265 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11267 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11268 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11269 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11270 int *retPt(ret->getPointer());
11271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11272 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11273 const int *oldc(_nodal_connec->begin());
11274 const int *oldci(_nodal_connec_index->begin());
11275 const double *coords(_coords->begin());
11276 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11278 std::vector<int> a; std::vector<double> b;
11279 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11280 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11281 const int *aa(&a[0]);
11284 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11286 *it=(-(*(it))-1+nbNodes);
11287 addPts->insertAtTheEnd(b.begin(),b.end());
11288 nbNodes+=(int)b.size()/3;
11290 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11291 newConn->insertAtTheEnd(aa,aa+4);
11293 if(!addPts->empty())
11295 addPts->rearrange(3);
11296 nbOfAdditionalPoints=addPts->getNumberOfTuples();
11297 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11298 ret0->setCoords(addPts);
11302 nbOfAdditionalPoints=0;
11303 ret0->setCoords(getCoords());
11305 ret0->setNodalConnectivity(newConn);
11307 ret->computeOffsets2();
11308 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11309 return ret0.retn();
11313 * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch).
11315 * \sa MEDCouplingUMesh::split2DCells
11317 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11319 checkConnectivityFullyDefined();
11320 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11322 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11323 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11324 int prevPosOfCi(ciPtr[0]);
11325 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11327 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11328 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11329 for(int j=0;j<sz;j++)
11331 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11332 for(int k=0;k<sz2;k++)
11333 *cPtr++=subPtr[offset2+k];
11335 *cPtr++=oldConn[prevPosOfCi+j+2];
11338 prevPosOfCi=ciPtr[1];
11339 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11343 _nodal_connec->decrRef();
11344 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11347 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11353 int ret(nodesCnter++);
11355 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11356 addCoo.insertAtTheEnd(newPt,newPt+2);
11363 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11366 int trueStart(start>=0?start:nbOfEdges+start);
11367 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11368 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11373 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11374 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11375 middles.push_back(tmp3+offset);
11378 middles.push_back(connBg[trueStart+nbOfEdges]);
11382 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11384 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11385 newConnOfCell->pushBackSilent(tmpEnd);
11390 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11391 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11392 middles.push_back(tmp3+offset);
11395 middles.push_back(connBg[start+nbOfEdges]);
11399 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11405 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11406 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11407 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11408 middles.push_back(tmp3+offset);
11411 middles.push_back(connBg[start+nbOfEdges]);
11418 * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
11419 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11421 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11423 std::size_t sz(std::distance(connBg,connEnd));
11424 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11427 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11428 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11429 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11430 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11431 INTERP_KERNEL::NormalizedCellType typeOfSon;
11432 std::vector<int> middles;
11434 for(;nbOfHit<nbs;nbOfTurn++)
11436 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11437 std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11438 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11441 unsigned endI(nbs-nbOfHit);
11442 for(unsigned i=0;i<endI;i++)
11444 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11445 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11446 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11447 bool isColinear(eint->areColinears());
11459 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11460 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11461 for(unsigned ii=0;ii<endII;ii++)
11463 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11464 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11465 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11466 isColinear=eint->areColinears();
11482 //push [posBaseElt,posEndElt) in newConnOfCell using e
11484 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11485 else if(nbOfHit!=nbs)
11486 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11488 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11489 posBaseElt=posEndElt;
11492 if(!middles.empty())
11493 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11498 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11500 * \return int - the number of new nodes created.
11501 * \sa MEDCouplingUMesh::split2DCells
11503 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11506 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11508 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11509 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11510 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11511 const double *oldCoordsPtr(getCoords()->begin());
11512 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11513 int prevPosOfCi(ciPtr[0]);
11514 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11516 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11517 for(int j=0;j<sz;j++)
11518 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11519 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11520 for(int j=0;j<sz;j++)//loop over subedges of oldConn
11522 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11526 cPtr[1]=oldConn[prevPosOfCi+2+j];
11527 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11530 std::vector<INTERP_KERNEL::Node *> ns(3);
11531 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11532 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11533 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11534 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11535 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11537 cPtr[1]=subPtr[offset2+k];
11538 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11540 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11542 { cPtr[1]=tmpEnd; }
11543 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11545 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11546 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11549 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11550 _nodal_connec->decrRef();
11551 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11552 addCoo->rearrange(2);
11553 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11555 return addCoo->getNumberOfTuples();
11558 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11560 if(nodalConnec && nodalConnecIndex)
11563 const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11564 int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11566 for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11567 types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11571 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11572 _own_cell(true),_cell_id(-1),_nb_cell(0)
11577 _nb_cell=mesh->getNumberOfCells();
11581 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11589 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11590 _own_cell(false),_cell_id(bg-1),
11597 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11600 if(_cell_id<_nb_cell)
11609 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11615 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11617 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11620 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11626 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11634 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11640 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11645 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11650 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11652 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11655 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11660 _nb_cell=mesh->getNumberOfCells();
11664 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11671 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11673 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11674 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11675 if(_cell_id<_nb_cell)
11677 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11678 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11679 int startId=_cell_id;
11680 _cell_id+=nbOfElems;
11681 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11687 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11691 _conn=mesh->getNodalConnectivity()->getPointer();
11692 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11696 void MEDCouplingUMeshCell::next()
11698 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11703 _conn_lgth=_conn_indx[1]-_conn_indx[0];
11706 std::string MEDCouplingUMeshCell::repr() const
11708 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11710 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11712 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11716 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11719 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11721 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11722 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11724 return INTERP_KERNEL::NORM_ERROR;
11727 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11730 if(_conn_lgth!=NOTICABLE_FIRST_VAL)