return 0;
}
+/*!
+ * See MEDCouplingUMesh::splitProfilePerType for more information
+ */
+void MEDCouplingCMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
+{
+ int nbCells=getNumberOfCells();
+ code.resize(3);
+ code[0]=(int)getTypeOfCell(0);
+ code[1]=nbCells;
+ code[2]=0;
+ idsPerType.push_back(profile->deepCpy());
+}
+
MEDCouplingUMesh *MEDCouplingCMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
{
int spaceDim=getSpaceDimension();
const DataArrayDouble *coordsZ=0);
// tools
DataArrayInt *checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
+ void splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
MEDCouplingUMesh *buildUnstructured() const throw(INTERP_KERNEL::Exception);
MEDCouplingMesh *buildPart(const int *start, const int *end) const;
MEDCouplingMesh *buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const;
throw INTERP_KERNEL::Exception("Not implemented yet !");
}
+void MEDCouplingExtrudedMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
+{
+ throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
MEDCouplingMesh *MEDCouplingExtrudedMesh::buildPart(const int *start, const int *end) const
{
// not implemented yet !
void translate(const double *vector);
void scale(const double *point, double factor);
DataArrayInt *checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
+ void splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
MEDCouplingMesh *buildPart(const int *start, const int *end) const;
MEDCouplingMesh *buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const;
DataArrayInt *simplexize(int policy) throw(INTERP_KERNEL::Exception);
declareAsNew();
}
+/*!
+ * 'this' should be allocated and with numberOfComponents set to one. If not an exception will be thrown.
+ * This method takes as input an array defined by ['arrBg','arrEnd'). The size of the array (std::distance(arrBg,arrEnd)) is equal to the number of cast + 1.
+ * The values contained in ['arrBg','arrEnd') should be sorted ascendently. No check of this will be done. If not the result is not waranted.
+ * For each cast j the value range that defines the cast is equal to [arrBg[j],arrBg[j+1]).
+ * This method returns three arrays (to be managed by the caller).
+ * This method is typically usefull for entity number spliting by types for example.
+ * Example : If 'this' contains [6,5,0,3,2,7,8,1,4] and if ['arrBg','arrEnd') contains [0,4,9] then the output of this method will be :
+ * - 'castArr' : [1,1,0,0,0,1,1,0,1]
+ * - 'rankInsideCast' : [2,1,0,3,2,3,4,1,0]
+ * - 'return' : [0,1]
+ *
+ * @param castArr is a returned param has the same number of tuples than 'this' and number of components set to one. In case of sucess, this param contains for each tuple in 'this' in which cast it holds.
+ * @param rankInsideCast is an another returned param has the same number of tuples than 'this' and number of components set to one too. In case of sucess, this param contains for each tuple its rank inside its cast.
+ * @param castsPresent the casts that 'this' contains.
+ * @throw if a value in 'this' is greater or equal to the last value of ['arrBg','arrEnd')
+ */
+void DataArrayInt::splitByValueRange(const int *arrBg, const int *arrEnd,
+ DataArrayInt *& castArr, DataArrayInt *& rankInsideCast, DataArrayInt *& castsPresent) const throw(INTERP_KERNEL::Exception)
+{
+ if(getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("Call splitByValueRange method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ int nbOfTuples=getNumberOfTuples();
+ std::size_t nbOfCast=std::distance(arrBg,arrEnd);
+ if(nbOfCast<2)
+ throw INTERP_KERNEL::Exception("DataArrayInt::splitByValueRange : The input array giving the cast range values should be of size >=2 !");
+ nbOfCast--;
+ const int *work=getConstPointer();
+ typedef std::reverse_iterator<const int *> rintstart;
+ rintstart bg(arrEnd);//OK no problem because size of 'arr' is greater of equal 2
+ rintstart end(arrBg);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=DataArrayInt::New();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3=DataArrayInt::New();
+ ret1->alloc(nbOfTuples,1);
+ ret2->alloc(nbOfTuples,1);
+ int *ret1Ptr=ret1->getPointer();
+ int *ret2Ptr=ret2->getPointer();
+ std::set<std::size_t> castsDetected;
+ for(int i=0;i<nbOfTuples;i++)
+ {
+ rintstart res=std::find_if(bg,end,std::bind2nd(std::less_equal<int>(), work[i]));
+ std::size_t pos=std::distance(bg,res);
+ std::size_t pos2=nbOfCast-pos;
+ if(pos2<nbOfCast)
+ {
+ ret1Ptr[i]=(int)pos2;
+ ret2Ptr[i]=work[i]-arrBg[pos2];
+ castsDetected.insert(pos2);
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::splitByValueRange : At rank #" << i << " the value is " << work[i] << " whereas the last value is " << *bg;
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ ret3->alloc((int)castsDetected.size(),1);
+ std::copy(castsDetected.begin(),castsDetected.end(),ret3->getPointer());
+ ret1->incrRef();
+ castArr=ret1;
+ ret2->incrRef();
+ rankInsideCast=ret2;
+ ret3->incrRef();
+ castsPresent=ret3;
+}
+
DataArrayInt *DataArrayInt::transformWithIndArrR(const int *indArrBg, const int *indArrEnd) const throw(INTERP_KERNEL::Exception)
{
if(getNumberOfComponents()!=1)
MEDCOUPLING_EXPORT void reprZipWithoutNameStream(std::ostream& stream) const;
MEDCOUPLING_EXPORT void transformWithIndArr(const int *indArrBg, const int *indArrEnd) throw(INTERP_KERNEL::Exception);
MEDCOUPLING_EXPORT DataArrayInt *transformWithIndArrR(const int *indArrBg, const int *indArrEnd) const throw(INTERP_KERNEL::Exception);
+ MEDCOUPLING_EXPORT void splitByValueRange(const int *arrBg, const int *arrEnd,
+ DataArrayInt *& castArr, DataArrayInt *& rankInsideCast, DataArrayInt *& castsPresent) const throw(INTERP_KERNEL::Exception);
MEDCOUPLING_EXPORT DataArrayInt *invertArrayO2N2N2O(int newNbOfElem) const;
MEDCOUPLING_EXPORT DataArrayInt *invertArrayN2O2O2N(int oldNbOfElem) const;
//!alloc or useArray should have been called before.
virtual std::string advancedRepr() const = 0;
// tools
virtual DataArrayInt *checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception) = 0;
+ virtual void splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception) = 0;
virtual void getBoundingBox(double *bbox) const = 0;
virtual MEDCouplingFieldDouble *getMeasureField(bool isAbs) const = 0;
virtual MEDCouplingFieldDouble *getMeasureFieldOnNode(bool isAbs) const = 0;
return ret;
}
+/*!
+ * This method makes the hypothesis that 'this' is sorted by type. If not an exception will be thrown.
+ * This method is the opposite of MEDCouplingUMesh::checkTypeConsistencyAndContig method. Given a list of cells in 'profile' it returns a list of profiles sorted by geo type.
+ * This method has 1 input 'profile' and 2 outputs 'code' and 'idsPerType'.
+ * @throw if 'profile' has not exactly one component. It throws too, if 'profile' contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
+ */
+void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
+{
+ if(profile->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
+ checkConnectivityFullyDefined();
+ const int *conn=_nodal_connec->getConstPointer();
+ const int *connI=_nodal_connec_index->getConstPointer();
+ int nbOfCells=getNumberOfCells();
+ std::vector<INTERP_KERNEL::NormalizedCellType> types;
+ std::vector<int> typeRangeVals(1);
+ for(const int *i=connI;i!=connI+nbOfCells;)
+ {
+ INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
+ if(std::find(types.begin(),types.end(),curType)!=types.end())
+ {
+ throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
+ }
+ types.push_back(curType);
+ i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
+ typeRangeVals.push_back(std::distance(connI,i));
+ }
+ //
+ DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
+ profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
+ //
+ int nbOfCastsFinal=castsPresent->getNumberOfTuples();
+ code.resize(3*nbOfCastsFinal);
+ std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
+ for(int i=0;i<nbOfCastsFinal;i++)
+ {
+ int castId=castsPresent->getIJ(i,0);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
+ code[3*i]=(int)types[castId];
+ code[3*i+1]=tmp3->getNumberOfTuples();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
+ if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
+ {
+ idsPerType2.push_back(tmp4);
+ code[3*i+2]=(int)idsPerType2.size()-1;
+ }
+ else
+ {
+ code[3*i+2]=-1;
+ }
+ }
+ int sz=idsPerType2.size();
+ idsPerType.resize(sz);
+ for(int i=0;i<sz;i++)
+ {
+ DataArrayInt *locDa=idsPerType2[i];
+ locDa->incrRef();
+ idsPerType[i]=locDa;
+ }
+}
+
/*!
* This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
* This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
{
INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
if(types.find(curType)!=types.end())
- return false;
+ return false;
types.insert(curType);
i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
}
MEDCOUPLING_EXPORT MEDCouplingFieldDouble *getSkewField() const throw(INTERP_KERNEL::Exception);
//utilities for MED File RW
MEDCOUPLING_EXPORT DataArrayInt *checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
+ MEDCOUPLING_EXPORT void splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
MEDCOUPLING_EXPORT MEDCouplingUMesh *emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception);
MEDCOUPLING_EXPORT DataArrayInt *sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception);
MEDCOUPLING_EXPORT bool checkConsecutiveCellTypes() const;
throw INTERP_KERNEL::Exception("Not implemented yet !");
}
+void MEDCouplingUMeshDesc::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
+{
+ throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
void MEDCouplingUMeshDesc::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
{
MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
MEDCOUPLING_EXPORT void setConnectivity(DataArrayInt *descConn, DataArrayInt *descConnIndex, DataArrayInt *nodalFaceConn, DataArrayInt *nodalFaceConnIndx);
//tools to overload
MEDCOUPLING_EXPORT DataArrayInt *checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
+ MEDCOUPLING_EXPORT void splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception);
MEDCOUPLING_EXPORT void getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const;
MEDCOUPLING_EXPORT bool isEmptyMesh(const std::vector<int>& tinyInfo) const;
MEDCOUPLING_EXPORT void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const;
CPPUNIT_TEST( testSortCellsInMEDFileFrmt1 );
CPPUNIT_TEST( testBuildPartAndReduceNodes1 );
CPPUNIT_TEST( testDAITransformWithIndArrR1 );
+ CPPUNIT_TEST( testDAISplitByValueRange1 );
+ CPPUNIT_TEST( testUMeshSplitProfilePerType1 );
//MEDCouplingBasicsTestInterp.cxx
CPPUNIT_TEST( test2DInterpP0P0_1 );
CPPUNIT_TEST( test2DInterpP0P0PL_1 );
void testSortCellsInMEDFileFrmt1();
void testBuildPartAndReduceNodes1();
void testDAITransformWithIndArrR1();
+ void testDAISplitByValueRange1();
+ void testUMeshSplitProfilePerType1();
//MEDCouplingBasicsTestInterp.cxx
void test2DInterpP0P0_1();
void test2DInterpP0P0PL_1();
d->decrRef();
d1->decrRef();
}
+
+void MEDCouplingBasicsTest::testDAISplitByValueRange1()
+{
+ const int val1[9]={6,5,0,3,2,7,8,1,4};
+ const int val2[3]={0,4,9};
+ DataArrayInt *d=DataArrayInt::New();
+ d->alloc(9,1);
+ std::copy(val1,val1+9,d->getPointer());
+ DataArrayInt *e=0,*f=0,*g=0;
+ d->splitByValueRange(val2,val2+3,e,f,g);
+ CPPUNIT_ASSERT_EQUAL(9,e->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(1,e->getNumberOfComponents());
+ CPPUNIT_ASSERT_EQUAL(9,f->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(1,f->getNumberOfComponents());
+ CPPUNIT_ASSERT_EQUAL(2,g->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(1,g->getNumberOfComponents());
+ //
+ const int expected1[9]={1,1,0,0,0,1,1,0,1};
+ const int expected2[9]={2,1,0,3,2,3,4,1,0};
+ for(int i=0;i<9;i++)
+ {
+ CPPUNIT_ASSERT_EQUAL(expected1[i],e->getIJ(i,0));
+ CPPUNIT_ASSERT_EQUAL(expected2[i],f->getIJ(i,0));
+ }
+ CPPUNIT_ASSERT_EQUAL(0,g->getIJ(0,0));
+ CPPUNIT_ASSERT_EQUAL(1,g->getIJ(1,0));
+ //
+ e->decrRef();
+ f->decrRef();
+ g->decrRef();
+ //
+ d->setIJ(6,0,9);
+ CPPUNIT_ASSERT_THROW(d->splitByValueRange(val2,val2+3,e,f,g),INTERP_KERNEL::Exception);
+ //
+ d->decrRef();
+}
+
+void MEDCouplingBasicsTest::testUMeshSplitProfilePerType1()
+{
+ const int val0[5]={2,0,1,3,4};
+ MEDCouplingUMesh *m=build2DTargetMesh_1();
+ m->renumberCells(val0,false);
+ std::vector<int> code;
+ std::vector<DataArrayInt *> pfls;
+ //
+ const int val1[3]={0,2,3};
+ DataArrayInt *d=DataArrayInt::New();
+ d->alloc(3,1);
+ std::copy(val1,val1+3,d->getPointer());
+ m->splitProfilePerType(d,code,pfls);
+ CPPUNIT_ASSERT_EQUAL(6,(int)code.size());
+ const int expected1[6]={3,1,0, 4,2,1};
+ for(int i=0;i<6;i++)
+ CPPUNIT_ASSERT_EQUAL(expected1[i],code[i]);
+ CPPUNIT_ASSERT_EQUAL(2,(int)pfls.size());
+ CPPUNIT_ASSERT_EQUAL(1,pfls[0]->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(0,pfls[0]->getIJ(0,0));
+ CPPUNIT_ASSERT_EQUAL(2,pfls[1]->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(0,pfls[1]->getIJ(0,0));
+ CPPUNIT_ASSERT_EQUAL(1,pfls[1]->getIJ(1,0));
+ pfls[0]->decrRef();
+ pfls[1]->decrRef();
+ d->decrRef();
+ pfls.clear();
+ code.clear();
+ //
+ const int val2[4]={0,2,3,4};// all quad4 are selected here ! So no profile for Quads
+ d=DataArrayInt::New();
+ d->alloc(4,1);
+ std::copy(val2,val2+4,d->getPointer());
+ m->splitProfilePerType(d,code,pfls);
+ CPPUNIT_ASSERT_EQUAL(6,(int)code.size());
+ const int expected2[6]={3,1,0, 4,3,-1};
+ for(int i=0;i<6;i++)
+ CPPUNIT_ASSERT_EQUAL(expected2[i],code[i]);
+ CPPUNIT_ASSERT_EQUAL(1,(int)pfls.size());
+ CPPUNIT_ASSERT_EQUAL(1,pfls[0]->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(0,pfls[0]->getIJ(0,0));
+ pfls[0]->decrRef();
+ d->decrRef();
+ pfls.clear();
+ code.clear();
+ //
+ const int val3[3]={1,0,2};// all tri3 are selected here but not in the same order ! Profile requested for Tri3
+ d=DataArrayInt::New();
+ d->alloc(3,1);
+ std::copy(val3,val3+3,d->getPointer());
+ m->splitProfilePerType(d,code,pfls);
+ CPPUNIT_ASSERT_EQUAL(6,(int)code.size());
+ const int expected3[6]={3,2,0, 4,1,1};
+ for(int i=0;i<6;i++)
+ CPPUNIT_ASSERT_EQUAL(expected3[i],code[i]);
+ CPPUNIT_ASSERT_EQUAL(2,(int)pfls.size());
+ CPPUNIT_ASSERT_EQUAL(2,pfls[0]->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(1,pfls[0]->getIJ(0,0));
+ CPPUNIT_ASSERT_EQUAL(0,pfls[0]->getIJ(1,0));
+ CPPUNIT_ASSERT_EQUAL(0,pfls[1]->getIJ(0,0));
+ pfls[0]->decrRef();
+ pfls[1]->decrRef();
+ d->decrRef();
+ pfls.clear();
+ code.clear();
+ //
+ const int val4[2]={3,4};// all tri3 are selected here but not in the same order ! Profile requested for Tri3
+ d=DataArrayInt::New();
+ d->alloc(2,1);
+ std::copy(val4,val4+2,d->getPointer());
+ m->splitProfilePerType(d,code,pfls);
+ CPPUNIT_ASSERT_EQUAL(3,(int)code.size());
+ const int expected4[3]={4,2,0};
+ for(int i=0;i<3;i++)
+ CPPUNIT_ASSERT_EQUAL(expected4[i],code[i]);
+ CPPUNIT_ASSERT_EQUAL(1,(int)pfls.size());
+ CPPUNIT_ASSERT_EQUAL(2,pfls[0]->getNumberOfTuples());
+ CPPUNIT_ASSERT_EQUAL(1,pfls[0]->getIJ(0,0));
+ CPPUNIT_ASSERT_EQUAL(2,pfls[0]->getIJ(1,0));
+ pfls[0]->decrRef();
+ d->decrRef();
+ pfls.clear();
+ code.clear();
+ //
+ m->decrRef();
+}