X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingUMesh.cxx;h=dc0dcf5b1e17a736acd025c1db08474cf2ca6f93;hb=bad9b3f822dd6c1a37873d27851e603d840b29ce;hp=a14022d1c21b78e6cc992f463a52e7742f2373b7;hpb=9417feb74e73698b9e10c557b3e3c463637a56a6;p=modules%2Fmed.git diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index a14022d1c..dc0dcf5b1 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -165,7 +165,7 @@ MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_conne void MEDCouplingUMesh::checkCoherency() const { if(_mesh_dim<-1) - throw INTERP_KERNEL::Exception("No mesh dimension specified !"); + throw INTERP_KERNEL::Exception("No mesh dimension specified !"); if(_mesh_dim!=-1) MEDCouplingPointSet::checkCoherency(); for(std::set::const_iterator iter=_types.begin();iter!=_types.end();iter++) @@ -565,8 +565,8 @@ bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other */ void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const { - MEDCouplingPointSet::checkFastEquivalWith(other,prec); - const MEDCouplingUMesh *otherC=dynamic_cast(other); + MEDCouplingPointSet::checkFastEquivalWith(other,prec); + const MEDCouplingUMesh *otherC=dynamic_cast(other); if(!otherC) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); } @@ -809,7 +809,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *d * \b WARNING this method do the assumption that connectivity lies on the coordinates set. * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result. * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered. - * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]]. + * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]]. * * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx. @@ -832,7 +832,7 @@ void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArr * excluding a set of meshdim-1 cells in input descending connectivity. * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity. * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered. - * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]]. + * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]]. * * \param [in] desc descending connectivity array. * \param [in] descIndx descending connectivity index array used to walk through \b desc. @@ -843,7 +843,7 @@ void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArr * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors. */ void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx, - DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception) + DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) { if(!desc || !descIndx || !revDesc || !revDescIndx) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !"); @@ -872,6 +872,60 @@ void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, cons neighborsIndx=out1.retn(); } +/*! + * \b WARNING this method do the assumption that connectivity lies on the coordinates set. + * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result. + * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered. + * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]]. + * + * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output + * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx. + * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors. + */ +void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const +{ + checkFullyDefined(); + int mdim(getMeshDimension()),nbNodes(getNumberOfNodes()); + MEDCouplingAutoRefCountObjectPtr desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New()); + MEDCouplingAutoRefCountObjectPtr mesh1D; + switch(mdim) + { + case 3: + { + mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx); + break; + } + case 2: + { + mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx); + break; + } + case 1: + { + mesh1D=const_cast(this); + mesh1D->incrRef(); + break; + } + default: + { + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !"); + } + } + desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0; + mesh1D->getReverseNodalConnectivity(desc,descIndx); + MEDCouplingAutoRefCountObjectPtr ret0(DataArrayInt::New()); + ret0->alloc(desc->getNumberOfTuples(),1); + int *r0Pt(ret0->getPointer()); + const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin()); + for(int i=0;i tmp=new int[lgthOfCurCell-1]; @@ -1272,7 +1326,7 @@ bool MEDCouplingUMesh::unPolyze() newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL; break; } - } + } ret=ret || (newType!=type); conn[newPos]=newType; newPos+=newLgth+1; @@ -1547,7 +1601,7 @@ DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType) { switch(compType) - { + { case 0: return AreCellsEqual0(conn,connI,cell1,cell2); case 1: @@ -1558,7 +1612,7 @@ int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1 return AreCellsEqual3(conn,connI,cell1,cell2); case 7: return AreCellsEqual7(conn,connI,cell1,cell2); - } + } throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7."); } @@ -1668,7 +1722,7 @@ int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell else return 0; } - + return work!=tmp+sz1?1:0; } else @@ -1756,7 +1810,7 @@ void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayI } void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI, - DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception) + DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) { MEDCouplingAutoRefCountObjectPtr commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1); int nbOfCells=nodalI->getNumberOfTuples()-1; @@ -2385,7 +2439,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons). */ void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate, - DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception) + DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const { checkFullyDefined(); otherDimM1OnSameCoords.checkFullyDefined(); @@ -2747,7 +2801,7 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) co */ DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const { - + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); ret->alloc(0,1); checkConnectivityFullyDefined(); @@ -3011,8 +3065,8 @@ void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connInd * 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), - _nodal_connec(0),_nodal_connec_index(0), - _types(other._types) + _nodal_connec(0),_nodal_connec_index(0), + _types(other._types) { if(other._nodal_connec) _nodal_connec=other._nodal_connec->performCpy(deepCopy); @@ -3575,29 +3629,29 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *be */ MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const { - if(getMeshDimension()!=1) + if(getMeshDimension()!=1) throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !"); - if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2) - throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !"); - MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); - MEDCouplingAutoRefCountObjectPtr array=DataArrayDouble::New(); - int nbOfCells=getNumberOfCells(); - int spaceDim=getSpaceDimension(); - array->alloc(nbOfCells,spaceDim); - double *pt=array->getPointer(); - const double *coo=getCoords()->getConstPointer(); - std::vector conn; - conn.reserve(2); - for(int i=0;i()); - } - ret->setArray(array); - ret->setMesh(this); - ret->synchronizeTimeWithSupport(); - return ret.retn(); + if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2) + throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !"); + MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); + MEDCouplingAutoRefCountObjectPtr array=DataArrayDouble::New(); + int nbOfCells=getNumberOfCells(); + int spaceDim=getSpaceDimension(); + array->alloc(nbOfCells,spaceDim); + double *pt=array->getPointer(); + const double *coo=getCoords()->getConstPointer(); + std::vector conn; + conn.reserve(2); + for(int i=0;i()); + } + ret->setArray(array); + ret->setMesh(this); + ret->synchronizeTimeWithSupport(); + return ret.retn(); } /*! @@ -3840,31 +3894,31 @@ void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, { if(getMeshDimension()!=1) throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !"); - if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2) - throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !"); - if(getSpaceDimension()!=3) - throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !"); - MEDCouplingAutoRefCountObjectPtr f=buildDirectionVectorField(); - const double *fPtr=f->getArray()->getConstPointer(); - double tmp[3]; - for(int i=0;i(tmp); - n1/=INTERP_KERNEL::norm<3>(tmp1); - if(n1>eps) - throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !"); - } - const double *coo=getCoords()->getConstPointer(); - for(int i=0;i()); - std::transform(tmp,tmp+3,v,tmp,std::multiplies()); - res[i]=std::accumulate(tmp,tmp+3,0.); - } + if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2) + throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !"); + if(getSpaceDimension()!=3) + throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !"); + MEDCouplingAutoRefCountObjectPtr f=buildDirectionVectorField(); + const double *fPtr=f->getArray()->getConstPointer(); + double tmp[3]; + for(int i=0;i(tmp); + n1/=INTERP_KERNEL::norm<3>(tmp1); + if(n1>eps) + throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !"); + } + const double *coo=getCoords()->getConstPointer(); + for(int i=0;i()); + std::transform(tmp,tmp+3,v,tmp,std::multiplies()); + res[i]=std::accumulate(tmp,tmp+3,0.); + } } /*! @@ -3872,7 +3926,7 @@ void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, * \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). - + * * 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. @@ -3954,7 +4008,7 @@ DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, MEDCouplingAutoRefCountObjectPtr bboxArr(getBoundingBoxForBBTree()); const double *bbox(bboxArr->begin()); switch(spaceDim) - { + { case 3: { BBTreeDst<3> myTree(bbox,0,0,nbCells); @@ -3983,7 +4037,7 @@ DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !"); - } + } cellIds=ret1.retn(); return ret0.retn(); } @@ -4005,7 +4059,7 @@ void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cel for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++) { switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]]) - { + { case INTERP_KERNEL::NORM_TRI3: { double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]); @@ -4023,7 +4077,7 @@ void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cel } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !"); - } + } } } @@ -4043,8 +4097,8 @@ void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *ce ret0=std::numeric_limits::max(); for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++) { - switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]]) - { + switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]]) + { case INTERP_KERNEL::NORM_SEG2: { std::size_t uselessEntry=0; @@ -4056,7 +4110,7 @@ void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *ce } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !"); - } + } } } @@ -4130,17 +4184,19 @@ namespace ParaMEDMEM INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; } // end }; - + + + /*! * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance. */ - INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map& m) + INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr,int>& m) { - INTERP_KERNEL::Edge *ret=0; - INTERP_KERNEL::Node *n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),*n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1])); + INTERP_KERNEL::Edge *ret(0); + MEDCouplingAutoRefCountObjectPtr n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1])); m[n0]=bg[0]; m[n1]=bg[1]; switch(typ) - { + { case INTERP_KERNEL::NORM_SEG2: { ret=new INTERP_KERNEL::EdgeLin(n0,n1); @@ -4162,7 +4218,7 @@ namespace ParaMEDMEM } default: throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !"); - } + } return ret; } @@ -4170,7 +4226,7 @@ namespace ParaMEDMEM { INTERP_KERNEL::Edge *ret=0; switch(typ) - { + { case INTERP_KERNEL::NORM_SEG2: { ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first); @@ -4193,7 +4249,7 @@ namespace ParaMEDMEM } default: throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !"); - } + } return ret; } @@ -4204,8 +4260,7 @@ namespace ParaMEDMEM * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'. */ INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector& candidates, - std::map& mapp) - throw(INTERP_KERNEL::Exception) + std::map& mapp) { mapp.clear(); std::map > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3. @@ -4380,7 +4435,7 @@ void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoint } /*else if(mDim==2) { - + }*/ else throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !"); @@ -4524,7 +4579,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *me int oldNbOfNodes=getNumberOfNodes(); MEDCouplingAutoRefCountObjectPtr newCoords; switch(policy) - { + { case 0: { newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad); @@ -4537,7 +4592,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *me } default: throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !"); - } + } setCoords(newCoords); MEDCouplingAutoRefCountObjectPtr ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad); updateTime(); @@ -4775,7 +4830,6 @@ DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(con double cosangle=i+1rotate(end,vecPlane,angle); - } retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr); } @@ -4963,10 +5017,10 @@ DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType MEDCouplingAutoRefCountObjectPtr coordsSafe; int meshDim=getMeshDimension(); switch(conversionType) - { + { case 0: switch(meshDim) - { + { case 1: ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types); connSafe=conn; connISafe=connI; coordsSafe=coords; @@ -4981,38 +5035,76 @@ DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType break; default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !"); - } + } break; - case 1: - { - switch(meshDim) - { case 1: - ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals - connSafe=conn; connISafe=connI; coordsSafe=coords; - break; - case 2: - ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types); - connSafe=conn; connISafe=connI; coordsSafe=coords; - break; - case 3: - ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types); - connSafe=conn; connISafe=connI; coordsSafe=coords; - break; + { + switch(meshDim) + { + case 1: + ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals + connSafe=conn; connISafe=connI; coordsSafe=coords; + break; + case 2: + ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types); + connSafe=conn; connISafe=connI; coordsSafe=coords; + break; + case 3: + ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types); + connSafe=conn; connISafe=connI; coordsSafe=coords; + break; + default: + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !"); + } + break; + } default: - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !"); - } - break; - } - default: - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !"); - } + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !"); + } setConnectivity(connSafe,connISafe,false); _types=types; setCoords(coordsSafe); return ret.retn(); } +#if 0 +/*! + * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2. + * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit. + * The nodes to be added in those 2D cells are defined by the pair of \a nodeIdsToAdd and \a nodeIdsIndexToAdd. + * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1. + * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge. + * This method can be seen as the opposite method of colinearize2D. + * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end + * to avoid to modify the numbering of existing nodes. + * + * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array) + * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added. + * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this. + * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this. + * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this. + * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this. + * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this. + * + * \sa buildDescendingConnectivity2 + */ +void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit, + const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI) +{ + if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !"); + nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated(); + if(getSpaceDimension()!=2 || getMeshDimension()!=2) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !"); + if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !"); + //DataArrayInt *out0(0),*outi0(0); + //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0); + //MEDCouplingAutoRefCountObjectPtr out0s(out0),outi0s(outi0); + //out0s=out0s->buildUnique(); out0s->sort(true); +} +#endif + /*! * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method. * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells. @@ -5108,7 +5200,6 @@ DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDC */ DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set& types) const { - MEDCouplingAutoRefCountObjectPtr desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New()); MEDCouplingAutoRefCountObjectPtr m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0; return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types); @@ -5397,18 +5488,18 @@ void MEDCouplingUMesh::tessellate2DCurve(double eps) DataArrayInt *MEDCouplingUMesh::simplexize(int policy) { switch(policy) - { + { case 0: return simplexizePol0(); case 1: return simplexizePol1(); case (int) INTERP_KERNEL::PLANAR_FACE_5: - return simplexizePlanarFace5(); + return simplexizePlanarFace5(); case (int) INTERP_KERNEL::PLANAR_FACE_6: - return simplexizePlanarFace6(); + return simplexizePlanarFace6(); default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n - 0 or 1 (only available for meshdim=2) \n - PLANAR_FACE_5, PLANAR_FACE_6 (only for meshdim=3)"); - } + } } /*! @@ -5471,7 +5562,7 @@ DataArrayInt *MEDCouplingUMesh::simplexizePol0() if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4) { const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3], - (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]}; + (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]}; pt=std::copy(tmp,tmp+8,pt); ptI[1]=ptI[0]+4; ptI[2]=ptI[0]+8; @@ -5524,7 +5615,7 @@ DataArrayInt *MEDCouplingUMesh::simplexizePol1() if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4) { const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4], - (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]}; + (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]}; pt=std::copy(tmp,tmp+8,pt); ptI[1]=ptI[0]+4; ptI[2]=ptI[0]+8; @@ -5934,15 +6025,15 @@ void MEDCouplingUMesh::orientCorrectlyPolyhedrons() if(type==INTERP_KERNEL::NORM_POLYHED) { try - { + { if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr)) TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr); - } + } catch(INTERP_KERNEL::Exception& e) - { + { std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what(); throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + } } } updateTime(); @@ -6017,7 +6108,7 @@ DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() { INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]]; switch(type) - { + { case INTERP_KERNEL::NORM_TETRA4: { if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr)) @@ -6058,7 +6149,7 @@ DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !"); - } + } } updateTime(); return ret.retn(); @@ -6129,28 +6220,28 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const { INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn; switch(t) - { - case INTERP_KERNEL::NORM_TRI3: - { - FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp); - *pt=INTERP_KERNEL::triEdgeRatio(tmp); - break; - } - case INTERP_KERNEL::NORM_QUAD4: - { - FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); - *pt=INTERP_KERNEL::quadEdgeRatio(tmp); - break; - } - case INTERP_KERNEL::NORM_TETRA4: - { - FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); - *pt=INTERP_KERNEL::tetraEdgeRatio(tmp); - break; - } + { + case INTERP_KERNEL::NORM_TRI3: + { + FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp); + *pt=INTERP_KERNEL::triEdgeRatio(tmp); + break; + } + case INTERP_KERNEL::NORM_QUAD4: + { + FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); + *pt=INTERP_KERNEL::quadEdgeRatio(tmp); + break; + } + case INTERP_KERNEL::NORM_TETRA4: + { + FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); + *pt=INTERP_KERNEL::tetraEdgeRatio(tmp); + break; + } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !"); - } + } conn+=connI[i+1]-connI[i]; } ret->setName("EdgeRatio"); @@ -6201,28 +6292,28 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const { INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn; switch(t) - { - case INTERP_KERNEL::NORM_TRI3: - { - FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp); - *pt=INTERP_KERNEL::triAspectRatio(tmp); - break; - } - case INTERP_KERNEL::NORM_QUAD4: - { - FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); - *pt=INTERP_KERNEL::quadAspectRatio(tmp); - break; - } - case INTERP_KERNEL::NORM_TETRA4: - { - FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); - *pt=INTERP_KERNEL::tetraAspectRatio(tmp); - break; - } + { + case INTERP_KERNEL::NORM_TRI3: + { + FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp); + *pt=INTERP_KERNEL::triAspectRatio(tmp); + break; + } + case INTERP_KERNEL::NORM_QUAD4: + { + FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); + *pt=INTERP_KERNEL::quadAspectRatio(tmp); + break; + } + case INTERP_KERNEL::NORM_TETRA4: + { + FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp); + *pt=INTERP_KERNEL::tetraAspectRatio(tmp); + break; + } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !"); - } + } conn+=connI[i+1]-connI[i]; } ret->setName("AspectRatio"); @@ -6272,16 +6363,16 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const { INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn; switch(t) - { - case INTERP_KERNEL::NORM_QUAD4: - { - FillInCompact3DMode(3,4,conn+1,coo,tmp); - *pt=INTERP_KERNEL::quadWarp(tmp); - break; - } + { + case INTERP_KERNEL::NORM_QUAD4: + { + FillInCompact3DMode(3,4,conn+1,coo,tmp); + *pt=INTERP_KERNEL::quadWarp(tmp); + break; + } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !"); - } + } conn+=connI[i+1]-connI[i]; } ret->setName("Warp"); @@ -6332,16 +6423,16 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const { INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn; switch(t) - { - case INTERP_KERNEL::NORM_QUAD4: - { - FillInCompact3DMode(3,4,conn+1,coo,tmp); - *pt=INTERP_KERNEL::quadSkew(tmp); - break; - } + { + case INTERP_KERNEL::NORM_QUAD4: + { + FillInCompact3DMode(3,4,conn+1,coo,tmp); + *pt=INTERP_KERNEL::quadSkew(tmp); + break; + } default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !"); - } + } conn+=connI[i+1]-connI[i]; } ret->setName("Skew"); @@ -7052,7 +7143,7 @@ std::vector MEDCouplingUMesh::splitByType() const MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const { checkConnectivityFullyDefined(); - if(_types.size()!=1) + 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 ret=MEDCoupling1GTUMesh::New(getName(),typ); @@ -7079,7 +7170,7 @@ MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const { checkConnectivityFullyDefined(); - if(_types.size()!=1) + 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); @@ -7160,7 +7251,7 @@ void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt */ MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector& ms, DataArrayInt *&szOfCellGrpOfSameType, - DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception) + DataArrayInt *&idInMsOfCellGrpOfSameType) { std::vector ms2; for(std::vector::const_iterator it=ms.begin();it!=ms.end();it++) @@ -7586,7 +7677,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, * \throw If the coordinates array is not set in none of the meshes. * \throw If \a a[ *i* ]->getMeshDimension() < 0. * \throw If the meshes in \a a are of different dimension (getMeshDimension()). -*/ + */ MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector& a) { std::size_t sz=a.size(); @@ -7932,7 +8023,7 @@ void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, ret.push_back(cm.getExtrudedType()); int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev; switch(flatType) - { + { case INTERP_KERNEL::NORM_POINT1: { ret.push_back(connBg[1]); @@ -7966,7 +8057,7 @@ void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, case INTERP_KERNEL::NORM_TRI6: { int conn[15]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4],connBg[5],connBg[6],connBg[4]+deltaz,connBg[5]+deltaz,connBg[6]+deltaz, - connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev}; + connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev}; ret.insert(ret.end(),conn,conn+15); break; } @@ -7999,7 +8090,7 @@ void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, } default: throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !"); - } + } } /*! @@ -8616,6 +8707,11 @@ std::string MEDCouplingUMesh::getVTKDataSetType() const return std::string("UnstructuredGrid"); } +std::string MEDCouplingUMesh::getVTKFileExtension() const +{ + return std::string("vtu"); +} + /*! * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and * returns a result mesh constituted by polygons. @@ -8645,6 +8741,8 @@ std::string MEDCouplingUMesh::getVTKDataSetType() const MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) { + if(!m1 || !m2) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !"); m1->checkFullyDefined(); m2->checkFullyDefined(); if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2) @@ -8655,10 +8753,8 @@ MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0; std::vector addCoo,addCoordsQuadratic; // coordinates of newly created nodes - INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; - INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2, - m1Desc,desc1,descIndx1,revDesc1,revDescIndx1, + m1Desc,desc1,descIndx1,revDesc1,revDescIndx1, addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2); revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef(); MEDCouplingAutoRefCountObjectPtr dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2); @@ -8676,62 +8772,755 @@ MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2); // Step 4: Prepare final result: - MEDCouplingAutoRefCountObjectPtr addCooDa=DataArrayDouble::New(); + MEDCouplingAutoRefCountObjectPtr addCooDa(DataArrayDouble::New()); addCooDa->alloc((int)(addCoo.size())/2,2); std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer()); - MEDCouplingAutoRefCountObjectPtr addCoordsQuadraticDa=DataArrayDouble::New(); + MEDCouplingAutoRefCountObjectPtr addCoordsQuadraticDa(DataArrayDouble::New()); addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2); std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer()); std::vector coordss(4); coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa; - MEDCouplingAutoRefCountObjectPtr coo=DataArrayDouble::Aggregate(coordss); - MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New("Intersect2D",2); - MEDCouplingAutoRefCountObjectPtr conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer()); - MEDCouplingAutoRefCountObjectPtr connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer()); - MEDCouplingAutoRefCountObjectPtr c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer()); - MEDCouplingAutoRefCountObjectPtr c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer()); + MEDCouplingAutoRefCountObjectPtr coo(DataArrayDouble::Aggregate(coordss)); + MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingUMesh::New("Intersect2D",2)); + MEDCouplingAutoRefCountObjectPtr conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer()); + MEDCouplingAutoRefCountObjectPtr connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer()); + MEDCouplingAutoRefCountObjectPtr c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer()); + MEDCouplingAutoRefCountObjectPtr c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer()); ret->setConnectivity(conn,connI,true); ret->setCoords(coo); cellNb1=c1.retn(); cellNb2=c2.retn(); return ret.retn(); } +/// @cond INTERNAL -/** - * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the - * (newly created) nodes corresponding to the edge intersections. - * Output params: - * @param[out] cr, crI connectivity of the resulting mesh - * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2 - * TODO: describe input parameters - */ -void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1, - const std::vector >& intesctEdges1, const std::vector< std::vector >& colinear2, - const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector >& intesctEdges2, - const std::vector& addCoords, - std::vector& addCoordsQuadratic, std::vector& cr, std::vector& crI, std::vector& cNb1, std::vector& cNb2) +bool IsColinearOfACellOf(const std::vector< std::vector >& intersectEdge1, const std::vector& candidates, int start, int stop, int& retVal) { - static const int SPACEDIM=2; - const double *coo1=m1->getCoords()->getConstPointer(); - const int *conn1=m1->getNodalConnectivity()->getConstPointer(); - const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer(); - int offset1=m1->getNumberOfNodes(); - const double *coo2=m2->getCoords()->getConstPointer(); - const int *conn2=m2->getNodalConnectivity()->getConstPointer(); - const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer(); - int offset2=offset1+m2->getNumberOfNodes(); - int offset3=offset2+((int)addCoords.size())/2; - MEDCouplingAutoRefCountObjectPtr bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree()); - const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin()); - // Here a BBTree on 2D-cells, not on segments: - BBTree myTree(bbox2,0,0,m2->getNumberOfCells(),eps); - int ncell1=m1->getNumberOfCells(); - crI.push_back(0); - for(int i=0;i::const_iterator it=candidates.begin();it!=candidates.end();it++) { - std::vector candidates2; - myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2); - std::map mapp; + const std::vector& pool(intersectEdge1[*it]); + int tmp[2]; tmp[0]=start; tmp[1]=stop; + if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end()) + { + retVal=*it+1; + return true; + } + tmp[0]=stop; tmp[1]=start; + if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end()) + { + retVal=-*it-1; + return true; + } + } + return false; +} + +/// @endcond + +MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector >& intersectEdge2, const DataArrayDouble *coords1, const std::vector& addCoo, const std::map& mergedNodes, const std::vector< std::vector >& colinear2, const std::vector< std::vector >& intersectEdge1, + MEDCouplingAutoRefCountObjectPtr& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr& idsInMesh1DForIdsInRetColinear) +{ + idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1); + idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1); + int nCells(mesh1D->getNumberOfCells()); + if(nCells!=(int)intersectEdge2.size()) + throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !"); + const DataArrayDouble *coo2(mesh1D->getCoords()); + const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin()); + const double *coo2Ptr(coo2->begin()); + int offset1(coords1->getNumberOfTuples()); + int offset2(offset1+coo2->getNumberOfTuples()); + int offset3(offset2+addCoo.size()/2); + std::vector addCooQuad; + MEDCouplingAutoRefCountObjectPtr cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0); + int tmp[4],cicnt(0),kk(0); + for(int i=0;i,int> m; + INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m)); + const std::vector& subEdges(intersectEdge2[i]); + int nbSubEdge(subEdges.size()/2); + for(int j=0;j n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)); + MEDCouplingAutoRefCountObjectPtr e2(e->buildEdgeLyingOnMe(n1,n2)); + INTERP_KERNEL::Edge *e2Ptr(e2); + std::map::const_iterator itm; + if(dynamic_cast(e2Ptr)) + { + tmp[0]=INTERP_KERNEL::NORM_SEG3; + itm=mergedNodes.find(subEdges[2*j]); + tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j]; + itm=mergedNodes.find(subEdges[2*j+1]); + tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1]; + tmp[3]=offset3+(int)addCooQuad.size()/2; + double tmp2[2]; + e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2); + cicnt+=4; + cOut->insertAtTheEnd(tmp,tmp+4); + ciOut->pushBackSilent(cicnt); + } + else + { + tmp[0]=INTERP_KERNEL::NORM_SEG2; + itm=mergedNodes.find(subEdges[2*j]); + tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j]; + itm=mergedNodes.find(subEdges[2*j+1]); + tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1]; + cicnt+=3; + cOut->insertAtTheEnd(tmp,tmp+3); + ciOut->pushBackSilent(cicnt); + } + int tmp00; + if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00)) + { + idsInRetColinear->pushBackSilent(kk); + idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00); + } + } + e->decrRef(); + } + MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingUMesh::New(mesh1D->getName(),1)); + ret->setConnectivity(cOut,ciOut,true); + MEDCouplingAutoRefCountObjectPtr arr3(DataArrayDouble::New()); + arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2); + MEDCouplingAutoRefCountObjectPtr arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2); + std::vector coordss(4); + coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4; + MEDCouplingAutoRefCountObjectPtr arr(DataArrayDouble::Aggregate(coordss)); + ret->setCoords(arr); + return ret.retn(); +} + +MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector >& intersectEdge1) +{ + std::vector allEdges; + for(const int *it2(descBg);it2!=descEnd;it2++) + { + const std::vector& edge1(intersectEdge1[std::abs(*it2)-1]); + if(*it2>0) + allEdges.insert(allEdges.end(),edge1.begin(),edge1.end()); + else + allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend()); + } + std::size_t nb(allEdges.size()); + if(nb%2!=0) + throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !"); + std::size_t nbOfEdgesOf2DCellSplit(nb/2); + MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingUMesh::New("",2)); + ret->setCoords(coords); + ret->allocateCells(1); + std::vector connOut(nbOfEdgesOf2DCellSplit); + for(std::size_t kk=0;kkinsertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]); + return ret.retn(); +} + +void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr >& edges) +{ + bool isQuad(false); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=edges.begin();it!=edges.end();it++) + { + const INTERP_KERNEL::Edge *ee(*it); + if(dynamic_cast(ee)) + isQuad=true; + } + if(!isQuad) + mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]); + else + { + const double *coo(mesh2D->getCoords()->begin()); + std::size_t sz(conn.size()); + std::vector addCoo; + std::vector conn2(conn); + int offset(mesh2D->getNumberOfNodes()); + for(std::size_t i=0;igetMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp); + addCoo.insert(addCoo.end(),tmp,tmp+2); + conn2.push_back(offset+(int)i); + } + mesh2D->getCoords()->rearrange(1); + mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size()); + mesh2D->getCoords()->rearrange(2); + mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]); + } +} + +/*! + * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve. + */ +void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr >& edge1BisPtr, + std::vector< std::vector >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr > >& out1) +{ + std::size_t nb(edge1Bis.size()/2); + std::size_t nbOfEdgesOf2DCellSplit(nb/2); + int iEnd(splitMesh1D->getNumberOfCells()); + if(iEnd==0) + throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !"); + std::size_t ii,jj; + const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin()); + for(ii=0;ii single output cell + out0.resize(1); out1.resize(1); + std::vector& connOut(out0[0]); + connOut.resize(nbOfEdgesOf2DCellSplit); + std::vector< MEDCouplingAutoRefCountObjectPtr >& edgesPtr(out1[0]); + edgesPtr.resize(nbOfEdgesOf2DCellSplit); + for(std::size_t kk=0;kk& connOutLeft(out0[0]); + std::vector& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1] + std::vector< MEDCouplingAutoRefCountObjectPtr >& eleft(out1[0]); + std::vector< MEDCouplingAutoRefCountObjectPtr >& eright(out1[1]); + for(std::size_t k=ii;k > ees(iEnd); + for(int ik=iEnd-1;ik>=0;ik--) + { + std::map< MEDCouplingAutoRefCountObjectPtr,int> m; + MEDCouplingAutoRefCountObjectPtr ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m)); + ees[iEnd-1-ik]=ee; + } + for(int ik=iEnd-1;ik>=0;ik--) + connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]); + for(std::size_t k=jj+1;k& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr >& edgesPtr); +public: + std::vector _edges; + std::vector< MEDCouplingAutoRefCountObjectPtr > _edges_ptr; +}; + +CellInfo::CellInfo(const std::vector& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr >& edgesPtr) +{ + std::size_t nbe(edges.size()); + std::vector edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr > edgesPtr2(2*nbe); + for(std::size_t i=0;i& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { } + EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { } + bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; } + void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newRight); + void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const; +private: + int _istart; + int _iend; + MEDCouplingAutoRefCountObjectPtr _mesh; + MEDCouplingAutoRefCountObjectPtr _edge; + int _left; + int _right; +}; + +void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newRight) +{ + const MEDCouplingUMesh *mesh(_mesh); + if(mesh) + return ; + if(_rightpos) + { _left++; _right++; return ; } + if(_right==pos) + { + bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end()); + if((isLeft && isRight) || (!isLeft && !isRight)) + throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !"); + if(isLeft) + return ; + if(isRight) + { + _right++; + return ; + } + } + if(_left==pos) + { + bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end()); + if((isLeft && isRight) || (!isLeft && !isRight)) + throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !"); + if(isLeft) + { + _right++; + return ; + } + if(isRight) + { + _left++; + _right++; + return ; + } + } +} + +void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const +{ + const MEDCouplingUMesh *mesh(_mesh); + if(!mesh) + { + neighbors[0]=offset+_left; neighbors[1]=offset+_right; + } + else + {// not fully splitting cell case + if(mesh2D->getNumberOfCells()==1) + {//little optimization. 1 cell no need to find in which cell mesh is ! + neighbors[0]=offset; neighbors[1]=offset; + return; + } + else + { + MEDCouplingAutoRefCountObjectPtr barys(mesh->getBarycenterAndOwner()); + int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps)); + if(cellId==-1) + throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !"); + neighbors[0]=offset+cellId; neighbors[1]=offset+cellId; + } + } +} + +class VectorOfCellInfo +{ +public: + VectorOfCellInfo(const std::vector& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr >& edgesPtr); + std::size_t size() const { return _pool.size(); } + int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const; + void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr& mesh1DInCase, const std::vector< std::vector >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr > >& edgePtrs); + const std::vector& getConnOf(int pos) const { return get(pos)._edges; } + const std::vector< MEDCouplingAutoRefCountObjectPtr >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; } + MEDCouplingAutoRefCountObjectPtr getZeMesh() const { return _ze_mesh; } + void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const; +private: + int getZePosOfEdgeGivenItsGlobalId(int pos) const; + void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newRight); + const CellInfo& get(int pos) const; + CellInfo& get(int pos); +private: + std::vector _pool; + MEDCouplingAutoRefCountObjectPtr _ze_mesh; + std::vector _edge_info; +}; + +VectorOfCellInfo::VectorOfCellInfo(const std::vector& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr >& edgesPtr):_pool(1) +{ + _pool[0]._edges=edges; + _pool[0]._edges_ptr=edgesPtr; +} + +int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const +{ + if(_pool.empty()) + throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !"); + if(_pool.size()==1) + return 0; + const MEDCouplingUMesh *zeMesh(_ze_mesh); + if(!zeMesh) + throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !"); + MEDCouplingAutoRefCountObjectPtr barys(mesh->getBarycenterAndOwner()); + return zeMesh->getCellContainingPoint(barys->begin(),eps); +} + +void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr& mesh1DInCase, const std::vector< std::vector >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr > >& edgePtrs) +{ + get(pos);//to check pos + bool isFast(pos==0 && _pool.size()==1); + std::size_t sz(edges.size()); + // dealing with edges + if(sz==1) + _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase)); + else + _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back())); + // + std::vector pool(_pool.size()-1+sz); + for(int i=0;i > ms; + if(pos>0) + { + MEDCouplingAutoRefCountObjectPtr elt(static_cast(_ze_mesh->buildPartOfMySelf2(0,pos,true))); + ms.push_back(elt); + } + ms.push_back(mesh); + if(pos<_ze_mesh->getNumberOfCells()-1) + { + MEDCouplingAutoRefCountObjectPtr elt(static_cast(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true))); + ms.push_back(elt); + } + std::vector< const MEDCouplingUMesh *> ms2(ms.size()); + for(std::size_t j=0;j=0 !"); + int ret(0); + for(std::vector::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++) + { + if((*it).isInMyRange(pos)) + return ret; + } + throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !"); +} + +void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr >& newRight) +{ + get(pos);//to check; + if(_edge_info.empty()) + return ; + std::size_t sz(_edge_info.size()-1); + for(std::size_t i=0;i=(int)_pool.size()) + throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !"); + return _pool[pos]; +} + +CellInfo& VectorOfCellInfo::get(int pos) +{ + if(pos<0 || pos>=(int)_pool.size()) + throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !"); + return _pool[pos]; +} + +MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr >& allEdgesPtr, int offset, + MEDCouplingAutoRefCountObjectPtr& idsLeftRight) +{ + int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells()); + if(nbCellsInSplitMesh1D==0) + throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !"); + const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin()); + std::size_t nb(allEdges.size()),jj; + if(nb%2!=0) + throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !"); + std::vector edge1Bis(nb*2); + std::vector< MEDCouplingAutoRefCountObjectPtr > edge1BisPtr(nb*2); + std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()); + std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb); + std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()); + std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb); + // + idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2); + int *idsLeftRightPtr(idsLeftRight->getPointer()); + VectorOfCellInfo pool(edge1Bis,edge1BisPtr); + for(int iStart=0;iStart partOfSplitMesh1D(static_cast(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true))); + int pos(pool.getPositionOf(eps,partOfSplitMesh1D)); + // + MEDCouplingAutoRefCountObjectPtrretTmp(MEDCouplingUMesh::New("",2)); + retTmp->setCoords(splitMesh1D->getCoords()); + retTmp->allocateCells(); + + std::vector< std::vector > out0; + std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr > > out1; + + BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1); + for(std::size_t cnt=0;cnt >& intersectEdge1, int offset, + MEDCouplingAutoRefCountObjectPtr& idsLeftRight) +{ + const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin()); + // + std::vector allEdges; + std::vector< MEDCouplingAutoRefCountObjectPtr > allEdgesPtr; + for(const int *it(descBg);it!=descEnd;it++) + { + int edgeId(std::abs(*it)-1); + std::map< MEDCouplingAutoRefCountObjectPtr,int> m; + MEDCouplingAutoRefCountObjectPtr ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m)); + const std::vector& edge1(intersectEdge1[edgeId]); + if(*it>0) + allEdges.insert(allEdges.end(),edge1.begin(),edge1.end()); + else + allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend()); + std::size_t sz(edge1.size()); + for(std::size_t cnt=0;cntcheckFullyDefined(); + mesh1D->checkFullyDefined(); + const std::vector& compNames(mesh2D->getCoords()->getInfoOnComponents()); + if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !"); + // Step 1: compute all edge intersections (new nodes) + std::vector< std::vector > intersectEdge1, colinear2, subDiv2; + std::vector addCoo,addCoordsQuadratic; // coordinates of newly created nodes + INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; + INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; + // + // Build desc connectivity + DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New()); + MEDCouplingAutoRefCountObjectPtr dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1); + MEDCouplingAutoRefCountObjectPtr m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1)); + std::map mergedNodes; + Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes); + // use mergeNodes to fix intersectEdge1 + for(std::vector< std::vector >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++) + { + std::size_t n((*it0).size()/2); + int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]); + std::map::const_iterator it1; + it1=mergedNodes.find(eltStart); + if(it1!=mergedNodes.end()) + (*it0)[0]=(*it1).second; + it1=mergedNodes.find(eltEnd); + if(it1!=mergedNodes.end()) + (*it0)[2*n-1]=(*it1).second; + } + // + MEDCouplingAutoRefCountObjectPtr addCooDa(DataArrayDouble::New()); + addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2); + // Step 2: re-order newly created nodes according to the ordering found in m2 + std::vector< std::vector > intersectEdge2; + BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2); + subDiv2.clear(); + // + MEDCouplingAutoRefCountObjectPtr idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear; + MEDCouplingAutoRefCountObjectPtr ret2(DataArrayInt::New()); ret2->alloc(0,1); + MEDCouplingAutoRefCountObjectPtr ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1, + idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear)); + MEDCouplingAutoRefCountObjectPtr ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2); + MEDCouplingAutoRefCountObjectPtr idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells())); + // deal with cells in mesh2D that are not cut but only some of their edges are + MEDCouplingAutoRefCountObjectPtr idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy()); + idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1); + idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique(); + MEDCouplingAutoRefCountObjectPtr out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells + if(!idsInDesc2DToBeRefined->empty()) + { + DataArrayInt *out0(0),*outi0(0); + MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0); + MEDCouplingAutoRefCountObjectPtr outi0s(outi0); + out0s=out0; + out0s=out0s->buildUnique(); + out0s->sort(true); + } + // + MEDCouplingAutoRefCountObjectPtr ret1NonCol(static_cast(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end()))); + MEDCouplingAutoRefCountObjectPtr baryRet1(ret1NonCol->getBarycenterAndOwner()); + MEDCouplingAutoRefCountObjectPtr elts,eltsIndex; + mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex); + MEDCouplingAutoRefCountObjectPtr eltsIndex2(eltsIndex->deltaShiftIndex()); + MEDCouplingAutoRefCountObjectPtr eltsIndex3(eltsIndex2->getIdsEqual(1)); + if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells()) + throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !"); + MEDCouplingAutoRefCountObjectPtr cellsToBeModified(elts->buildUnique()); + MEDCouplingAutoRefCountObjectPtr untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells())); + if((DataArrayInt *)out0s) + untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one + std::vector< MEDCouplingAutoRefCountObjectPtr > outMesh2DSplit; + if(!untouchedCells->empty()) + { + outMesh2DSplit.push_back(static_cast(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end()))); + outMesh2DSplit.back()->setCoords(ret1->getCoords()); + ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end()); + } + if((DataArrayInt *)out0s) + {// here dealing with cells in out0s but not in cellsToBeModified + MEDCouplingAutoRefCountObjectPtr fewModifiedCells(out0s->buildSubstraction(cellsToBeModified)); + const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin()); + for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++) + { + outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1)); + } + int offset(ret2->getNumberOfTuples()); + ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end()); + MEDCouplingAutoRefCountObjectPtr partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1); + partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2); + int kk(0),*ret3ptr(partOfRet3->getPointer()); + for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++) + { + int faceId(std::abs(*it)-1); + for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++) + { + int tmp(fewModifiedCells->locateValue(*it2)); + if(tmp!=-1) + { + if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1]) + ret3ptr[2*kk]=tmp+offset; + if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1]) + ret3ptr[2*kk+1]=tmp+offset; + } + else + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !"); + } + } + ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true); + } + for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++) + { + MEDCouplingAutoRefCountObjectPtr idsNonColPerCell(elts->getIdsEqual(*it)); + idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end()); + MEDCouplingAutoRefCountObjectPtr idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end())); + MEDCouplingAutoRefCountObjectPtr partOfMesh1CuttingCur2DCell(static_cast(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end()))); + MEDCouplingAutoRefCountObjectPtr partOfRet3; + MEDCouplingAutoRefCountObjectPtr splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3)); + ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true); + outMesh2DSplit.push_back(splitOfOneCell); + for(int i=0;igetNumberOfCells();i++) + ret2->pushBackSilent(*it); + } + // + std::size_t nbOfMeshes(outMesh2DSplit.size()); + std::vector tmp(nbOfMeshes); + for(std::size_t i=0;igetCoords()->setInfoOnComponents(compNames); + // + splitMesh1D=ret1.retn(); + splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp); + cellIdInMesh2D=ret2.retn(); + cellIdInMesh1D=ret3.retn(); +} + +/** + * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the + * (newly created) nodes corresponding to the edge intersections. + * Output params: + * @param[out] cr, crI connectivity of the resulting mesh + * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2 + * TODO: describe input parameters + */ +void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1, + const std::vector >& intesctEdges1, const std::vector< std::vector >& colinear2, + const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector >& intesctEdges2, + const std::vector& addCoords, + std::vector& addCoordsQuadratic, std::vector& cr, std::vector& crI, std::vector& cNb1, std::vector& cNb2) +{ + static const int SPACEDIM=2; + const double *coo1(m1->getCoords()->getConstPointer()); + const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer()); + int offset1(m1->getNumberOfNodes()); + const double *coo2(m2->getCoords()->getConstPointer()); + const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer()); + int offset2(offset1+m2->getNumberOfNodes()); + int offset3(offset2+((int)addCoords.size())/2); + MEDCouplingAutoRefCountObjectPtr bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree()); + const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin()); + // Here a BBTree on 2D-cells, not on segments: + BBTree myTree(bbox2,0,0,m2->getNumberOfCells(),eps); + int ncell1(m1->getNumberOfCells()); + crI.push_back(0); + for(int i=0;i candidates2; + myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2); + std::map mapp; std::map mappRev; INTERP_KERNEL::QuadraticPolygon pol1; INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]]; @@ -8740,7 +9529,7 @@ void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCo MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev); // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes. pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1, - desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1); + desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1); // std::set edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result std::set edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1. @@ -8759,12 +9548,12 @@ void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCo MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev); // pol2 is the new QP in the final merged result. pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2, - pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare); + pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare); } ii=0; for(std::vector::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++) { - pol1.initLocationsWithOther(pol2s[ii]); + INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]); pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2); //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2); pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2); @@ -8774,23 +9563,108 @@ void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCo if(!edges1.empty()) { try - { + { INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2); - } + } catch(INTERP_KERNEL::Exception& e) - { + { std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what(); throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + } } for(std::map::const_iterator it=mappRev.begin();it!=mappRev.end();it++) (*it).second->decrRef(); } } -void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map& m, int forbVal0, int forbVal1, std::vector& isect) +/** + * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that + * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors). + * This doesn't modify the mesh. + * The caller is to deal with the resulting DataArrayInt. + * \throw If the coordinate array is not set. + * \throw If the nodal connectivity of the cells is not defined. + * \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1 + * \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments) + */ +DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const +{ + checkFullyDefined(); + if(getMeshDimension()!=1 || getSpaceDimension()!=2) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with (meshdim, spacedim) = (1,2)!"); + + // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments: + MEDCouplingAutoRefCountObjectPtr _d(DataArrayInt::New()),_dI(DataArrayInt::New()); + MEDCouplingAutoRefCountObjectPtr _rD(DataArrayInt::New()),_rDI(DataArrayInt::New()); + MEDCouplingAutoRefCountObjectPtr m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI)); + const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer()); + const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer()); + MEDCouplingAutoRefCountObjectPtr _dsi(_rDI->deltaShiftIndex()); + const int * dsi(_dsi->getConstPointer()); + MEDCouplingAutoRefCountObjectPtr dsii = _dsi->getIdsNotInRange(0,3); + m_points=0; + if (dsii->getNumberOfTuples()) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!"); + + int nc(getNumberOfCells()); + MEDCouplingAutoRefCountObjectPtr result(DataArrayInt::New()); + result->alloc(nc,1); + + // set of edges not used so far + std::set edgeSet; + for (int i=0; i linePiece; + // fills a list of consecutive segment linked to startSeg. This can go forward or backward. + for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward + { + // Fill the list forward (resp. backward) from the start segment: + int activeSeg = startSeg; + int prevPointId = -20; + int ptId; + while (!edgeSet.empty()) + { + if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg + { + if (direction==0) + linePiece.push_back(activeSeg); + else + linePiece.push_front(activeSeg); + edgeSet.erase(activeSeg); + } + + int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1]; + ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2); + if (dsi[ptId] == 1) // hitting the end of the line + break; + prevPointId = ptId; + int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1]; + activeSeg = (seg1 == activeSeg) ? seg2 : seg1; + } + } + // Done, save final piece into DA: + std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx); + newIdx += linePiece.size(); + + // identify next valid start segment (one which is not consumed) + if(!edgeSet.empty()) + startSeg = *(edgeSet.begin()); + } + while (!edgeSet.empty()); + return result.retn(); +} + +/// @cond INTERNAL + +void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map,int>& m, int forbVal0, int forbVal1, std::vector& isect) { - std::map::const_iterator it(m.find(n)); + MEDCouplingAutoRefCountObjectPtr nTmp(n); nTmp->incrRef(); + std::map,int>::const_iterator it(m.find(nTmp)); if(it==m.end()) throw INTERP_KERNEL::Exception("Internal error in remapping !"); int v((*it).second); @@ -8800,7 +9674,7 @@ void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map& m, int forbVal0, int forbVal1, std::vector& isect) +bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map,int>& m, int forbVal0, int forbVal1, std::vector& isect) { int sz(c.size()); if(sz<=1) @@ -8817,9 +9691,11 @@ bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map< return presenceOfOn; } +/// @endcond + /** * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode. - * To do the work this method can optionnaly needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted. + * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted. * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle. * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh. * @@ -8896,9 +9772,9 @@ DataArrayInt *MEDCouplingUMesh::conformize2D(double eps) for(std::vector::const_iterator it=candidates.begin();it!=candidates.end();it++) if(*it>i) { - std::map m; + std::map,int> m; INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)), - *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m)); + *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m)); INTERP_KERNEL::MergePoints merge; INTERP_KERNEL::QuadraticPolygon c1,c2; e1->intersectWith(e2,merge,c1,c2); @@ -8907,8 +9783,6 @@ DataArrayInt *MEDCouplingUMesh::conformize2D(double eps) overlapEdge[i].push_back(*it); if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it])) overlapEdge[*it].push_back(i); - for(std::map::const_iterator it2=m.begin();it2!=m.end();it2++) - (*it2).first->decrRef(); } } // splitting done. sort intersect point in intersectEdge. @@ -8922,12 +9796,10 @@ DataArrayInt *MEDCouplingUMesh::conformize2D(double eps) int sz((int)isect.size()); if(sz>1) { - std::map m; + std::map,int> m; INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)); e->sortSubNodesAbs(coords,isect); e->decrRef(); - for(std::map::const_iterator it2=m.begin();it2!=m.end();it2++) - (*it2).first->decrRef(); } if(sz!=0) { @@ -9049,46 +9921,33 @@ DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps) } /*! - * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2). - * It builds the descending connectivity of the two meshes, and then using a binary tree - * it computes the edge intersections. This results in new points being created : they're stored in addCoo. - * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs(). + * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop. + * So for all edge \a i in \a m1Desc \a intersectEdge1[i] is of length 2*n where n is the number of sub edges. + * And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j]. + * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo + * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it. + * \param [out] addCoo - nodes to be append at the end + * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc. */ -void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, - std::vector< std::vector >& intersectEdge1, std::vector< std::vector >& colinear2, std::vector< std::vector >& subDiv2, - MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1, - std::vector& addCoo, - MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2) - throw(INTERP_KERNEL::Exception) +void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps, + std::vector< std::vector >& intersectEdge1, std::vector< std::vector >& colinear2, std::vector< std::vector >& subDiv2, std::vector& addCoo, std::map& mergedNodes) { static const int SPACEDIM=2; - // Build desc connectivity - desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New(); - desc2=DataArrayInt::New(); - descIndx2=DataArrayInt::New(); - revDesc2=DataArrayInt::New(); - revDescIndx2=DataArrayInt::New(); - MEDCouplingAutoRefCountObjectPtr dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1); - MEDCouplingAutoRefCountObjectPtr dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2); - m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1); - m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2); - MEDCouplingAutoRefCountObjectPtr dd9(m1Desc),dd10(m2Desc); - const int *c1=m1Desc->getNodalConnectivity()->getConstPointer(); - const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer(); - + INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps; + INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps; + const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer()); // Build BB tree of all edges in the tool mesh (second mesh) MEDCouplingAutoRefCountObjectPtr bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree()); const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin()); - int nDescCell1=m1Desc->getNumberOfCells(); - int nDescCell2=m2Desc->getNumberOfCells(); + int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells()); intersectEdge1.resize(nDescCell1); colinear2.resize(nDescCell2); subDiv2.resize(nDescCell2); BBTree myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps); std::vector candidates1(1); - int offset1=m1->getNumberOfNodes(); - int offset2=offset1+m2->getNumberOfNodes(); + int offset1(m1Desc->getNumberOfNodes()); + int offset2(offset1+m2Desc->getNumberOfNodes()); for(int i=0;i candidates2; // edges of mesh2 candidate for intersection @@ -9111,13 +9970,40 @@ void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, c { (*itt)->incrRef(); nodesSafe[iii]=*itt; } // end of protection // Performs egde cutting: - pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo); + pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes); delete pol2; delete pol1; } else intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]); } +} + +/*! + * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2). + * It builds the descending connectivity of the two meshes, and then using a binary tree + * it computes the edge intersections. This results in new points being created : they're stored in addCoo. + * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs(). + */ +void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, + std::vector< std::vector >& intersectEdge1, std::vector< std::vector >& colinear2, std::vector< std::vector >& subDiv2, + MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1, + std::vector& addCoo, + MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2) +{ + // Build desc connectivity + desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New(); + desc2=DataArrayInt::New(); + descIndx2=DataArrayInt::New(); + revDesc2=DataArrayInt::New(); + revDescIndx2=DataArrayInt::New(); + MEDCouplingAutoRefCountObjectPtr dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1); + MEDCouplingAutoRefCountObjectPtr dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2); + m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1); + m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2); + MEDCouplingAutoRefCountObjectPtr dd9(m1Desc),dd10(m2Desc); + std::map notUsedMap; + Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap); m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef(); m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef(); } @@ -9137,8 +10023,8 @@ void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, c * \param[out] intersectEdge the same content as subDiv, but correclty oriented. */ void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, - const std::vector& addCoo, - const std::vector< std::vector >& subDiv, std::vector< std::vector >& intersectEdge) + const std::vector& addCoo, + const std::vector< std::vector >& subDiv, std::vector< std::vector >& intersectEdge) { int offset1=m1->getNumberOfNodes(); int ncell=m2->getNumberOfCells(); @@ -9203,7 +10089,7 @@ void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MED void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector& cut3DCurve, std::vector& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf, const int *nodal3DCurve, const int *nodalIndx3DCurve, const int *desc, const int *descIndx, - std::vector< std::pair >& cut3DSurf) throw(INTERP_KERNEL::Exception) + std::vector< std::pair >& cut3DSurf) { std::set nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end()); int nbOf3DSurfCell=(int)cut3DSurf.size(); @@ -9228,7 +10114,7 @@ void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector& cut3D } } switch(res.size()) - { + { case 2: { cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1]; @@ -9258,7 +10144,7 @@ void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector& cut3D else throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !"); } - } + } } } @@ -9273,7 +10159,7 @@ void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector& cut3D */ void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair >& cut3DSurf, const int *desc, const int *descIndx, - DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception) + DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const { checkFullyDefined(); if(getMeshDimension()!=3 || getSpaceDimension()!=3) @@ -9502,7 +10388,7 @@ bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, cons * \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) + DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) { if(!arrIn || !arrIndxIn) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !"); @@ -9574,7 +10460,7 @@ void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const * \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) + DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) { if(!arrIn || !arrIndxIn) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !"); @@ -9650,7 +10536,7 @@ void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOf */ void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex, - DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception) + DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) { if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !"); @@ -9713,7 +10599,7 @@ void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const in * \sa MEDCouplingUMesh::SetPartOfIndexedArrays */ void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn, - const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception) + const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) { if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !"); @@ -9855,7 +10741,7 @@ DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vecto */ void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex, - DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception) + DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) { if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !"); @@ -9917,7 +10803,7 @@ void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, con * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx */ void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn, - const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception) + const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) { if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !"); @@ -9976,7 +10862,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const MEDCouplingAutoRefCountObjectPtr tmp=static_cast(buildPartOfMySelf((*it)->begin(),(*it)->end(),true)); MEDCouplingAutoRefCountObjectPtr cell; switch(mdim) - { + { case 2: cell=tmp->buildUnionOf2DMesh(); break; @@ -9985,8 +10871,8 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const break; default: throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !"); - } - + } + ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1); } // @@ -10246,7 +11132,7 @@ bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg for(;nbOfHit m; + std::map,int> m; INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m)); posEndElt++; nbOfHit++; @@ -10284,6 +11170,8 @@ bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg } delete eint; eCand->decrRef(); + if(!isColinear) + break; } } break; @@ -10297,8 +11185,6 @@ bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg else EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles); posBaseElt=posEndElt; - for(std::map::const_iterator it=m.begin();it!=m.end();it++) - (*it).first->decrRef(); e->decrRef(); } if(!middles.empty()) @@ -10368,7 +11254,7 @@ int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const Data } MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)), - _own_cell(true),_cell_id(-1),_nb_cell(0) + _own_cell(true),_cell_id(-1),_nb_cell(0) { if(mesh) { @@ -10386,8 +11272,8 @@ MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator() } MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc), - _own_cell(false),_cell_id(bg-1), - _nb_cell(end) + _own_cell(false),_cell_id(bg-1), + _nb_cell(end) { if(mesh) mesh->incrRef(); @@ -10423,8 +11309,8 @@ MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry() } MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type), - _itc(itc), - _bg(bg),_end(end) + _itc(itc), + _bg(bg),_end(end) { if(_mesh) _mesh->incrRef();