// Author : Anthony Geay (CEA/DEN)
#include "MEDCouplingUMesh.hxx"
+#include "MEDCoupling1GTUMesh.hxx"
#include "MEDCouplingMemArray.txx"
#include "MEDCouplingFieldDouble.hxx"
#include "CellModel.hxx"
#include "InterpolationUtils.hxx"
#include "PointLocatorAlgos.txx"
#include "BBTree.txx"
+#include "BBTreeDst.txx"
#include "SplitterTetra.hxx"
#include "DirectedBoundingBox.hxx"
#include "InterpKernelMeshQuality.hxx"
return ret;
}
+/*!
+ * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
+ * between \a this and the new mesh.
+ * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
+ * delete this mesh using decrRef() as it is no more needed.
+ */
MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
{
return clone(true);
}
+/*!
+ * Returns a new MEDCouplingMesh which is a copy of \a this one.
+ * \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
+ * this mesh are shared by the new mesh.
+ * \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
+ * delete this mesh using decrRef() as it is no more needed.
+ */
MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
{
return new MEDCouplingUMesh(*this,recDeepCpy);
}
+/*!
+ * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
+ * The coordinates are shared between \a this and the returned instance.
+ *
+ * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
+ * \sa MEDCouplingUMesh::deepCpy
+ */
+MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception)
+{
+ checkConnectivityFullyDefined();
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
+ ret->setConnectivity(c,ci);
+ return ret.retn();
+}
+
+void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
+{
+ if(!other)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
+ const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
+ if(!otherC)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
+ MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
+ setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
+}
+
std::size_t MEDCouplingUMesh::getHeapMemorySize() const
{
std::size_t ret=0;
}
/*!
- * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity.
- * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be
- * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check
- * that all is in order in 'this'.
+ * Checks if \a this mesh is well defined. If no exception is thrown by this method,
+ * then \a this mesh is most probably is writable, exchangeable and available for most
+ * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
+ * this method to check that all is in order with \a this mesh.
+ * \throw If the mesh dimension is not set.
+ * \throw If the coordinates array is not set (if mesh dimension != -1 ).
+ * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
+ * \throw If the connectivity data array has more than one component.
+ * \throw If the connectivity data array has a named component.
+ * \throw If the connectivity index data array has more than one component.
+ * \throw If the connectivity index data array has a named component.
*/
void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
{
if(_nodal_connec->getInfoOnComponent(0)!="")
throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
}
+ else
+ if(_mesh_dim!=-1)
+ throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
if(_nodal_connec_index)
{
if(_nodal_connec_index->getNumberOfComponents()!=1)
if(_nodal_connec_index->getInfoOnComponent(0)!="")
throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
}
-}
-
-/*!
- * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does.
- * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids.
- * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2.
+ else
+ if(_mesh_dim!=-1)
+ throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
+}
+
+/*!
+ * Checks if \a this mesh is well defined. If no exception is thrown by this method,
+ * then \a this mesh is most probably is writable, exchangeable and available for all
+ * algorithms. <br> In addition to the checks performed by checkCoherency(), this
+ * method thoroughly checks the nodal connectivity.
+ * \param [in] eps - a not used parameter.
+ * \throw If the mesh dimension is not set.
+ * \throw If the coordinates array is not set (if mesh dimension != -1 ).
+ * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
+ * \throw If the connectivity data array has more than one component.
+ * \throw If the connectivity data array has a named component.
+ * \throw If the connectivity index data array has more than one component.
+ * \throw If the connectivity index data array has a named component.
+ * \throw If number of nodes defining an element does not correspond to the type of element.
+ * \throw If the nodal connectivity includes an invalid node id.
*/
void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
{
}
}
+
+/*!
+ * Checks if \a this mesh is well defined. If no exception is thrown by this method,
+ * then \a this mesh is most probably is writable, exchangeable and available for all
+ * algorithms. <br> This method performs the same checks as checkCoherency1() does.
+ * \param [in] eps - a not used parameter.
+ * \throw If the mesh dimension is not set.
+ * \throw If the coordinates array is not set (if mesh dimension != -1 ).
+ * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
+ * \throw If the connectivity data array has more than one component.
+ * \throw If the connectivity data array has a named component.
+ * \throw If the connectivity index data array has more than one component.
+ * \throw If the connectivity index data array has a named component.
+ * \throw If number of nodes defining an element does not correspond to the type of element.
+ * \throw If the nodal connectivity includes an invalid node id.
+ */
void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
{
checkCoherency1(eps);
}
+/*!
+ * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
+ * elements contained in the mesh. For more info on the mesh dimension see
+ * \ref MEDCouplingUMeshPage.
+ * \param [in] meshDim - a new mesh dimension.
+ * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
+ */
void MEDCouplingUMesh::setMeshDimension(int meshDim)
{
if(meshDim<-1 || meshDim>3)
declareAsNew();
}
+/*!
+ * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
+ * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
+ * If a nodal connectivity previouly existed before the call of this method, it will be reset.
+ *
+ * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
+ *
+ * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
+ * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
+ */
void MEDCouplingUMesh::allocateCells(int nbOfCells)
{
+ if(nbOfCells<0)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
if(_nodal_connec_index)
{
_nodal_connec_index->decrRef();
}
/*!
- * Appends a cell in connectivity array.
- * @param type type of cell to add.
- * @param size number of nodes constituting this cell.
- * @param nodalConnOfCell the connectivity of the cell to add.
+ * Appends a cell to the connectivity array. For deeper understanding what is
+ * happening see \ref MEDCouplingUMeshNodalConnectivity.
+ * \param [in] type - type of cell to add.
+ * \param [in] size - number of nodes constituting this cell.
+ * \param [in] nodalConnOfCell - the connectivity of the cell to add.
+ *
+ * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
+ * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
*/
void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * Method to be called to cloture the insertion of cells using this->insertNextCell.
+ * Compacts data arrays to release unused memory. This method is to be called after
+ * finishing cell insertion using \a this->insertNextCell().
+ *
+ * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
+ * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
*/
void MEDCouplingUMesh::finishInsertingCells()
{
/*!
* Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
- * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
+ * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
* In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
* Useful for python users.
*/
return new MEDCouplingUMeshCellByTypeEntry(this);
}
+/*!
+ * Returns a set of all cell types available in \a this mesh.
+ * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
+ * \warning this method does not throw any exception even if \a this is not defined.
+ */
std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
{
return _types;
}
/*!
- * This method is a method that compares 'this' and 'other'.
+ * This method is a method that compares \a this and \a other.
* This method compares \b all attributes, even names and component names.
*/
bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
return true;
}
+/*!
+ * Checks if data arrays of this mesh (node coordinates, nodal
+ * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
+ * not considered.
+ * \param [in] other - the mesh to compare with.
+ * \param [in] prec - precision value used to compare node coordinates.
+ * \return bool - \a true if the two meshes are same.
+ */
bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
{
const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
}
/*!
- * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
- * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
- *
- * In case of success cellCor and nodeCor are informed both.
- * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
- * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
- * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
- */
-void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
- DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
-{
- const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
- if(!otherC)
- throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
- MEDCouplingMesh::checkFastEquivalWith(other,prec);
- if(_types!=otherC->_types)
- throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
- bool areNodesMerged;
- int newNbOfNodes;
- int oldNbOfNodes=getNumberOfNodes();
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
- //mergeNodes
- if(!areNodesMerged)
- throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
- const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
- if(pt!=da->getConstPointer()+da->getNbOfElems())
- throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
- m->renumberNodes(da->getConstPointer(),newNbOfNodes);
- //
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
- da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
-
- //
- da=m->zipConnectivityTraducer(cellCompPol);
- int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
- pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
- if(pt!=da->getConstPointer()+da->getNbOfElems())
- throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
- nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
- cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
-}
-
-/*!
- * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
- * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
- * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
- * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception !
- *
- * In case of success cellCor are informed both.
- * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
- * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
- */
-void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
- DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
-{
- const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
- if(!otherC)
- throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
- MEDCouplingMesh::checkFastEquivalWith(other,prec);
- if(_types!=otherC->_types)
- throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
- if(_coords!=otherC->_coords)
- throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
- std::vector<const MEDCouplingUMesh *> ms(2);
- ms[0]=this;
- ms[1]=otherC;
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
- int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
- const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
- if(pt!=da->getConstPointer()+da->getNbOfElems())
- {
- throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
- }
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
- cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
-}
-
-/*!
- * This method checks fastly that 'this' and 'other' are equal.
+ * Checks if \a this and \a other meshes are geometrically equivalent with high
+ * probability, else an exception is thrown. The meshes are considered equivalent if
+ * (1) meshes contain the same number of nodes and the same number of elements of the
+ * same types (2) three cells of the two meshes (first, last and middle) are based
+ * on coincident nodes (with a specified precision).
+ * \param [in] other - the mesh to compare with.
+ * \param [in] prec - the precision used to compare nodes of the two meshes.
+ * \throw If the two meshes do not match.
*/
void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
{
- const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
+ MEDCouplingPointSet::checkFastEquivalWith(other,prec);
+ const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
if(!otherC)
- throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
- MEDCouplingPointSet::checkFastEquivalWith(other,prec);
- int nbOfCells=getNumberOfCells();
- if(nbOfCells<1)
- return ;
- bool status=true;
- status&=areCellsFrom2MeshEqual(otherC,0,prec);
- status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
- status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
- if(!status)
- throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
-}
-
-/*!
- * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
- * For speed reasons no check of this will be done.
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
+}
+
+/*!
+ * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
+ * cells each node belongs to.
+ * \warning For speed reasons, this method does not check if node ids in the nodal
+ * connectivity correspond to the size of node coordinates array.
+ * \param [in,out] revNodal - an array holding ids of cells sharing each node.
+ * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
+ * dividing cell ids in \a revNodal into groups each referring to one
+ * node. Its every element (except the last one) is an index pointing to the
+ * first id of a group of cells. For example cells sharing the node #1 are
+ * described by following range of indices:
+ * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
+ * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
+ * Number of cells sharing the *i*-th node is
+ * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
+ * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
*/
void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
{
checkFullyDefined();
int nbOfNodes=getNumberOfNodes();
- int *revNodalIndxPtr=new int[nbOfNodes+1];
- revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
+ int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
+ revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
const int *conn=_nodal_connec->getConstPointer();
const int *connIndex=_nodal_connec_index->getConstPointer();
}
}
std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
- int *revNodalPtr=new int[nbOfEltsInRevNodal];
- revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
+ int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
+ revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
for(int eltId=0;eltId<nbOfCells;eltId++)
{
/// @endcond
/*!
- * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
- * For speed reasons no check of this will be done.
- * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
- * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
- * The algorithm to compute this p-1 mesh is the following :
- * For each cell in 'this' it splits into p-1 elements.
- * If this p-1 element does not already exists it is appended to the returned mesh
- * If this p-1 element already exists, it is not appended.
- * This method returns or 4 arrays plus the returned mesh.
- * 'desc' and 'descIndx' are the descending connectivity. These 2 arrays tell for each cell in 'this', to wich p-1 dimension cell in returned mesh it refers.
- * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
- *
- * Reversely 'revDesc' and 'revDescIndx' are the reverse descending connectivity. These 2 arrays tell for each cell in returned mesh, to wich cell in 'this' it refers.
- * For a cell with a cellid d in returned p-1 mesh it is shared by the following cells in 'this' [revDesc+revDescIndx[d],revDesc+revDescIndx[d+1])
- *
- * \warning This method returns a mesh whose geometric type order in are \b not sorted.
- * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
+ * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
+ * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
+ * describing correspondence between cells of \a this and the result meshes are
+ * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
+ * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
+ * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
+ * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
+ * \warning For speed reasons, this method does not check if node ids in the nodal
+ * connectivity correspond to the size of node coordinates array.
+ * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
+ * to write this mesh to the MED file, its cells must be sorted using
+ * sortCellsInMEDFileFrmt().
+ * \param [in,out] desc - the array containing cell ids of the result mesh bounding
+ * each cell of \a this mesh.
+ * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
+ * dividing cell ids in \a desc into groups each referring to one
+ * cell of \a this mesh. Its every element (except the last one) is an index
+ * pointing to the first id of a group of cells. For example cells of the
+ * result mesh bounding the cell #1 of \a this mesh are described by following
+ * range of indices:
+ * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
+ * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
+ * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
+ * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
+ * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
+ * by each cell of the result mesh.
+ * \param [in,out] revDescIndx - the array, of length one more than number of cells
+ * in the result mesh,
+ * dividing cell ids in \a revDesc into groups each referring to one
+ * cell of the result mesh the same way as \a descIndx divides \a desc.
+ * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
+ * delete this mesh using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is node defined.
+ * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
+ * revDescIndx == NULL.
+ *
+ * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
+ * \sa buildDescendingConnectivity2()
*/
MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * WARNING this method do the assumption that connectivity lies on the coordinates set.
- * For speed reasons no check of this will be done.
- * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
- * This method is more precise because it returns in descending connectivity giving the direction. If value is positive the n-1 dim element is taken in the same direction,
- * if it is in the opposite direction it is retrieved negative. So the problem is for elemt #0 in C convention. That's why this method is the only one that retrieves
- * an array in relative "FORTRAN" mode.
- *
- * \warning This method returns a mesh whose geometric type order in are \b not sorted.
- * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
+ * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
+ * this->getMeshDimension(), that bound cells of \a this mesh. In
+ * addition arrays describing correspondence between cells of \a this and the result
+ * meshes are returned. The arrays \a desc and \a descIndx describe the descending
+ * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
+ * mesh. This method differs from buildDescendingConnectivity() in that apart
+ * from cell ids, \a desc returns mutual orientation of cells in \a this and the
+ * result meshes. So a positive id means that order of nodes in corresponding cells
+ * of two meshes is same, and a negative id means a reverse order of nodes. Since a
+ * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
+ * i.e. cell ids are one-based.
+ * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
+ * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
+ * \warning For speed reasons, this method does not check if node ids in the nodal
+ * connectivity correspond to the size of node coordinates array.
+ * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
+ * to write this mesh to the MED file, its cells must be sorted using
+ * sortCellsInMEDFileFrmt().
+ * \param [in,out] desc - the array containing cell ids of the result mesh bounding
+ * each cell of \a this mesh.
+ * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
+ * dividing cell ids in \a desc into groups each referring to one
+ * cell of \a this mesh. Its every element (except the last one) is an index
+ * pointing to the first id of a group of cells. For example cells of the
+ * result mesh bounding the cell #1 of \a this mesh are described by following
+ * range of indices:
+ * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
+ * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
+ * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
+ * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
+ * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
+ * by each cell of the result mesh.
+ * \param [in,out] revDescIndx - the array, of length one more than number of cells
+ * in the result mesh,
+ * dividing cell ids in \a revDesc into groups each referring to one
+ * cell of the result mesh the same way as \a descIndx divides \a desc.
+ * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
+ * shares the node coordinates array with \a this mesh. The caller is to
+ * delete this mesh using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is node defined.
+ * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
+ * revDescIndx == NULL.
+ *
+ * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
+ * \sa buildDescendingConnectivity()
*/
MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
{
/// @endcond
-
/*!
- * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
- * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
- * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
- * If mesh dimension is not in [2,3] an exception is thrown.
- * Of course pay attention that the resulting mesh is slower than previous one.
- * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
- * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
- * If mesh==3, after throw the mesh is \b unconsistent !
- * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
- *
- * \warning This method modifies can modify significantly the geometric type order in \a this.
- * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
+ * Converts specified cells to either polygons (if \a this is a 2D mesh) or
+ * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
+ * array of cell ids. Pay attention that after conversion all algorithms work slower
+ * with \a this mesh than before conversion. <br> If an exception is thrown during the
+ * conversion due presence of invalid ids in the array of cells to convert, as a
+ * result \a this mesh contains some already converted elements. In this case the 2D
+ * mesh remains valid but 3D mesh becomes \b inconsistent!
+ * \warning This method can significantly modify the order of geometric types in \a this,
+ * hence, to write this mesh to the MED file, its cells must be sorted using
+ * sortCellsInMEDFileFrmt().
+ * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
+ * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
+ * cellIdsToConvertBg.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is node defined.
+ * \throw If dimension of \a this mesh is not either 2 or 3.
+ *
+ * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
+ * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
*/
void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
{
if(*iter>=0 && *iter<nbOfCells)
{
const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
- if(!cm.isDynamic())
+ if(!cm.isQuadratic())
conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
else
conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
}
/*!
- * This method converts all cells into poly type if possible.
- * This method is purely for userfriendliness.
- * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
+ * Converts all cells to either polygons (if \a this is a 2D mesh) or
+ * polyhedrons (if \a this is a 3D mesh).
+ * \warning As this method is purely for user-friendliness and no optimization is
+ * done to avoid construction of a useless vector, this method can be costly
+ * in memory.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is node defined.
+ * \throw If dimension of \a this mesh is not either 2 or 3.
*/
void MEDCouplingUMesh::convertAllToPoly()
{
}
/*!
- * This method expects that 'this' has a spacedim equal to 3 and a mesh dimension equal to 3 too, if not an exception will be thrown.
- * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
- * For such polyhedra, they are expected to have only 1 face (containing 2 faces in opposition), having 2*n number of nodes (n nodes on
- * each 2 faces hidden in the single face of polyhedron).
- * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
- * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
- * In case of presence of polyhedron that has not the extruded aspect (2 faces with the same number of nodes) an exception is thrown and 'this'
- * remains unchanged.
- * This method is useful only for users that wants to build extruded unstructured mesh.
- * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
- * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
+ * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
+ * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
+ * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
+ * base facet of the volume and the second half of nodes describes an opposite facet
+ * having the same number of nodes as the base one. This method converts such
+ * connectivity to a valid polyhedral format where connectivity of each facet is
+ * explicitly described and connectivity of facets are separated by -1. If \a this mesh
+ * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
+ * not as expected, an exception is thrown and the mesh remains unchanged. Care of
+ * a correct orientation of the first facet of a polyhedron, else orientation of a
+ * corrected cell is reverse.<br>
+ * This method is useful to build an extruded unstructured mesh with polyhedrons as
+ * it releases the user from boring description of polyhedra connectivity in the valid
+ * format.
+ * \throw If \a this->getMeshDimension() != 3.
+ * \throw If \a this->getSpaceDimension() != 3.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this mesh contains polyhedrons with the valid connectivity.
+ * \throw If \a this mesh contains polyhedrons with odd number of nodes.
+ *
+ * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
+ * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
*/
void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
{
newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
newc[n1+5*j]=-1;
newc[n1+5*j+1]=c[ci[i]+1+j];
- newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
+ newc[n1+5*j+2]=c[ci[i]+1+j+n1];
newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
- newc[n1+5*j+4]=c[ci[i]+1+j+n1];
+ newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
}
newc+=n1*6;
}
_nodal_connec->decrRef(); _nodal_connec=newC.retn();
}
+
/*!
- * This method is the opposite of ParaMEDMEM::MEDCouplingUMesh::convertToPolyTypes method.
- * The aim is to take all polygons or polyhedrons cell and to try to traduce them into classical cells.
- *
- * \return If true at least one cell has been unpolyzed.
- \n If false has been returned the nodal connectivity of \a this has **not** been altered and \a this has remains unchanged.
- *
- * \warning This method modifies can modify significantly the geometric type order in \a this.
- * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
+ * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
+ * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
+ * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
+ * to write this mesh to the MED file, its cells must be sorted using
+ * sortCellsInMEDFileFrmt().
+ * \return \c true if at least one cell has been converted, \c false else. In the
+ * last case the nodal connectivity remains unchanged.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If \a this->getMeshDimension() < 0.
*/
bool MEDCouplingUMesh::unPolyze()
{
* The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
* the format of returned DataArrayInt instance.
*
- * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
+ * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
* \sa MEDCouplingUMesh::getNodeIdsInUse
*/
DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
}
/*!
- * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
- * The returned array is newly created and should be dealt by the caller.
- * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
- * The size of returned array is the number of nodes of 'this'.
- * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
- * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
- * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
- * \throw if a cell contains in its nodal connectivity a node id >= nb of nodes an exception will be thrown.
- * \sa MEDCouplingUMesh::computeNodeIdsAlg
+ * Finds nodes not used in any cell and returns an array giving a new id to every node
+ * by excluding the unused nodes, for which the array holds -1. The result array is
+ * a mapping in "Old to New" mode.
+ * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
+ * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
+ * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
+ * if the node is unused or a new id else. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the nodal connectivity includes an invalid id.
+ *
+ * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
+ * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
+ * \sa computeNodeIdsAlg()
*/
DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
{
/*!
* This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
* For each cell in \b this the number of nodes constituting cell is computed.
- * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
- * For polyhedrons, the face separation (-1) are excluded from the couting.
+ * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
+ * So for pohyhedrons some nodes can be counted several times in the returned result.
*
* \return a newly allocated array
+ * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
*/
DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
- * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
- * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
- * -1 values in returned array means that the corresponding old node is no more used.
+ * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
+ * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
+ *
+ * \return DataArrayInt * - new object to be deallocated by the caller.
+ * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
+ */
+DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
+{
+ checkConnectivityFullyDefined();
+ int nbOfCells=getNumberOfCells();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
+ ret->alloc(nbOfCells,1);
+ int *retPtr=ret->getPointer();
+ const int *conn=getNodalConnectivity()->getConstPointer();
+ const int *connI=getNodalConnectivityIndex()->getConstPointer();
+ for(int i=0;i<nbOfCells;i++,retPtr++)
+ {
+ std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
+ if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
+ *retPtr=(int)s.size();
+ else
+ {
+ s.erase(-1);
+ *retPtr=(int)s.size();
+ }
+ }
+ return ret.retn();
+}
+
+/*!
+ * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
+ * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
+ *
+ * \return a newly allocated array
+ */
+DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
+{
+ checkConnectivityFullyDefined();
+ int nbOfCells=getNumberOfCells();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
+ ret->alloc(nbOfCells,1);
+ int *retPtr=ret->getPointer();
+ const int *conn=getNodalConnectivity()->getConstPointer();
+ const int *connI=getNodalConnectivityIndex()->getConstPointer();
+ for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
+ {
+ const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
+ *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
+ }
+ return ret.retn();
+}
+
+/*!
+ * Removes unused nodes (the node coordinates array is shorten) and returns an array
+ * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
+ * array mean that the corresponding old node is no more used.
+ * \return DataArrayInt * - a new instance of DataArrayInt of length \a
+ * this->getNumberOfNodes() before call of this method. The caller is to
+ * delete this array using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the nodal connectivity includes an invalid id.
+ *
+ * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
+ * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
*/
DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
{
- int newNbOfNodes=-1;
- DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
- renumberNodes(traducer->getConstPointer(),newNbOfNodes);
- return traducer;
+ return MEDCouplingPointSet::zipCoordsTraducer();
}
/*!
* This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
- * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
+ * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
*/
int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
{
}
/*!
- * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
+ * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
*/
int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
{
}
/*!
- * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
+ * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
*/
int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
{
}
/*!
- * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
+ * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
*/
int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
{
}
/*!
- * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
+ * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
*/
int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
{
return 0;
}
-
-/*!
- * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
- * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
- */
-bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
-{
- if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
- return false;
- std::vector<int> c1,c2;
- getNodeIdsOfCell(cellId,c1);
- other->getNodeIdsOfCell(cellId,c2);
- std::size_t sz=c1.size();
- if(sz!=c2.size())
- return false;
- for(std::size_t i=0;i<sz;i++)
- {
- std::vector<double> n1,n2;
- getCoordinatesOfNode(c1[0],n1);
- other->getCoordinatesOfNode(c2[0],n2);
- std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
- std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
- if(*std::max_element(n1.begin(),n1.end())>prec)
- return false;
- }
- return true;
-}
-
/*!
* This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
* If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
* and result remains unchanged.
- * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
+ * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
* If in 'candidates' pool -1 value is considered as an empty value.
* WARNING this method returns only ONE set of result !
*/
*/
void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
{
- checkConnectivityFullyDefined();
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
getReverseNodalConnectivity(revNodal,revNodalI);
FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
}
/*!
- * This method could potentially modify \a this. This method merges cells if there are cells equal in \a this. The comparison is specified by \a compType.
- * This method keeps the coordiantes of \a this.
+ * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
+ * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
+ * than \a other->getNumberOfCells() in the returned array means that there is no
+ * corresponding cell in \a this mesh.
+ * It is expected that \a this and \a other meshes share the same node coordinates
+ * array, if it is not so an exception is thrown.
+ * \param [in] other - the mesh to compare with.
+ * \param [in] compType - specifies a cell comparison technique. For meaning of its
+ * valid values [0,1,2], see zipConnectivityTraducer().
+ * \param [out] arr - a new instance of DataArrayInt returning correspondence
+ * between cells of the two meshes. It contains \a other->getNumberOfCells()
+ * values. The caller is to delete this array using
+ * decrRef() as it is no more needed.
+ * \return bool - \c true if all cells of \a other mesh are present in the \a this
+ * mesh.
*
- * \param [in] compType input specifying the technique used to compare cells each other.
- * - 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.
- * - 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)
- * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
- * - 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
- * can be used for users not sensitive to orientation of cell
- * \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
- * \return the correspondance array old to new in a newly allocated array.
- *
- * \warning This method modifies can modify significantly the geometric type order in \a this.
- * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
- */
-DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
-{
- DataArrayInt *commonCells=0,*commonCellsI=0;
- findCommonCells(compType,startCellId,commonCells,commonCellsI);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
- int newNbOfCells=-1;
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
- commonCellsI->end(),newNbOfCells);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
- setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
- return ret.retn();
-}
-
-/*!
- * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
- * This method tries to determine if 'other' is fully included in 'this'. To compute that, this method works with connectivity as MEDCouplingUMesh::zipConnectivityTraducer method does.
- * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
- * The main difference is that this method is not expected to throw exception.
- * This method has two outputs :
- *
- * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
- * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
- * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
+ * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
+ * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
+ * \sa checkDeepEquivalOnSameNodesWith()
+ * \sa checkGeoEquivalWith()
*/
bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
{
}
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
arr=o2n->substr(nbOfCells);
- arr->setName(other->getName());
+ arr->setName(other->getName().c_str());
int tmp;
if(other->getNumberOfCells()==0)
return true;
}
/*!
- * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
+ * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
* This method tries to determine if \b other is fully included in \b this.
* The main difference is that this method is not expected to throw exception.
* This method has two outputs :
*
- * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
- * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
+ * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
+ * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
*/
bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
{
}
}
}
- arr2->setName(other->getName());
+ arr2->setName(other->getName().c_str());
if(arr2->presenceOfValue(0))
return false;
arr=arr2.retn();
return true;
}
-/*!
- * @param areNodesMerged if at least two nodes have been merged.
- * @return old to new node correspondance.
- */
-DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
-{
- DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
- if(areNodesMerged)
- renumberNodes(ret->getConstPointer(),newNbOfNodes);
- return ret;
-}
-
-/*!
- * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
- */
-DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
-{
- DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
- if(areNodesMerged)
- renumberNodes2(ret->getConstPointer(),newNbOfNodes);
- return ret;
-}
-
-/*!
- * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
- * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
- * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
- * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
- */
-void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
+MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
{
- const DataArrayDouble *coords=other.getCoords();
- if(!coords)
- throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
- if(!_coords)
- throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
- int otherNbOfNodes=other.getNumberOfNodes();
- MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
- _coords->incrRef();
- MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
- setCoords(newCoords);
- bool areNodesMerged;
- int newNbOfNodes;
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
- if(!areNodesMerged)
- {
- setCoords(oldCoords);
- throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
- }
- int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
- const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
- if(pt!=da->getConstPointer()+da->getNbOfElems())
- {
- setCoords(oldCoords);
- throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
- }
- setCoords(oldCoords);
- renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
- setCoords(coords);
+ if(!other)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
+ const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
+ if(!otherC)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
+ std::vector<const MEDCouplingUMesh *> ms(2);
+ ms[0]=this;
+ ms[1]=otherC;
+ return MergeUMeshesOnSameCoords(ms);
}
/*!
MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
{
if(getMeshDimension()!=-1)
- {
- MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
- if(!keepCoords)
- ret->zipCoords();
- return ret;
- }
+ return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
else
{
int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
}
/*!
- * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
- * @param begin begin of array containing the cell ids to keep.
- * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
- * @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.
- *
- * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
- * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
+ * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
+ * The result mesh shares or not the node coordinates array with \a this mesh depending
+ * on \a keepCoords parameter.
+ * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
+ * to write this mesh to the MED file, its cells must be sorted using
+ * sortCellsInMEDFileFrmt().
+ * \param [in] begin - an array of cell ids to include to the new mesh.
+ * \param [in] end - a pointer to last-plus-one-th element of \a begin.
+ * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
+ * array of \a this mesh, else "free" nodes are removed from the result mesh
+ * by calling zipCoords().
+ * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
+ * to delete this mesh using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If any cell id in the array \a begin is not valid.
+ *
+ * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
*/
MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
{
if(getMeshDimension()!=-1)
- {
- MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
- if(!keepCoords)
- ret->zipCoords();
- return ret;
- }
+ return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
else
{
if(end-begin!=1)
/*!
* This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
*
- * 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.
- * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
+ * 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.
+ * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
* The number of cells of \b this will remain the same with this method.
*
* \param [in] begin begin of cell ids (included) of cells in this to assign
* \param [in] end end of cell ids (excluded) of cells in this to assign
- * \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).
+ * \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 ).
* Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
*/
void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
}
}
-DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
-{
- DataArrayInt *cellIdsKept=0;
- fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
- cellIdsKept->setName(getName());
- return cellIdsKept;
-}
-
/*!
- * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
+ * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
* The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
- * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
- * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
+ * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
+ * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
*
* \param [in] begin input start of array of node ids.
* \param [in] end input end of array of node ids.
- * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
+ * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
* \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
*/
void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
}
/*!
- * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
- */
-DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
-{
- DataArrayInt *cellIdsKept=0;
- fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
- cellIdsKept->setName(getName());
- return cellIdsKept;
-}
-
-/*!
- * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
- * The return newly allocated mesh will share the same coordinates as 'this'.
- * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
- * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
- */
-MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
-{
- DataArrayInt *cellIdsKept=0;
- fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
- return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
-}
-
-/*!
- * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
- * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
- * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
- * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
+ * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
+ * this->getMeshDimension(), that bound some cells of \a this mesh.
+ * The cells of lower dimension to include to the result mesh are selected basing on
+ * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
+ * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
+ * ==\c false, a cell is copied if any its node is in the array of node ids. The
+ * created mesh shares the node coordinates array with \a this mesh.
+ * \param [in] begin - the array of node ids.
+ * \param [in] end - a pointer to the (last+1)-th element of \a begin.
+ * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
+ * array \a begin are added, else cells whose any node is in the
+ * array \a begin are added.
+ * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
+ * to delete this mesh using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If any node id in \a begin is not valid.
+ *
+ * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
*/
MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
{
}
/*!
- * This method returns a mesh with meshDim=this->getMeshDimension()-1.
- * This returned mesh contains cells that are linked with one and only one cell of this.
- * @param keepCoords specifies if ParaMEDMEM::MEDCouplingUMesh::zipCoords is called on returned mesh before being returned. If true zipCoords is \b NOT called, if false, zipCoords is called.
- * @return mesh with ref counter equal to 1.
+ * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
+ * this->getMeshDimension(), which bound only one cell of \a this mesh.
+ * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
+ * array of \a this mesh, else "free" nodes are removed from the result mesh
+ * by calling zipCoords().
+ * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
+ * to delete this mesh using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
*/
MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
{
/*!
* This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
* A cell is detected to be on boundary if it contains one or more than one face having only one father.
- * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown.
+ * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
*/
DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
- * The returned nodes ids are those lying on the boundary of \b this.
+ * Finds nodes lying on the boundary of \a this mesh.
+ * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
+ * nodes. The caller is to delete this array using decrRef() as it is no
+ * more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is node defined.
+ *
+ * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
+ * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
*/
DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
{
return const_cast<MEDCouplingUMesh *>(this);
}
-/*
- * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
- * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
- * This value is asked because often known by the caller of this method.
- * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
- *
- * @param newNodeNumbers array specifying the new numbering in old2New convention.
- * @param newNbOfNodes the new number of nodes.
- */
-void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
-{
- MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
- renumberNodesInConn(newNodeNumbers);
-}
-
-/*
- * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
- * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
- * This value is asked because often known by the caller of this method.
- * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
- * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
- *
- * @param newNodeNumbers array specifying the new numbering.
- * @param newNbOfNodes the new number of nodes.
- *
- */
-void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
-{
- MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
- renumberNodesInConn(newNodeNumbers);
-}
-
/*!
* This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
* otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
/*!
* This method operates a modification of the connectivity and coords in \b this.
- * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
+ * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
* its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
* 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
* renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
}
/*!
- * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
- * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
- * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
- * @param [in] newNodeNumbers in old2New convention
+ * Changes ids of nodes within the nodal connectivity arrays according to a permutation
+ * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
+ * This method is a generalization of shiftNodeNumbersInConn().
+ * \warning This method performs no check of validity of new ids. **Use it with care !**
+ * \param [in] newNodeNumbersO2N - a permutation array, of length \a
+ * this->getNumberOfNodes(), in "Old to New" mode.
+ * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
+ * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
*/
void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
{
* This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
* This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
*
- * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
+ * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
*/
void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
{
/*!
* This method operates a modification of the connectivity in \b this.
* 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.
- * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this
+ * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
* its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
* 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
* renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
*
* \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
* \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
- * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd).
+ * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
*/
void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
+ * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
*
* Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
* After the call of this method the number of cells remains the same as before.
*
- * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
- * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
+ * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
+ * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
* be strictly in [0;this->getNumberOfCells()).
*
- * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
- * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
+ * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
+ * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
* should be contained in[0;this->getNumberOfCells()).
*
* \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
//
const int *conn=_nodal_connec->getConstPointer();
const int *connI=_nodal_connec_index->getConstPointer();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
+ const int *n2oPtr=n2o->begin();
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
newConn->copyStringInfoFrom(*_nodal_connec);
newCI[0]=loc;
for(int i=0;i<nbCells;i++)
{
- std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
+ int pos=n2oPtr[i];
int nbOfElts=connI[pos+1]-connI[pos];
newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
loc+=nbOfElts;
//
setConnectivity(newConn,newConnI);
if(check)
- delete [] const_cast<int *>(array);
-}
-
-/*!
- * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
- * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
- * added in 'elems' parameter.
+ free(const_cast<int *>(array));
+}
+
+/*!
+ * Finds cells whose bounding boxes intersect a given bounding box.
+ * \param [in] bbox - an array defining the bounding box via coordinates of its
+ * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
+ * zMax (if in 3D).
+ * \param [in] eps - a factor used to increase size of the bounding box of cell
+ * before comparing it with \a bbox. This factor is multiplied by the maximal
+ * extent of the bounding box of cell to produce an addition to this bounding box.
+ * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
+ * cells. The caller is to delete this array using decrRef() as it is no more
+ * needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
+ * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
*/
DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
{
}
/*!
- * Returns the cell type of cell with id 'cellId'.
+ * Returns a type of a cell by its id.
+ * \param [in] cellId - the id of the cell of interest.
+ * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
+ * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
*/
INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
{
/*!
* This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
+ * This method does not throw exception if geometric type \a type is not in \a this.
* This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
* The coordinates array is not considered here.
*
}
/*!
- * Returns nb of cells having the geometric type 'type'.
+ * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
*/
int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
{
}
/*!
- * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
- * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
- * That is to say -1 separator is omitted in returned conn.
+ * Returns the nodal connectivity of a given cell.
+ * The separator of faces within polyhedron connectivity (-1) is not returned, thus
+ * all returned node ids can be used in getCoordinatesOfNode().
+ * \param [in] cellId - an id of the cell of interest.
+ * \param [in,out] conn - a vector where the node ids are appended. It is not
+ * cleared before the appending.
+ * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
*/
void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
{
double tt=getTime(tmpp1,tmpp2);
ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
- ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
+ if(_mesh_dim>=-1)
+ { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
+ else
+ { ret << " Mesh dimension has not been set or is invalid !"; }
if(_coords!=0)
{
const int spaceDim=getSpaceDimension();
}
/*!
- * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
+ * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
* This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
* but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
* some algos).
*
- * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
- * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
+ * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
+ * 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
* with number of tuples set to 0, if not the array is taken as this in the returned instance.
*/
MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
int mdim=getMeshDimension();
if(mdim<0)
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
bool needToCpyCT=true;
if(!_nodal_connec)
}
/*!
- * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
- * This method avoids to compute explicitely submesh to get its types.
+ * Returns types of cells of the specified part of \a this mesh.
+ * This method avoids computing sub-mesh explicitely to get its types.
+ * \param [in] begin - an array of cell ids of interest.
+ * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
+ * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
+ * describing the cell types.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \sa getAllTypes()
*/
std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * Method reserved for advanced users having prepared their connectivity before.
- * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
+ * Defines the nodal connectivity using given connectivity arrays. Optionally updates
+ * a set of types of cells constituting \a this mesh.
+ * This method is for advanced users having prepared their connectivity before. For
+ * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
+ * \param [in] conn - the nodal connectivity array.
+ * \param [in] connIndex - the nodal connectivity index array.
+ * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
+ * mesh is updated.
*/
void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
{
}
/*!
- * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
+ * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
* If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
*/
MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
}
/*!
- * This method recomputes all cell types of 'this'.
+ * Recomputes a set of cell types of \a this mesh. For more info see
+ * \ref MEDCouplingUMeshNodalConnectivity.
*/
void MEDCouplingUMesh::computeTypes()
{
throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
}
+/*!
+ * Returns a number of cells constituting \a this mesh.
+ * \return int - the number of cells in \a this mesh.
+ * \throw If the nodal connectivity of cells is not defined.
+ */
int MEDCouplingUMesh::getNumberOfCells() const
{
if(_nodal_connec_index)
throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
}
+/*!
+ * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
+ * mesh. For more info see \ref MEDCouplingMeshesPage.
+ * \return int - the dimension of \a this mesh.
+ * \throw If the mesh dimension is not defined using setMeshDimension().
+ */
int MEDCouplingUMesh::getMeshDimension() const
{
if(_mesh_dim<-1)
}
/*!
- * This method is for test reason. Normally the integer returned is not useable by user.
+ * Returns a length of the nodal connectivity array.
+ * This method is for test reason. Normally the integer returned is not useable by
+ * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
+ * \return int - the length of the nodal connectivity array.
*/
int MEDCouplingUMesh::getMeshLength() const
{
/*!
* Second step of serialization process.
- * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
+ * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
*/
void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
{
/*!
* Second and final unserialization process.
- * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
+ * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
*/
void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
{
* This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
* CellIds are given using range specified by a start an end and step.
*/
-MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
+MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
{
checkFullyDefined();
int ncell=getNumberOfCells();
/*!
* This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
- * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
- * The return newly allocated mesh will share the same coordinates as 'this'.
+ * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
+ * The return newly allocated mesh will share the same coordinates as \a this.
*/
-MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
+MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
{
- checkFullyDefined();
+ checkConnectivityFullyDefined();
int ncell=getNumberOfCells();
MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
ret->_mesh_dim=_mesh_dim;
ret->setCoords(_coords);
std::size_t nbOfElemsRet=std::distance(begin,end);
- int *connIndexRet=new int[nbOfElemsRet+1];
+ int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
connIndexRet[0]=0;
const int *conn=_nodal_connec->getConstPointer();
const int *connIndex=_nodal_connec_index->getConstPointer();
connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
else
{
- delete [] connIndexRet;
+ free(connIndexRet);
std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
throw INTERP_KERNEL::Exception(oss.str().c_str());
}
}
- int *connRet=new int[connIndexRet[nbOfElemsRet]];
+ int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
int *connRetWork=connRet;
std::set<INTERP_KERNEL::NormalizedCellType> types;
for(const int *work=begin;work!=end;work++)
connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
}
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
- connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
+ connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
- connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
+ connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
ret->setConnectivity(connRetArr,connIndexRetArr,false);
ret->_types=types;
ret->copyTinyInfoFrom(this);
}
/*!
- * brief returns the volumes of the cells underlying the field \a field
- *
- * For 2D geometries, the returned field contains the areas.
- * For 3D geometries, the returned field contains the volumes.
- *
- * param field field on which cells the volumes are required
- * return field containing the volumes, area or length depending the meshdimension.
+ * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
+ * mesh.<br>
+ * For 1D cells, the returned field contains lengths.<br>
+ * For 2D cells, the returned field contains areas.<br>
+ * For 3D cells, the returned field contains volumes.
+ * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
+ * orientation, i.e. the volume is always positive.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
+ * and one time . The caller is to delete this field using decrRef() as it is no
+ * more needed.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
{
}
/*!
- * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
- * This method avoids to build explicitely part of this to perform the work.
+ * Returns a new DataArrayDouble containing volumes of specified cells of \a this
+ * mesh.<br>
+ * For 1D cells, the returned array contains lengths.<br>
+ * For 2D cells, the returned array contains areas.<br>
+ * For 3D cells, the returned array contains volumes.
+ * This method avoids building explicitly a part of \a this mesh to perform the work.
+ * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
+ * orientation, i.e. the volume is always positive.
+ * \param [in] begin - an array of cell ids of interest.
+ * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
+ * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
+ * delete this array using decrRef() as it is no more needed.
+ *
+ * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
+ * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
+ * \sa getMeasureField()
*/
DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
{
}
/*!
- * This methods returns a field on nodes and no time. This method is useful to check "P1*" conservative interpolators.
- * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
+ * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
+ * \a this one. The returned field contains the dual cell volume for each corresponding
+ * node in \a this mesh. In other words, the field returns the getMeasureField() of
+ * the dual mesh in P1 sens of \a this.<br>
+ * For 1D cells, the returned field contains lengths.<br>
+ * For 2D cells, the returned field contains areas.<br>
+ * For 3D cells, the returned field contains volumes.
+ * This method is useful to check "P1*" conservative interpolators.
+ * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
+ * orientation, i.e. the volume is always positive.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * nodes and one time. The caller is to delete this array using decrRef() as
+ * it is no more needed.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
{
}
/*!
- * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
- * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
+ * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
+ * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
+ * The computed vectors have <em> this->getMeshDimension()+1 </em> components
+ * and are normalized.
+ * <br> \a this can be either
+ * - a 2D mesh in 2D or 3D space or
+ * - an 1D mesh in 2D space.
+ *
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * cells and one time. The caller is to delete this field using decrRef() as
+ * it is no more needed.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the coordinates array is not set.
+ * \throw If the mesh dimension is not set.
+ * \throw If the mesh and space dimension is not as specified above.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
{
}
/*!
- * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
- * This method avoids to build explicitely part of this to perform the work.
+ * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
+ * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
+ * and are normalized.
+ * <br> \a this can be either
+ * - a 2D mesh in 2D or 3D space or
+ * - an 1D mesh in 2D space.
+ *
+ * This method avoids building explicitly a part of \a this mesh to perform the work.
+ * \param [in] begin - an array of cell ids of interest.
+ * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * cells and one time. The caller is to delete this field using decrRef() as
+ * it is no more needed.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the coordinates array is not set.
+ * \throw If the mesh dimension is not set.
+ * \throw If the mesh and space dimension is not as specified above.
+ * \sa buildOrthogonalField()
+ *
+ * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
+ * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
{
}
/*!
- * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
- * This method is only callable on mesh with meshdim == 1 containing only SEG2.
+ * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
+ * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
+ * and are \b not normalized.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * cells and one time. The caller is to delete this field using decrRef() as
+ * it is no more needed.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this->getMeshDimension() != 1.
+ * \throw If \a this mesh includes cells of type other than SEG2.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
{
}
/*!
- * This method expects that 'this' is fully defined and has a spaceDim==3 and a meshDim==3. If it is not the case an exception will be thrown.
- * This method returns 2 objects :
- * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
- * - a newly created dataarray having number of tuples equal to the number of cells in returned mesh that tells for each 2D cell in returned
- * mesh the 3D cell id is 'this' it comes from.
- * This method works only for linear meshes (non quadratic).
- * If plane crosses within 'eps' a face in 'this' shared by more than 1 cell, 2 output faces will be generated. The 2 faces having the same geometry than intersecting
- * face. Only 'cellIds' parameter can distinguish the 2.
- * @param origin is the origin of the plane. It should be an array of length 3.
- * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
- * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
- * also used to state if new points should be created or already existing points are reused. 'eps' is also used to tells if plane overlaps a face, edge or nodes (in absolute).
+ * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
+ * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
+ * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
+ * from. If a result face is shared by two 3D cells, then the face in included twice in
+ * the result mesh.
+ * \param [in] origin - 3 components of a point defining location of the plane.
+ * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
+ * must be greater than 1e-6.
+ * \param [in] eps - half-thickness of the plane.
+ * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
+ * producing correspondent 2D cells. The caller is to delete this array
+ * using decrRef() as it is no more needed.
+ * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
+ * not share the node coordinates array with \a this mesh. The caller is to
+ * delete this mesh using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
+ * \throw If magnitude of \a vec is less than 1e-6.
+ * \throw If the plane does not intersect any 3D cell of \a this mesh.
+ * \throw If \a this includes quadratic cells.
*/
MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method expects that 'this' is fully defined and has a spaceDim==3 and a meshDim==2. If it is not the case an exception will be thrown.
- * This method returns 2 objects :
- * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
- * - a newly created dataarray having number of tuples equal to the number of cells in returned mesh that tells for each 2D cell in returned
- * mesh the 3DSurf cell id is 'this' it comes from.
- * This method works only for linear meshes (non quadratic).
- * If plane crosses within 'eps' a face in 'this' shared by more than 1 cell, 2 output faces will be generated. The 2 faces having the same geometry than intersecting
- * face. Only 'cellIds' parameter can distinguish the 2.
- * @param origin is the origin of the plane. It should be an array of length 3.
- * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
- * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
- * also used to state if new points should be created or already existing points are reused. 'eps' is also used to tells if plane overlaps a face, edge or nodes (in absolute).
+ * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
+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
+from. If a result segment is shared by two 2D cells, then the segment in included twice in
+the result mesh.
+ * \param [in] origin - 3 components of a point defining location of the plane.
+ * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
+ * must be greater than 1e-6.
+ * \param [in] eps - half-thickness of the plane.
+ * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
+ * producing correspondent segments. The caller is to delete this array
+ * using decrRef() as it is no more needed.
+ * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
+ * mesh in 3D space. This mesh does not share the node coordinates array with
+ * \a this mesh. The caller is to delete this mesh using decrRef() as it is
+ * no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
+ * \throw If magnitude of \a vec is less than 1e-6.
+ * \throw If the plane does not intersect any 2D cell of \a this mesh.
+ * \throw If \a this includes quadratic cells.
*/
MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
- * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
- * @param origin is the origin of the plane. It should be an array of length 3.
- * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
+ * Finds cells whose bounding boxes intersect a given plane.
+ * \param [in] origin - 3 components of a point defining location of the plane.
+ * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
+ * must be greater than 1e-6.
+ * \param [in] eps - half-thickness of the plane.
+ * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
+ * cells. The caller is to delete this array using decrRef() as it is no more
+ * needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If \a this->getSpaceDimension() != 3.
+ * \throw If magnitude of \a vec is less than 1e-6.
+ * \sa buildSlice3D()
*/
DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
+ * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
* If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
* No consideration of coordinate is done by this method.
* 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)
/*!
* This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
* This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
- * @param pt reference point of the line
- * @param v normalized director vector of the line
- * @param eps max precision before throwing an exception
- * @param res output of size this->getNumberOfCells
+ * \param pt reference point of the line
+ * \param v normalized director vector of the line
+ * \param eps max precision before throwing an exception
+ * \param res output of size this->getNumberOfCells
*/
void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
{
}
/*!
- * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance.
+ * 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.
* \a this is expected to be a mesh so that its space dimension is equal to its
* mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
* 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).
- *
- * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found
- * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked
- * to the node that minimizes distance with the input point then -1 is returned in cellId.
+
+ * 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
+ * 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).
+ * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
*
* So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
* If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
* \return the positive value of the distance.
* \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
* dimension - 1.
- * \sa DataArrayDouble::distanceToTuple
+ * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
*/
-double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
+double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
{
int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
if(meshDim!=spaceDim-1)
checkFullyDefined();
if((int)std::distance(ptBg,ptEnd)!=spaceDim)
{ 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()); }
- nodeId=-1;
- double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
- if(nodeId==-1)
- throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
- switch(meshDim)
+ DataArrayInt *ret1=0;
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
+ cellId=*ret1Safe->begin();
+ return *ret0->begin();
+}
+
+/*!
+ * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
+ * to \a this and the first \a cellId in \a this corresponding to the returned distance.
+ * 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
+ * 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).
+ * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
+ *
+ * \a this is expected to be a mesh so that its space dimension is equal to its
+ * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
+ * 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).
+ *
+ * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
+ * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
+ *
+ * \param [in] pts the list of points in which each tuple represents a point
+ * \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.
+ * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
+ * \throw if number of components of \a pts is not equal to the space dimension.
+ * \throw if mesh dimension of \a this is not equal to space dimension - 1.
+ * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
+ */
+DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
+{
+ if(!pts)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
+ pts->checkAllocated();
+ int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
+ if(meshDim!=spaceDim-1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
+ if(meshDim!=2 && meshDim!=1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
+ if(pts->getNumberOfComponents()!=spaceDim)
{
- case 2:
+ std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ checkFullyDefined();
+ int nbCells=getNumberOfCells();
+ if(nbCells==0)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
+ int nbOfPts=pts->getNumberOfTuples();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
+ const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
+ double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
+ std::vector<double> bbox;
+ getBoundingBoxForBBTree(bbox);
+ switch(spaceDim)
+ {
+ case 3:
{
- distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
- return ret0;
+ BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
+ for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
+ {
+ double x=std::numeric_limits<double>::max();
+ std::vector<int> elems;
+ myTree.getMinDistanceOfMax(ptsPtr,x);
+ myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
+ DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
+ }
+ break;
}
- case 1:
+ case 2:
{
- distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
- return ret0;
+ BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
+ for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
+ {
+ double x=std::numeric_limits<double>::max();
+ std::vector<int> elems;
+ myTree.getMinDistanceOfMax(ptsPtr,x);
+ myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
+ DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
+ }
+ break;
}
default:
- throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
}
-
- return ret0;
+ cellIds=ret1.retn();
+ return ret0.retn();
}
-
/*!
* \param [in] pt the start pointer (included) of the coordinates of the point
- * \param [in] cellIds
+ * \param [in] cellIdsBg the start pointer (included) of cellIds
+ * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
+ * \param [in] nc nodal connectivity
+ * \param [in] ncI nodal connectivity index
* \param [in,out] ret0 the min distance between \a this and the external input point
* \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
- * \sa MEDCouplingUMesh::distanceToPoint
+ * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
*/
-void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
+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) throw(INTERP_KERNEL::Exception)
{
- const double *coords=_coords->getConstPointer();
- cellId=-1;
- if(cellIds->empty())
- return;
- const int *ptr=_nodal_connec->getConstPointer();
- const int *ptrI=_nodal_connec_index->getConstPointer();
- for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
+ cellId=-1;
+ ret0=std::numeric_limits<double>::max();
+ for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
{
- switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
+ switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
{
case INTERP_KERNEL::NORM_TRI3:
{
- double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
+ double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
if(tmp<ret0)
{ ret0=tmp; cellId=*zeCell; }
break;
case INTERP_KERNEL::NORM_QUAD4:
case INTERP_KERNEL::NORM_POLYGON:
{
- double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
+ double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
if(tmp<ret0)
{ ret0=tmp; cellId=*zeCell; }
break;
/*!
* \param [in] pt the start pointer (included) of the coordinates of the point
- * \param [in] cellIds
+ * \param [in] cellIdsBg the start pointer (included) of cellIds
+ * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
+ * \param [in] nc nodal connectivity
+ * \param [in] ncI nodal connectivity index
* \param [in,out] ret0 the min distance between \a this and the external input point
* \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
- * \sa MEDCouplingUMesh::distanceToPoint
+ * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
*/
-void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
+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) throw(INTERP_KERNEL::Exception)
{
- const double *coords=_coords->getConstPointer();
- if(cellIds->empty())
- { cellId=-1; return; }
- const int *ptr=_nodal_connec->getConstPointer();
- const int *ptrI=_nodal_connec_index->getConstPointer();
- for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
+ cellId=-1;
+ ret0=std::numeric_limits<double>::max();
+ for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
{
- switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
+ switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
{
case INTERP_KERNEL::NORM_SEG2:
{
- double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
- if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
+ std::size_t uselessEntry=0;
+ double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
+ tmp=sqrt(tmp);
if(tmp<ret0)
{ ret0=tmp; cellId=*zeCell; }
break;
}
/*!
- * Returns a cell if any that contains the point located on 'pos' with precison eps.
- * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
- * \b Warning this method is good if the caller intends to evaluate only one point. But if more than one point is requested on 'this'
- * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
+ * Finds cells in contact with a ball (i.e. a point with precision).
+ * \warning This method is suitable if the caller intends to evaluate only one
+ * point, for more points getCellsContainingPoints() is recommended as it is
+ * faster.
+ * \param [in] pos - array of coordinates of the ball central point.
+ * \param [in] eps - ball radius.
+ * \return int - a smallest id of cells being in contact with the ball, -1 in case
+ * if there are no such cells.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
*/
int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
{
}
/*!
- * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
- * \b Warning this method is good if the caller intends to evaluate only one point. But if more than one point is requested on 'this'
- * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
+ * Finds cells in contact with a ball (i.e. a point with precision).
+ * \warning This method is suitable if the caller intends to evaluate only one
+ * point, for more points getCellsContainingPoints() is recommended as it is
+ * faster.
+ * \param [in] pos - array of coordinates of the ball central point.
+ * \param [in] eps - ball radius.
+ * \param [in,out] elts - vector returning ids of the found cells. It is cleared
+ * before inserting ids.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
+ *
+ * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
+ * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
*/
void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
{
}
}
}
-
/*!
- * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
- * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
- * in case of multi points searching.
- * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
- * For point j in [0,nbOfPoints), (eltsIndex[j+1]-eltsIndex[j]) cells contain this point. These cells are : [elts.begin()+eltsIndex[j],elts.begin():eltsIndex[j+1]).
- *
- * \param pos input parameter that points to an array of size 'getSpaceDim()*nbOfPoints' points stored in full interlace mode : X0,Y0,Z0,X1,Y1,Z1...
+ * Finds cells in contact with several balls (i.e. points with precision).
+ * This method is an extension of getCellContainingPoint() and
+ * getCellsContainingPoint() for the case of multiple points.
+ * \param [in] pos - an array of coordinates of points in full interlace mode :
+ * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
+ * this->getSpaceDimension() * \a nbOfPoints
+ * \param [in] nbOfPoints - number of points to locate within \a this mesh.
+ * \param [in] eps - radius of balls (i.e. the precision).
+ * \param [in,out] elts - vector returning ids of found cells.
+ * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
+ * dividing cell ids in \a elts into groups each referring to one
+ * point. Its every element (except the last one) is an index pointing to the
+ * first id of a group of cells. For example cells in contact with the *i*-th
+ * point are described by following range of indices:
+ * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
+ * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
+ * Number of cells in contact with the *i*-th point is
+ * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
+ * \throw If the coordinates array is not set.
+ * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
+ *
+ * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
+ * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
*/
void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
std::vector<int>& elts, std::vector<int>& eltsIndex) const
}
/*!
- * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
- * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
- * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
- * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
+ * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
+ * least two its edges intersect each other anywhere except their extremities. An
+ * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
+ * \param [in,out] cells - a vector returning ids of the found cells. It is not
+ * cleared before filling in.
+ * \param [in] eps - precision.
+ * \throw If \a this->getMeshDimension() != 2.
+ * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
*/
void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
{
* 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)
* 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.
*
- * @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.
+ * \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.
*/
DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method is \b NOT const because it can modify 'this'.
- * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
- * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
- * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
+ * This method is \b NOT const because it can modify \a this.
+ * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
+ * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
+ * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
* \b 1 for translation and rotation around point of 'mesh1D'.
- * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.
+ * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
*/
MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
{
/*!
* This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
* If it is not the case an exception will be thrown.
- * This method is non const because the coordinate of 'this' can be appended with some new points issued from
+ * This method is non const because the coordinate of \a this can be appended with some new points issued from
* intersection of plane defined by ('origin','vec').
* This method has one in/out parameter : 'cut3DCurve'.
* Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
- * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
+ * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
* if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
- * This method will throw an exception if 'this' contains a non linear segment.
+ * This method will throw an exception if \a this contains a non linear segment.
*/
void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
{
/*!
* This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
- * @param mesh1D is the input 1D mesh used for translation computation.
- * @return newCoords new coords filled by this method.
+ * \param mesh1D is the input 1D mesh used for translation computation.
+ * \return newCoords new coords filled by this method.
*/
DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
{
/*!
* This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
- * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
- * @return newCoords new coords filled by this method.
+ * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
+ * \return newCoords new coords filled by this method.
*/
DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
{
/*!
* This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
- * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
- * @return newCoords new coords filled by this method.
+ * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
+ * \return newCoords new coords filled by this method.
*/
DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
{
/*!
* This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
- * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
- * @return newCoords new coords filled by this method.
+ * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
+ * \return newCoords new coords filled by this method.
*/
DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
{
* This method is private because not easy to use for end user. This method is const contrary to
* MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
* the coords sorted slice by slice.
- * @param isQuad specifies presence of quadratic cells.
+ * \param isQuad specifies presence of quadratic cells.
*/
MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
{
}
/*!
- * This method returns if 'this' is constituted by only quadratic cells.
+ * Checks if \a this mesh is constituted by only quadratic cells.
+ * \return bool - \c true if there are only quadratic cells in \a this mesh.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
*/
bool MEDCouplingUMesh::isFullyQuadratic() const
{
}
/*!
- * This method returns if there is at least one quadratic cell.
+ * Checks if \a this mesh includes any quadratic cell.
+ * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
*/
bool MEDCouplingUMesh::isPresenceOfQuadratic() const
{
}
/*!
- * This method convert quadratic cells to linear cells if any was found.
- * If no such cells exists 'this' remains unchanged.
+ * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
+ * this mesh, it remains unchanged.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
*/
void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
{
checkFullyDefined();
int nbOfCells=getNumberOfCells();
int delta=0;
+ const int *iciptr=_nodal_connec_index->getConstPointer();
for(int i=0;i<nbOfCells;i++)
{
INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
{
INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
- delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
+ if(!cml.isDynamic())
+ delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
+ else
+ delta+=(iciptr[i+1]-iciptr[i]-1)/2;
}
}
if(delta==0)
return ;
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
+ const int *icptr=_nodal_connec->getConstPointer();
newConn->alloc(getMeshLength()-delta,1);
newConnI->alloc(nbOfCells+1,1);
- const int *icptr=_nodal_connec->getConstPointer();
- const int *iciptr=_nodal_connec_index->getConstPointer();
int *ocptr=newConn->getPointer();
int *ociptr=newConnI->getPointer();
*ociptr=0;
_types.insert(typel);
const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
int newNbOfNodes=cml.getNumberOfNodes();
+ if(cml.isDynamic())
+ newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
*ocptr++=(int)typel;
ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
ociptr[1]=ociptr[0]+newNbOfNodes+1;
}
/*!
- * This method tessallates 'this' so that the number of cells remains the same.
- * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
- * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
- *
- * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
- * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
+ * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
+ * so that the number of cells remains the same. Quadratic faces are converted to
+ * polygons. This method works only for 2D meshes in
+ * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
+ * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
+ * \warning This method can lead to a huge amount of nodes if \a eps is very low.
+ * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
+ * a polylinized edge constituting the input polygon.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If \a this->getMeshDimension() != 2.
+ * \throw If \a this->getSpaceDimension() != 2.
*/
void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method tessallates 'this' so that the number of cells remains the same.
- * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
- * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
- *
- * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
- * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
+ * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
+ * \warning This method can lead to a huge amount of nodes if \a eps is very low.
+ * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
+ * a sub-divided edge.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If \a this->getMeshDimension() != 1.
+ * \throw If \a this->getSpaceDimension() != 2.
*/
void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
- * This cut into simplex is performed following the parameter \a policy. This method so typically increases the number of cells of \a this.
- * This method \b keeps the number of nodes \b unchanged. That's why the splitting policy in 3D INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
- * This method returns new2old newly allocated array that specifies a each cell of \a this after the call what was its id it comes.
- *
- * The semantic of \a policy parameter :
- * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
- * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
- * - PLANAR_FACE_5 only HEXA8. All HEXA8 are split into 5 TETRA4
- * - PLANAR_FACE_6 only HEXA8. All HEXA8 are split into 6 TETRA4
+ * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
+ * In addition, returns an array mapping new cells to old ones. <br>
+ * This method typically increases the number of cells in \a this mesh
+ * but the number of nodes remains \b unchanged.
+ * That's why the 3D splitting policies
+ * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
+ * \param [in] policy - specifies a pattern used for splitting.
+ * The semantic of \a policy is:
+ * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
+ * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
+ * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
+ * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
+ * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
+ * an id of old cell producing it. The caller is to delete this array using
+ * decrRef() as it is no more needed.
+ * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
+ * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
+ * and \a this->getMeshDimension() != 3.
+ * \throw If \a policy is not one of the four discussed above.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \sa MEDCouplingUMesh::tetrahedrize
*/
DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
{
}
}
+/*!
+ * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
+ * - 1D: INTERP_KERNEL::NORM_SEG2
+ * - 2D: INTERP_KERNEL::NORM_TRI3
+ * - 3D: INTERP_KERNEL::NORM_TETRA4.
+ *
+ * This method is useful for users that need to use P1 field services as
+ * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
+ * All these methods need mesh support containing only simplex cells.
+ * \return bool - \c true if there are only simplex cells in \a this mesh.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If \a this->getMeshDimension() < 1.
+ */
bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
{
checkFullyDefined();
- if(getMeshDimension()<1)
- throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
+ int mdim=getMeshDimension();
+ if(mdim<1 || mdim>3)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
int nbCells=getNumberOfCells();
const int *conn=_nodal_connec->getConstPointer();
const int *connI=_nodal_connec_index->getConstPointer();
}
/*!
- * This private method is used to subdivide edges of a mesh with meshdim==2. If 'this' has no a meshdim equal to 2 an exception will be thrown.
+ * 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.
* This method completly ignore coordinates.
- * @param nodeSubdived is the nodal connectivity of subdivision of edges
- * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
- * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
- * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
+ * \param nodeSubdived is the nodal connectivity of subdivision of edges
+ * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
+ * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
+ * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
*/
void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
- * nodal connectivity will be transform to a NORM_TRI3 cell.
- * This method works \b only \b on \b linear cells.
- * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
- * method could be useful before calling this method in case of presence of several pair of nodes located on same position.
- * This method throws an exception if 'this' is not fully defined (connectivity).
- * This method throws an exception too if a "too" degenerated cell is detected. For example a NORM_TRI3 with 3 times the same node id.
+ * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
+ * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
+ * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
+ * does \b not perform geometrical checks and checks only nodal connectivity of cells,
+ * so it can be useful to call mergeNodes() before calling this method.
+ * \throw If \a this->getMeshDimension() <= 1.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
*/
void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
- * The 'vec' vector has to have a non nul norm.
- * If not 'cells' parameter will be appended with cellIds of incorrect cells.
- * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
+ * Finds incorrectly oriented cells of this 2D mesh in 3D space.
+ * A cell is considered to be oriented correctly if an angle between its
+ * normal vector and a given vector is less than \c PI / \c 2.
+ * \param [in] vec - 3 components of the vector specifying the correct orientation of
+ * cells.
+ * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
+ * checked.
+ * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
+ * is not cleared before filling in.
+ * \throw If \a this->getMeshDimension() != 2.
+ * \throw If \a this->getSpaceDimension() != 3.
+ *
+ * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
+ * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
*/
void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
- * The 'vec' vector has to have a non nul norm.
- * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
+ * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
+ * considered to be oriented correctly if an angle between its normal vector and a
+ * given vector is less than \c PI / \c 2.
+ * \param [in] vec - 3 components of the vector specifying the correct orientation of
+ * cells.
+ * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
+ * checked.
+ * \throw If \a this->getMeshDimension() != 2.
+ * \throw If \a this->getSpaceDimension() != 3.
+ *
+ * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
+ * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
*/
void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method checks that all polyhedrons cells have correctly oriented faces.
- * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
- * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
+ * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
+ * oriented facets. The normal vector of the facet should point out of the cell.
+ * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
+ * is not cleared before filling in.
+ * \throw If \a this->getMeshDimension() != 3.
+ * \throw If \a this->getSpaceDimension() != 3.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
+ * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
*/
void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method tries to orient correctly polhedrons cells.
- *
- * \throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
+ * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
+ * out of the cell.
+ * \throw If \a this->getMeshDimension() != 3.
+ * \throw If \a this->getSpaceDimension() != 3.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \throw If the reparation fails.
+ *
+ * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
+ * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
* \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
*/
void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
}
/*!
- * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
- * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
- * If some extruded cells does not fulfill the MED norm for extruded cells (first face of 3D cell should be oriented to the exterior of the 3D cell).
- * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
+ * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
+ * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
+ * according to which the first facet of the cell should be oriented to have the normal vector
+ * pointing out of cell.
+ * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
+ * cells. The caller is to delete this array using decrRef() as it is no more
+ * needed.
+ * \throw If \a this->getMeshDimension() != 3.
+ * \throw If \a this->getSpaceDimension() != 3.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
*
- * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
+ * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
+ * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
* \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
*/
DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
/*!
* This method has a sense for meshes with spaceDim==3 and meshDim==2.
* If it is not the case an exception will be thrown.
- * This method is fast because the first cell of 'this' is used to compute the plane.
- * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
- * @param pos output of size at least 3 used to store a point owned of searched plane.
+ * This method is fast because the first cell of \a this is used to compute the plane.
+ * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
+ * \param pos output of size at least 3 used to store a point owned of searched plane.
*/
void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * The returned newly created field has to be managed by the caller.
- * This method returns a field on cell with no time lying on 'this'. The meshdimension and spacedimension of this are expected to be both in [2,3]. If not an exception will be thrown.
- * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
- * If a cell has an another type an exception will be thrown.
+ * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
+ * cells. Currently cells of the following types are treated:
+ * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
+ * For a cell of other type an exception is thrown.
+ * Space dimension of a 2D mesh can be either 2 or 3.
+ * The Edge Ratio of a cell \f$t\f$ is:
+ * \f$\frac{|t|_\infty}{|t|_0}\f$,
+ * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
+ * the smallest edge lengths of \f$t\f$.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * cells and one time, lying on \a this mesh. The caller is to delete this
+ * field using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
+ * \throw If the connectivity data array has more than one component.
+ * \throw If the connectivity data array has a named component.
+ * \throw If the connectivity index data array has more than one component.
+ * \throw If the connectivity index data array has a named component.
+ * \throw If \a this->getMeshDimension() is neither 2 nor 3.
+ * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
+ * \throw If \a this mesh includes cells of type different from the ones enumerated above.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * The returned newly created field has to be managed by the caller.
- * This method returns a field on cell with no time lying on 'this'. The meshdimension and spacedimension of this are expected to be both in [2,3]. If not an exception will be thrown.
- * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
- * If a cell has an another type an exception will be thrown.
+ * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
+ * cells. Currently cells of the following types are treated:
+ * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
+ * For a cell of other type an exception is thrown.
+ * Space dimension of a 2D mesh can be either 2 or 3.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * cells and one time, lying on \a this mesh. The caller is to delete this
+ * field using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
+ * \throw If the connectivity data array has more than one component.
+ * \throw If the connectivity data array has a named component.
+ * \throw If the connectivity index data array has more than one component.
+ * \throw If the connectivity index data array has a named component.
+ * \throw If \a this->getMeshDimension() is neither 2 nor 3.
+ * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
+ * \throw If \a this mesh includes cells of type different from the ones enumerated above.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * The returned newly created field has to be managed by the caller.
- * This method returns a field on cell with no time lying on 'this'. The meshdimension must be equal to 2 and the spacedimension must be equal to 3. If not an exception will be thrown.
- * This method for the moment only deals with NORM_QUAD4 geometric type.
- * If a cell has an another type an exception will be thrown.
+ * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
+ * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
+ * treated: INTERP_KERNEL::NORM_QUAD4.
+ * For a cell of other type an exception is thrown.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * cells and one time, lying on \a this mesh. The caller is to delete this
+ * field using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
+ * \throw If the connectivity data array has more than one component.
+ * \throw If the connectivity data array has a named component.
+ * \throw If the connectivity index data array has more than one component.
+ * \throw If the connectivity index data array has a named component.
+ * \throw If \a this->getMeshDimension() != 2.
+ * \throw If \a this->getSpaceDimension() != 3.
+ * \throw If \a this mesh includes cells of type different from the ones enumerated above.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
{
return ret.retn();
}
+
/*!
- * The returned newly created field has to be managed by the caller.
- * This method returns a field on cell with no time lying on 'this'. The meshdimension must be equal to 2 and the spacedimension must be equal to 3. If not an exception will be thrown.
- * This method for the moment only deals with NORM_QUAD4 geometric type.
- * If a cell has an another type an exception will be thrown.
+ * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
+ * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
+ * treated: INTERP_KERNEL::NORM_QUAD4.
+ * For a cell of other type an exception is thrown.
+ * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
+ * cells and one time, lying on \a this mesh. The caller is to delete this
+ * field using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
+ * \throw If the connectivity data array has more than one component.
+ * \throw If the connectivity data array has a named component.
+ * \throw If the connectivity index data array has more than one component.
+ * \throw If the connectivity index data array has a named component.
+ * \throw If \a this->getMeshDimension() != 2.
+ * \throw If \a this->getSpaceDimension() != 3.
+ * \throw If \a this mesh includes cells of type different from the ones enumerated above.
*/
MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
{
/*!
* This method aggregate the bbox of each cell and put it into bbox parameter.
- * @param bbox out parameter of size 2*spacedim*nbOfcells.
+ * \param bbox out parameter of size 2*spacedim*nbOfcells.
*/
void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
{
/// @endcond
/*!
- * This method expects that 'this' is sorted by types. If not an exception will be thrown.
+ * This method expects that \a this is sorted by types. If not an exception will be thrown.
* This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
- * 'this' is composed in cell types.
- * The returned array is of size 3*n where n is the number of different types present in 'this'.
- * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
+ * \a this is composed in cell types.
+ * The returned array is of size 3*n where n is the number of different types present in \a this.
+ * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
* This parameter is kept only for compatibility with other methode listed above.
*/
std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
const int *work=connI;
int nbOfCells=getNumberOfCells();
std::size_t n=getAllTypes().size();
- std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
+ std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
std::set<INTERP_KERNEL::NormalizedCellType> types;
for(std::size_t i=0;work!=connI+nbOfCells;i++)
{
}
/*!
- * This method is used to check that this has contiguous cell type in same order than described in 'code'.
+ * This method is used to check that this has contiguous cell type in same order than described in \a code.
* only for types cell, type node is not managed.
- * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
+ * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
* foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
* 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
- * If 2 or more same geometric type is in 'code' and exception is thrown too.
+ * If 2 or more same geometric type is in \a code and exception is thrown too.
*
* This method firstly checks
* If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
* If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
* an exception is thrown too.
*
- * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
- * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown
+ * If all geometric types in \a code are exactly those in \a this null pointer is returned.
+ * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
* and a DataArrayInt instance is returned that the user has the responsability to deallocate.
*/
DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
std::vector<INTERP_KERNEL::NormalizedCellType> types;
int nb=0;
+ bool isNoPflUsed=true;
for(std::size_t i=0;i<n;i++)
if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
{
nb+=code[3*i+1];
if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
+ isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
}
if(types.size()!=n)
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
- if(idsPerType.empty())
+ if(isNoPflUsed)
{
if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
if(types.size()==_types.size())
return 0;
}
- DataArrayInt *ret=DataArrayInt::New();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
ret->alloc(nb,1);
int *retPtr=ret->getPointer();
const int *connI=_nodal_connec_index->getConstPointer();
{
i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
int offset=(int)std::distance(connI,i);
+ const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
+ int nbOfCellsOfCurType=(int)std::distance(i,j);
if(code[3*kk+2]==-1)
- {
- const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
- std::size_t pos2=std::distance(i,j);
- for(std::size_t k=0;k<pos2;k++)
- *retPtr++=(int)k+offset;
- i=j;
- }
+ for(int k=0;k<nbOfCellsOfCurType;k++)
+ *retPtr++=k+offset;
else
{
- retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
- retPtr,std::bind2nd(std::plus<int>(),offset));
+ int idInIdsPerType=code[3*kk+2];
+ if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
+ {
+ const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
+ if(zePfl)
+ {
+ zePfl->checkAllocated();
+ if(zePfl->getNumberOfComponents()==1)
+ {
+ for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
+ {
+ if(*k>=0 && *k<nbOfCellsOfCurType)
+ *retPtr=(*k)+offset;
+ else
+ {
+ std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
+ oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ }
+ else
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
+ }
+ else
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
+ }
+ else
+ {
+ std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
+ oss << " should be in [0," << idsPerType.size() << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
}
+ i=j;
}
- return ret;
+ return ret.retn();
}
/*!
* This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
* 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.
* 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.
- * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
+ * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
*
- * @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.
- * @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,
+ * \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.
+ * \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,
* \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
- * @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.
+ * \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.
* This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
- * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
+ * \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
*/
void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
{
+ if(!profile)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
if(profile->getNumberOfComponents()!=1)
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
checkConnectivityFullyDefined();
/*!
* This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
- * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
+ * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
* The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
* 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.
*/
}
/*!
- * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
- * It avoids to deal with renum in MEDLoader so it is useful for MED file R/W with multi types.
- * This method returns a newly allocated array old2New.
- * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
+ * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
+ * necessary for writing the mesh to MED file. Additionally returns a permutation array
+ * in "Old to New" mode.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
+ * this array using decrRef() as it is no more needed.
+ * \throw If the nodal connectivity of cells is not defined.
*/
DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
{
checkConnectivityFullyDefined();
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
renumberCells(ret->getConstPointer(),false);
return ret.retn();
}
/*!
* This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
- * that the order is specified in array defined by [orderBg,orderEnd).
+ * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
* If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
* If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
*/
}
/*!
- * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in 'this'.
+ * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
+ *
+ * \return a new object containing the old to new correspondance.
+ *
+ * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
+ */
+DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
+{
+ return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
+}
+
+/*!
+ * 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.
* This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
* The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
* The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
}
/*!
- * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
+ * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
* The number of cells remains unchanged after the call of this method.
* This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
* MEDCouplingUMesh::sortCellsInMEDFileFrmt.
*
- * @return the array giving the correspondance old to new.
+ * \return the array giving the correspondance old to new.
*/
DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
{
}
/*!
- * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
+ * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
* So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
* This method makes asumption that connectivity is correctly set before calling.
*/
std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
{
- checkFullyDefined();
+ checkConnectivityFullyDefined();
const int *conn=_nodal_connec->getConstPointer();
const int *connI=_nodal_connec_index->getConstPointer();
int nbOfCells=getNumberOfCells();
return ret;
}
+/*!
+ * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
+ * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
+ * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
+ *
+ * \return a newly allocated instance, that the caller must manage.
+ * \throw If \a this contains more than one geometric type.
+ * \throw If the nodal connectivity of \a this is not fully defined.
+ * \throw If the internal data is not coherent.
+ */
+MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
+{
+ checkConnectivityFullyDefined();
+ if(_types.size()!=1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
+ INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
+ MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
+ ret->setCoords(getCoords());
+ MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
+ if(retC)
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
+ retC->setNodalConnectivity(c);
+ }
+ else
+ {
+ MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
+ if(!retD)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
+ DataArrayInt *c=0,*ci=0;
+ convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
+ retD->setNodalConnectivity(cs,cis);
+ }
+ return ret.retn();
+}
+
+DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
+{
+ checkConnectivityFullyDefined();
+ if(_types.size()!=1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
+ INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
+ const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
+ if(cm.isDynamic())
+ {
+ std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
+ oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ int nbCells=getNumberOfCells();
+ int typi=(int)typ;
+ int nbNodesPerCell=(int)cm.getNumberOfNodes();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
+ int *outPtr=connOut->getPointer();
+ const int *conn=_nodal_connec->begin();
+ const int *connI=_nodal_connec_index->begin();
+ nbNodesPerCell++;
+ for(int i=0;i<nbCells;i++,connI++)
+ {
+ if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
+ outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
+ else
+ {
+ 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 << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ return connOut.retn();
+}
+
+void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
+{
+ static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
+ checkConnectivityFullyDefined();
+ if(_types.size()!=1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
+ int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
+ if(lgth<nbCells)
+ throw INTERP_KERNEL::Exception(msg0);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
+ c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
+ int *cp(c->getPointer()),*cip(ci->getPointer());
+ const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
+ cip[0]=0;
+ for(int i=0;i<nbCells;i++,cip++,incip++)
+ {
+ int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
+ int delta(stop-strt);
+ if(delta>=1)
+ {
+ if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
+ cp=std::copy(incp+strt,incp+stop,cp);
+ else
+ throw INTERP_KERNEL::Exception(msg0);
+ }
+ else
+ throw INTERP_KERNEL::Exception(msg0);
+ cip[1]=cip[0]+delta;
+ }
+ nodalConn=c.retn(); nodalConnIndex=ci.retn();
+}
+
/*!
* This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
* Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
/*!
* This method returns a newly created DataArrayInt instance.
- * This method retrieves cell ids in [begin,end) that have the type 'type'.
+ * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
*/
DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
{
/*!
* This method returns a vector of size 'this->getNumberOfCells()'.
- * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
+ * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
*/
std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
{
}
/*!
- * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
+ * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
*/
MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
{
}
/*!
- * This method is ** very badly named ** : This method computes the center of inertia of each cells in \a this.
- * So this method is not a right choice for degnerated meshes (not well oriented, cells with measure close to zero).
- *
- * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
- * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
- *
- * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
+ * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
+ * computed by averaging coordinates of cell nodes, so this method is not a right
+ * choice for degnerated meshes (not well oriented, cells with measure close to zero).
+ * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
+ * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
+ * components. The caller is to delete this array using decrRef() as it is
+ * no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
*/
DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
{
}
/*!
- * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
- * building explicitely it. The input part is defined by an array [begin,end). All ids contained in this array should be less than this->getNumberOfCells().
- * No check of that will be done !
+ * Returns a new DataArrayDouble holding barycenters of specified cells. The
+ * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
+ * are specified via an array of cell ids.
+ * \warning Validity of the specified cell ids is not checked!
+ * Valid range is [ 0, \a this->getNumberOfCells() ).
+ * \param [in] begin - an array of cell ids of interest.
+ * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
+ * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
+ * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
+ * caller is to delete this array using decrRef() as it is no more needed.
+ * \throw If the coordinates array is not set.
+ * \throw If the nodal connectivity of cells is not defined.
+ *
+ * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
+ * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
*/
DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
{
ret->setConnectivity(c,cI,true);
return ret.retn();
}
-
/*!
- * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
- * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
+ * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
+ * Cells and nodes of
+ * the first mesh precede cells and nodes of the second mesh within the result mesh.
+ * \param [in] mesh1 - the first mesh.
+ * \param [in] mesh2 - the second mesh.
+ * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
+ * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
+ * is no more needed.
+ * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
+ * \throw If the coordinates array is not set in none of the meshes.
+ * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
+ * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
*/
MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
- * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
- * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
- * cells in meshes in 'a' (in the same order too).
- */
+ * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
+ * Cells and nodes of
+ * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
+ * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
+ * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
+ * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
+ * is no more needed.
+ * \throw If \a a.size() == 0.
+ * \throw If \a a[ *i* ] == NULL.
+ * \throw If the coordinates array is not set in none of the meshes.
+ * \throw If \a a[ *i* ]->getMeshDimension() < 0.
+ * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
+*/
MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
{
std::size_t sz=a.size();
/// @endcond
/*!
- * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
- * 'meshes' must be a non empty vector.
+ * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
+ * dimension and sharing the node coordinates array.
+ * All cells of the first mesh precede all cells of the second mesh
+ * within the result mesh.
+ * \param [in] mesh1 - the first mesh.
+ * \param [in] mesh2 - the second mesh.
+ * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
+ * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
+ * is no more needed.
+ * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
+ * \throw If the meshes do not share the node coordinates array.
+ * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
+ * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
*/
MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
- * 'meshes' must be a non empty vector.
+ * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
+ * dimension and sharing the node coordinates array.
+ * All cells of the *i*-th mesh precede all cells of the
+ * (*i*+1)-th mesh within the result mesh.
+ * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
+ * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
+ * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
+ * is no more needed.
+ * \throw If \a a.size() == 0.
+ * \throw If \a a[ *i* ] == NULL.
+ * \throw If the meshes do not share the node coordinates array.
+ * \throw If \a a[ *i* ]->getMeshDimension() < 0.
+ * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
*/
MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
{
}
/*!
- * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
- * If a same cell is detected in several meshes in 'meshes', this cell will appear only once in returned mesh (see ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for more details)
- *
- * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
- * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
- * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
- * The arrays contained in 'corr' parameter are returned with refcounter set to one.
- * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
- * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with
- * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
+ * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
+ * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
+ * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
+ * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
+ * New" mode are returned for each input mesh.
+ * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
+ * \param [in] compType - specifies a cell comparison technique. For meaning of its
+ * valid values [0,1,2], see zipConnectivityTraducer().
+ * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
+ * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
+ * mesh. The caller is to delete each of the arrays using decrRef() as it is
+ * no more needed.
+ * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
+ * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
+ * is no more needed.
+ * \throw If \a meshes.size() == 0.
+ * \throw If \a meshes[ *i* ] == NULL.
+ * \throw If the meshes do not share the node coordinates array.
+ * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
+ * \throw If the \a meshes are of different dimension (getMeshDimension()).
+ * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
+ * \throw If the nodal connectivity any of \a meshes includes an invalid id.
*/
MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
{
tmp->alloc(curNbOfCells,1);
std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
offset+=curNbOfCells;
- tmp->setName(meshes[i]->getName());
+ tmp->setName(meshes[i]->getName().c_str());
corr[i]=tmp;
}
return ret.retn();
}
/*!
- * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
- * \b meshes should have a good coherency (connectivity and coordinates well defined).
- * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
- * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
- *
- * This method performs nothing if size of \b meshes is in [0,1].
- * This method is particulary useful in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
- * coordinates DataArrayDouble instance.
- *
- * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
+ * Makes all given meshes share the nodal connectivity array. The common connectivity
+ * array is created by concatenating the connectivity arrays of all given meshes. All
+ * the given meshes must be of the same space dimension but dimension of cells **can
+ * differ**. This method is particulary useful in MEDLoader context to build a \ref
+ * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
+ * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
+ * \param [in,out] meshes - a vector of meshes to update.
+ * \throw If any of \a meshes is NULL.
+ * \throw If the coordinates array is not set in any of \a meshes.
+ * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
+ * \throw If \a meshes are of different space dimension.
*/
void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
- * \b meshes should have a good coherency (connectivity and coordinates well defined).
- * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
- * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
- * If \b meshes share the same instance of DataArrayDouble as coordinates and that this instance is null, this method do nothing and no exception will be thrown.
- *
- * This method performs nothing if size of \b meshes is empty.
- * This method is particulary useful in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
- * coordinates DataArrayDouble instance.
- *
- * \param [in,out] meshes :vector containing no null instance of MEDCouplingUMesh sharing the same DataArrayDouble instance of coordinates, that in case of success of this method will be modified.
- * \param [in] eps is the distance in absolute (that should be positive !), so that 2 or more points within a distance of eps will be merged into a single point.
+ * Merges nodes coincident with a given precision within all given meshes that share
+ * the nodal connectivity array. The given meshes **can be of different** mesh
+ * dimension. This method is particulary useful in MEDLoader context to build a \ref
+ * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
+ * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
+ * \param [in,out] meshes - a vector of meshes to update.
+ * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
+ * \throw If any of \a meshes is NULL.
+ * \throw If the \a meshes do not share the same node coordinates array.
+ * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
*/
void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
{
}
/*!
- * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [connBg,connEnd) and returns its extruded cell by inserting the result at the end of ret.
- * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
- * @param isQuad specifies the policy of connectivity.
+ * 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.
+ * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
+ * \param isQuad specifies the policy of connectivity.
* @ret in/out parameter in which the result will be append
*/
void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
}
/*!
- * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
+ * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
*/
bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
{
}
/*!
- * The polyhedron is specfied by its connectivity nodes in [begin,end).
+ * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
*/
bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
{
}
/*!
- * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
+ * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
*/
bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
{
}
/*!
- * 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)
+ * 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 )
* 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
* a 2D space.
*
/*!
* 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
- * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
+ * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
*
* \param [in] eps below that value the dot product of 2 vectors is considered as colinears
* \param [in] coords coordinates expected to have 3 components.
std::size_t nbPoints=std::distance(begin,end);
if(nbPoints<3)
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
- double vec[3];
+ double vec[3]={0.,0.,0.};
std::size_t j=0;
bool refFound=false;
for(;j<nbPoints-1 && !refFound;j++)
void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
{
- stream << "MEDCouplingUMesh C++ instance at " << this << ".";
+ stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
if(_mesh_dim==-2)
{ stream << " Not set !"; return ; }
stream << " Mesh dimension : " << _mesh_dim << ".";
return std::string("UnstructuredGrid");
}
-/// @cond INTERNAL
-
+/*!
+ * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
+ * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
+ * addition, returns two arrays mapping cells of the result mesh to cells of the input
+ * meshes.
+ * \param [in] m1 - the first input mesh which is a partitioned object.
+ * \param [in] m2 - the second input mesh which is a partition tool.
+ * \param [in] eps - precision used to detect coincident mesh entities.
+ * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
+ * cell an id of the cell of \a m1 it comes from. The caller is to delete
+ * this array using decrRef() as it is no more needed.
+ * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
+ * cell an id of the cell of \a m2 it comes from. -1 value means that a
+ * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
+ * any cell of \a m2. The caller is to delete this array using decrRef() as
+ * it is no more needed.
+ * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
+ * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
+ * is no more needed.
+ * \throw If the coordinates array is not set in any of the meshes.
+ * \throw If the nodal connectivity of cells is not defined in any of the meshes.
+ * \throw If any of the meshes is not a 2D mesh in 2D space.
+ */
MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
{
m1->checkFullyDefined();
return ret.retn();
}
-/// @endcond
-
void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
* - a mesh 'm2' with meshDim==1 and a SpaceDim==2
* - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
* The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
- * @param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
- * @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.
- * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
+ * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
+ * \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.
+ * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
*/
void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
{
* 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).
* 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
* with a plane. The result will be put in 'cut3DSuf' out parameter.
- * @param cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
- * @param nodesOnPlane, returns all the nodes that are on the plane.
- * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
- * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
- * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
- * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
- * @param desc is the descending connectivity 3DSurf->3DCurve
- * @param descIndx is the descending connectivity index 3DSurf->3DCurve
- * @param cut3DSuf input/output param.
+ * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
+ * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
+ * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
+ * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
+ * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
+ * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
+ * \param [in] desc is the descending connectivity 3DSurf->3DCurve
+ * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
+ * \param [out] cut3DSuf input/output param.
*/
void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
const int *nodal3DCurve, const int *nodalIndx3DCurve,
}
/*!
- * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
+ * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
* 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).
* 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
* with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
- * @param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
- * @param desc is the descending connectivity 3D->3DSurf
- * @param descIndx is the descending connectivity index 3D->3DSurf
+ * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
+ * \param desc is the descending connectivity 3D->3DSurf
+ * \param descIndx is the descending connectivity index 3D->3DSurf
*/
void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
const int *desc, const int *descIndx,
* 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
* 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
* the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
- * 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
+ * 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
* 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.
*
- * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
+ * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
*/
bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
{
int nextNode=-1;
int prevNode=-1;
double resRef;
- double angleNext;
+ double angleNext=0.;
while(nextNode!=startNode)
{
nextNode=-1;
* \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
* \param [out] arrOut the resulting array
* \param [out] arrIndexOut the index array of the resulting array \b arrOut
+ * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
*/
void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
{
if(!arrIn || !arrIndxIn)
throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
+ arrIn->checkAllocated(); arrIndxIn->checkAllocated();
+ if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
const int *arrInPtr=arrIn->getConstPointer();
const int *arrIndxPtr=arrIndxIn->getConstPointer();
int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
+ if(nbOfGrps<0)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
int maxSizeOfArr=arrIn->getNumberOfTuples();
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
arrIndexOut=arrIo.retn();
}
+/*!
+ * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
+ * 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 ).
+ * The selection of extraction is done standardly in new2old format.
+ * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
+ *
+ * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
+ * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
+ * \param [in] arrIn arr origin array from which the extraction will be done.
+ * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
+ * \param [out] arrOut the resulting array
+ * \param [out] arrIndexOut the index array of the resulting array \b arrOut
+ * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
+ */
+void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
+ DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
+{
+ if(!arrIn || !arrIndxIn)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
+ arrIn->checkAllocated(); arrIndxIn->checkAllocated();
+ if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
+ int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
+ const int *arrInPtr=arrIn->getConstPointer();
+ const int *arrIndxPtr=arrIndxIn->getConstPointer();
+ int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
+ if(nbOfGrps<0)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
+ int maxSizeOfArr=arrIn->getNumberOfTuples();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
+ arrIo->alloc((int)(sz+1),1);
+ int idsIt=idsOfSelectStart;
+ int *work=arrIo->getPointer();
+ *work++=0;
+ int lgth=0;
+ for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
+ {
+ if(idsIt>=0 && idsIt<nbOfGrps)
+ lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
+ else
+ {
+ std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ if(lgth>=work[-1])
+ *work=lgth;
+ else
+ {
+ std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
+ oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ arro->alloc(lgth,1);
+ work=arro->getPointer();
+ idsIt=idsOfSelectStart;
+ for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
+ {
+ if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
+ work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
+ else
+ {
+ std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
+ oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ arrOut=arro.retn();
+ arrIndexOut=arrIo.retn();
+}
+
/*!
* This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
- * 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
- * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
+ * 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
+ * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
* This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
*
* \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
* \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
* \param [in] arrIn arr origin array from which the extraction will be done.
* \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
- * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
+ * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
* \param [in] srcArrIndex index array of \b srcArr
* \param [out] arrOut the resulting array
* \param [out] arrIndexOut the index array of the resulting array \b arrOut
* \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
* \param [in,out] arrInOut arr origin array from which the extraction will be done.
* \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
- * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
+ * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
* \param [in] srcArrIndex index array of \b srcArr
*
* \sa MEDCouplingUMesh::SetPartOfIndexedArrays
/*!
* This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
- * 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
+ * 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
* cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
* This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
*
std::vector<DataArrayInt *> partition=partitionBySpreadZone();
std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
ret->setCoords(getCoords());
ret->allocateCells((int)partition.size());
//
*/
std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
{
- //#if 0
int nbOfCellsCur=getNumberOfCells();
std::vector<DataArrayInt *> ret;
if(nbOfCellsCur<=0)
for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
ret.push_back((*it).retn());
return ret;
- //#endif
-#if 0
- int nbOfCellsCur=getNumberOfCells();
- DataArrayInt *neigh=0,*neighI=0;
- computeNeighborsOfCells(neigh,neighI);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
- std::vector<DataArrayInt *> ret;
- std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
- while(nbOfCellsCur>0)
- {
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
- ret2.push_back(tmp2); ret.push_back(tmp2);
- nbOfCellsCur=tmp3->getNumberOfTuples();
- if(nbOfCellsCur>0)
- {
- ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
- MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
- neighAuto=neigh;
- neighIAuto=neighI;
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
- neighAuto->transformWithIndArr(renum->begin(),renum->end());
- }
- }
- for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
- (*it)->incrRef();
- return ret;
-#endif
}
/*!
return ret.retn();
}
+/*!
+ * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
+ * All cells in \a this are expected to be linear 3D cells.
+ * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
+ * It leads to an increase to number of cells.
+ * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
+ * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
+ * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
+ *
+ * \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.
+ * For all other cells, the splitting policy will be ignored.
+ * \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.
+ * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
+ * an id of old cell producing it. The caller is to delete this array using
+ * decrRef() as it is no more needed.
+ * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
+ *
+ * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
+ * \throw If \a this is not fully constituted with linear 3D cells.
+ * \sa MEDCouplingUMesh::simplexize
+ */
+MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
+{
+ INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
+ checkConnectivityFullyDefined();
+ if(getMeshDimension()!=3 || getSpaceDimension()!=3)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
+ int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
+ MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
+ int *retPt(ret->getPointer());
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
+ const int *oldc(_nodal_connec->begin());
+ const int *oldci(_nodal_connec_index->begin());
+ const double *coords(_coords->begin());
+ for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
+ {
+ std::vector<int> a; std::vector<double> b;
+ INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
+ std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
+ const int *aa(&a[0]);
+ if(!b.empty())
+ {
+ for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
+ if(*it<0)
+ *it=(-(*(it))-1+nbNodes);
+ addPts->insertAtTheEnd(b.begin(),b.end());
+ nbNodes+=(int)b.size()/3;
+ }
+ for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
+ newConn->insertAtTheEnd(aa,aa+4);
+ }
+ if(!addPts->empty())
+ {
+ addPts->rearrange(3);
+ nbOfAdditionalPoints=addPts->getNumberOfTuples();
+ addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
+ ret0->setCoords(addPts);
+ }
+ else
+ {
+ nbOfAdditionalPoints=0;
+ ret0->setCoords(getCoords());
+ }
+ ret0->setNodalConnectivity(newConn);
+ //
+ ret->computeOffsets2();
+ n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
+ return ret0.retn();
+}
+
MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
_own_cell(true),_cell_id(-1),_nb_cell(0)
{