// 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 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;
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 !");
}
+ else
+ if(_mesh_dim!=-1)
+ throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
}
/*!
}
/*!
- * Allocates memory to store given number of cells.
- * \param [in] nbOfCells - number of cell \a this mesh will contain.
+ * 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();
/*!
* 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.
*/
/*!
* Returns a set of all cell types available in \a this mesh.
- * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
+ * \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
{
}
/*!
- * 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)
}
/*!
- * \brief Checks if data arrays of this mesh (node coordinates, nodal
+ * 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.
return true;
}
-/*!
- * Checks if \a this and \a other meshes are geometrically equivalent, else an
- * exception is thrown. The meshes are
- * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
- * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
- * the \a other mesh (with use of a specified cell comparison technique). The mapping
- * from \a other to \a this for nodes and cells is returned via out parameters.
- * \param [in] other - the mesh to compare with.
- * \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
- * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
- * \param [in] prec - the precision used to compare nodes of the two meshes.
- * \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
- * to delete this array using decrRef() as it is no more needed.
- * \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
- * to delete this array using decrRef() as it is no more needed.
- * \throw If the two meshes do not match.
- *
- * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
- * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
- */
-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 nbCells=getNumberOfCells();
- int maxId=-1;
- if(nbCells!=0)
- maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
- pt=std::find_if(da->getConstPointer()+nbCells,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(nbCells,da->getNbOfElems(),1);
- nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
- cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
-}
-
-/*!
- * Checks if \a this and \a other meshes are geometrically equivalent, else an
- * exception is thrown. The meshes are considered equivalent if (1) they share one
- * node coordinates array and (2) they contain the same cells (with use of a specified
- * cell comparison technique). The mapping from cells of the \a other to ones of \a this
- * is returned via an out parameter.
- * \param [in] other - the mesh to compare with.
- * \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
- * each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
- * \param [in] prec - a not used parameter.
- * \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
- * to delete this array using decrRef() as it is no more needed.
- * \throw If the two meshes do not match.
- *
- * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
- * \ref py_mcumesh_checkDeepEquivalWith "Here is a Python example".
- */
-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();
-}
-
/*!
* 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
*/
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 !");
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
}
/*!
{
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++)
{
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;
* 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)
/*!
* 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)
{
return ret.retn();
}
+/*!
+ * 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
*/
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);
commonCellsIArr=commonCellsI.retn();
}
-/*!
- * Removes duplicates of cells from \a this mesh and returns an array mapping between
- * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
- * equal cells found.
- * \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] compType - specifies a cell comparison technique. Meaning of its
- * valid values [0,1,2] is as follows.
- * - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
- * connectivity and type. This is the strongest policy.
- * - 1 : "permuted same orientation". Two cells are considered equal \c iff they
- * are based on same nodes and have the same type and orientation.
- * - 2 : "nodal". Two cells are considered equal \c iff they
- * are based on same nodes and have the same type. This is the weakest
- * policy, it can be used by users not sensitive to cell orientation.
- * \param [in] startCellId - specifies the cell id at which search for equal cells
- * starts. By default it is 0, which means that all cells in \a this will be
- * scanned.
- * \return DataArrayInt - a new instance of DataArrayInt, of length \a
- * this->getNumberOfCells() 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_zipConnectivityTraducer "Here is a C++ example".<br>
- * \ref py_mcumesh_zipConnectivityTraducer "Here is a Python example".
- */
-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();
-}
-
/*!
* 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
}
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;
}
-/*!
- * Merges nodes equal within \a precision and returns an array describing the
- * permutation used to remove duplicate nodes.
- * \param [in] precision - minimal absolute distance between two nodes at which they are
- * considered not coincident.
- * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
- * \param [out] newNbOfNodes - number of nodes remaining after the removal.
- * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
- * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. 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_mergeNodes "Here is a C++ example".<br>
- * \ref py_mcumesh_mergeNodes "Here is a Python example".
- */
-DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
+MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
{
- DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
- if(areNodesMerged)
- renumberNodes(ret->getConstPointer(),newNbOfNodes);
- return ret;
-}
-
-
-/*!
- * Merges nodes equal within \a precision and returns an array describing the
- * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
- * of merged nodes is changed to be at their barycenter.
- * \param [in] precision - minimal absolute distance between two nodes at which they are
- * considered not coincident.
- * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
- * \param [out] newNbOfNodes - number of nodes remaining after the removal.
- * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
- * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. 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_mergeNodes "Here is a C++ example".<br>
- * \ref py_mcumesh_mergeNodes "Here is a Python example".
- */
-DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
-{
- DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
- if(areNodesMerged)
- renumberNodes2(ret->getConstPointer(),newNbOfNodes);
- return ret;
-}
-
-/*!
- * Substitutes node coordinates array of \a this mesh with that of \a other mesh
- * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
- * meshes match with a specified precision, else an exception is thrown and \a this
- * remains unchanged. In case of success the nodal connectivity of \a this mesh
- * is permuted according to new order of nodes.
- * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
- * coordinates (and so more expensive) than simple equality.
- * \param [in] other - the other mesh whose node coordinates array will be used by
- * \a this mesh in case of their equality.
- * \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
- * \throw If the coordinates array of \a this is not set.
- * \throw If the coordinates array of \a other is not set.
- * \throw If the coordinates of \a this and \a other do not match.
- */
-void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
-{
- 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 ");
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)
}
/*!
- * Finds cells whose all nodes are in a given array of node ids.
- * \param [in] partBg - the array of node ids.
- * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
- * \return DataArrayInt * - a new instance of DataArrayInt holding ids of 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 any cell id in \a partBg is not valid.
- *
- * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
- * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
- */
-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
cellIdsKeptArr=cellIdsKept.retn();
}
-/*!
- * Finds cells whose all or some nodes are in a given array of node ids.
- * \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 returned only, else cells whose any node is in the
- * array \a begin are returned.
- * \return DataArrayInt * - a new instance of DataArrayInt holding ids of 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 any cell id in \a begin is not valid.
- *
- * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
- * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
- */
-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;
-}
-
-/*!
- Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
- copy 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 copied, else cells whose any node is in the
- * array \a begin are copied.
- * \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_buildPartOfMySelfNode "Here is a C++ example".<br>
- * \ref py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
- */
-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);
-}
-
/*!
* Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
* this->getMeshDimension(), that bound some cells of \a this mesh.
/*!
* 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)
{
return const_cast<MEDCouplingUMesh *>(this);
}
-/*!
- * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
- * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
- * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
- * array is modified accordingly.
- * \param [in] newNodeNumbers - a permutation array, of length \a
- * this->getNumberOfNodes(), in "Old to New" mode.
- * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
- * \param [in] newNbOfNodes - number of nodes remaining after renumbering.
- * \throw If the coordinates array is not set.
- * \throw If the nodal connectivity of cells is not defined.
- *
- * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
- * \ref py_mcumesh_renumberNodes "Here is a Python example".
- */
-void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
-{
- MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
- renumberNodesInConn(newNodeNumbers);
-}
-
-/*!
- * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
- * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed,
- * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
- * array is modified accordingly. In contrast to renumberNodes(), location
- * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
- * \param [in] newNodeNumbers - a permutation array, of length \a
- * this->getNumberOfNodes(), in "Old to New" mode.
- * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
- * \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
- * actually one more than the maximal id in \a newNodeNumbers.
- * \throw If the coordinates array is not set.
- * \throw If the nodal connectivity of cells is not defined.
- *
- * \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
- * \ref py_mcumesh_renumberNodes "Here is a Python example".
- */
-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 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);
+ free(const_cast<int *>(array));
}
/*!
/*!
* 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
{
}
/*!
- * 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)
}
/*!
- * 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),
/*!
* 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);
}
/*!
- * 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;
* 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
{
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;
* 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)
{
}
/*!
- * 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 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)
{
/*!
* 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.
*/
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
{
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 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++)
* - 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)
{