Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/ccontour is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_ccontour
0005 #define tools_ccontour
0006 
0007 // G.Barrand : inline version of the one found in Lib of OSC 16.11.
0008 //             This code is not mine and I keep it "as it is".
0009 
0010 // Contour.h: interface for the ccontour class.
0011 //
0012 // ccontour implements Contour plot algorithm descrided in
0013 //              IMPLEMENTATION OF
0014 //              AN IMPROVED CONTOUR
0015 //              PLOTTING ALGORITHM
0016 //              BY
0017 //
0018 //              MICHAEL JOSEPH ARAMINI
0019 //
0020 //              B.S., Stevens Institute of Technology, 1980
0021 // See http://www.ultranet.com/~aramini/thesis.html
0022 //
0023 // Ported to C++ by Jonathan de Halleux.
0024 //
0025 // Using ccontour :
0026 //
0027 // ccontour is not directly usable. The user has to
0028 //      1. derive the function ExportLine that is
0029 //              supposed to draw/store the segment of the contour
0030 //      2. Set the function draw contour of. (using  SetFieldFn
0031 //              The function must be declared as follows
0032 //              double (*myF)(double x , double y);
0033 //
0034 //      History:
0035 //              31-07-2002:
0036 //                      - A lot of contribution from Chenggang Zhou (better strip compressions, merging, area, weight),
0037 //                      - Got rid of ugly MFC lists for STL.
0038 //////////////////////////////////////////////////////////////////////
0039 
0040 //G.Barrand :
0041 #include <vector>
0042 #include <cstdio>
0043 #include <cstdlib>
0044 #include <cmath>
0045 
0046 #include "mnmx"
0047 
0048 namespace tools {
0049 
0050 class ccontour
0051 {
0052 protected:
0053         // plots a line from (x1,y1) to (x2,y2)
0054         virtual void ExportLine(int iPlane,int x1,int y1,int x2,int y2) = 0;
0055 
0056 public:
0057         ccontour();
0058         virtual ~ccontour(){
0059           CleanMemory();
0060         }
0061 protected: //G.Barrand
0062         ccontour(const ccontour&){}
0063 private: //G.Barrand
0064         ccontour& operator=(const ccontour&){return *this;}
0065 public:
0066 protected: //G.Barrand
0067         // Initialize memory. Called in generate
0068         virtual void InitMemory();
0069         // Clean work arrays
0070         virtual void CleanMemory();
0071         // generates contour
0072         // Before calling this functions you must
0073         //      1. derive the function ExportLine that is
0074         //              supposed to draw/store the segment of the contour
0075         //      2. Set the function draw contour of. (using  SetFieldFn
0076         //              The function must be declared as follows
0077         //              double (*myF)(double x , double y);
0078 public: //G.Barrand
0079         virtual void generate();
0080 
0081         // Set the dimension of the primary grid
0082         void set_first_grid(int iCol, int iRow);
0083         // Set the dimension of the base grid
0084         void set_secondary_grid(int iCol, int iRow);
0085         // Sets the region [left, right, bottom,top] to generate contour
0086         void set_limits(double pLimits[4]);
0087         // Sets the isocurve values
0088         void set_planes(const std::vector<double>& vPlanes);
0089         // Sets the pointer to the F(x,y) funtion
0090         // G.Barrand : handle a user data pointer.
0091         void set_field_fcn(double (*_pFieldFcn)(double, double,void*),void*);
0092 
0093         size_t get_number_of_planes() const { return m_vPlanes.size();};
0094         const std::vector<double>& get_planes() const   {       return m_vPlanes;};
0095         double get_plane(unsigned int i)        const;
0096 
0097         // For an indexed point i on the sec. grid, returns x(i)
0098         double get_xi(int i) const {    return m_pLimits[0] +  i%(m_iColSec+1)*(m_pLimits[1]-m_pLimits[0])/(double)( m_iColSec );};
0099         // For an indexed point i on the fir. grid, returns y(i)
0100         double get_yi(int i) const;
0101 
0102         void get_limits(double pLimits[4]);
0103 protected: //G.Barrand
0104 
0105         // Retrieve dimension of grids, contouring region and isocurve
0106         int GetColFir() const           {       return m_iColFir;};
0107         int GetRowFir() const           {       return m_iRowFir;};
0108         int GetColSec() const           {       return m_iColSec;};
0109         int GetRowSec() const           {       return m_iRowSec;};
0110 
0111 private:
0112   class CFnStr {
0113   public:
0114     CFnStr():m_dFnVal(0),m_sLeftLen(0),m_sRightLen(0),m_sTopLen(0),m_sBotLen(0){
0115     }
0116     ~CFnStr(){
0117     }
0118   protected:
0119     CFnStr(const CFnStr&){}
0120     CFnStr& operator=(const CFnStr&){return *this;}
0121   public:
0122     double m_dFnVal;
0123     short m_sLeftLen;
0124     short m_sRightLen;
0125     short m_sTopLen;
0126     short m_sBotLen;
0127   };
0128 
0129 
0130 protected:
0131         // Accesibles variables
0132         std::vector<double> m_vPlanes;                  // value of contour planes
0133         double m_pLimits[4];                                            // left, right, bottom, top
0134         int m_iColFir;                                                          // primary      grid, number of columns
0135         int m_iRowFir;                                                          // primary      grid, number of rows
0136         unsigned int m_iColSec;                                                         // secondary grid, number of columns
0137         unsigned int m_iRowSec;                                                         // secondary grid, number of rows
0138         void* m_pFieldFcnData; // G.Barrand : handle a user data pointer.
0139         double (*m_pFieldFcn)(double x, double y,void*); // pointer to F(x,y) function
0140 
0141         // Work functions and variables
0142         double m_dDx;
0143         double m_dDy;
0144         CFnStr** m_ppFnData;    // pointer to mesh parts
0145         CFnStr* FnctData(int i,int j)  {        return (m_ppFnData[i]+j);};
0146 
0147         double Field(int x, int y);      /* evaluate funct if we must,  */
0148         void Cntr1(int x1, int x2, int y1, int y2);
0149         void Pass2(int x1, int x2, int y1, int y2);       /* draws the contour lines */
0150 
0151 private:
0152         //G.Barrand : have the below in the class.
0153         // A simple test function
0154         static double ContourTestFunction(double x,double y,void*) {
0155           return 0.5*(::cos(x+3.14/4)+::sin(y+3.14/4));
0156         }
0157 
0158 protected:
0159         static void _ASSERT_(bool a_what,const char* a_where) {
0160           if(!a_what) {
0161             ::printf("debug : Contour : assert failure in %s\n",a_where);
0162             ::exit(0);
0163           }
0164         }
0165 
0166         static void _ASSERTP_(void* a_what,const char* a_where) {
0167           if(!a_what) {
0168             ::printf("debug : Contour : assert failure in %s\n",a_where);
0169             ::exit(0);
0170           }
0171         }
0172 
0173 };
0174 
0175 // implementation :
0176 //
0177 //  Code get on the web at :
0178 //    http://www.codeproject.com/cpp/contour.asp
0179 //
0180 //  G.Barrand
0181 //
0182 
0183 //////////////////////////////////////////////////////////////////////
0184 // Construction/Destruction
0185 //////////////////////////////////////////////////////////////////////
0186 
0187 inline ccontour::ccontour()
0188 {
0189         m_iColFir=m_iRowFir=32;
0190         m_iColSec=m_iRowSec=256;
0191         m_dDx=m_dDy=0;
0192         m_pFieldFcnData = NULL;
0193         m_pFieldFcn=NULL;
0194         m_pLimits[0]=m_pLimits[2]=0;
0195         m_pLimits[1]=m_pLimits[3]=5.;
0196         m_ppFnData=NULL;
0197 
0198         // temporary stuff
0199         m_pFieldFcn=ContourTestFunction;
0200         m_vPlanes.resize(20);
0201         for (unsigned int i=0;i<m_vPlanes.size();i++)
0202         {
0203                 m_vPlanes[i]=(i-m_vPlanes.size()/2.0)*0.1;
0204         }
0205 }
0206 
0207 //G.Barrand : inline
0208 
0209 inline void ccontour::InitMemory()
0210 {
0211         if (!m_ppFnData)
0212         {
0213                 m_ppFnData=new CFnStr*[m_iColSec+1];
0214                 for (unsigned int i=0;i<m_iColSec+1;i++)
0215                 {
0216                         m_ppFnData[i]=NULL;
0217                 }
0218         }
0219 }
0220 
0221 inline void ccontour::CleanMemory()
0222 {
0223         if (m_ppFnData)
0224         {
0225                 for (unsigned int i=0;i<m_iColSec+1;i++)
0226                 {
0227                         if (m_ppFnData[i])
0228                                 delete[] (m_ppFnData[i]);
0229                 }
0230                 delete[] m_ppFnData;
0231                 m_ppFnData=NULL;
0232         }
0233 }
0234 
0235 inline void ccontour::generate()
0236 {
0237 
0238         int i, j;
0239         int x3, x4, y3, y4, x, y, oldx3, xlow;
0240         const unsigned int cols=m_iColSec+1;
0241         const unsigned int rows=m_iRowSec+1;
0242         //double xoff,yoff;
0243 
0244         // Initialize memroy if needed
0245         InitMemory();
0246 
0247         m_dDx = (m_pLimits[1]-m_pLimits[0])/(double)(m_iColSec);
0248         //xoff = m_pLimits[0];
0249         m_dDy = (m_pLimits[3]-m_pLimits[2])/(double)(m_iRowSec);
0250         //yoff = m_pLimits[2];
0251 
0252         xlow = 0;
0253         oldx3 = 0;
0254         x3 = (cols-1)/m_iRowFir;
0255         x4 = ( 2*(cols-1) )/m_iRowFir;
0256         for (x = oldx3; x <= x4; x++)
0257         {         /* allocate new columns needed
0258                 */
0259                 if (x >= (int)cols)
0260                         break;
0261                 if (m_ppFnData[x]==NULL)
0262                         m_ppFnData[x] = new CFnStr[rows];
0263 
0264                 for (y = 0; y < (int)rows; y++)
0265                         FnctData(x,y)->m_sTopLen = -1;
0266         }
0267 
0268         y4 = 0;
0269         for (j = 0; j < m_iColFir; j++)
0270         {
0271                 y3 = y4;
0272                 y4 = ((j+1)*(rows-1))/m_iColFir;
0273                 Cntr1(oldx3, x3, y3, y4);
0274         }
0275 
0276         for (i = 1; i < m_iRowFir; i++)
0277         {
0278                 y4 = 0;
0279                 for (j = 0; j < m_iColFir; j++)
0280                 {
0281                         y3 = y4;
0282                         y4 = ((j+1)*(rows-1))/m_iColFir;
0283                         Cntr1(x3, x4, y3, y4);
0284                 }
0285 
0286                 y4 = 0;
0287                 for (j = 0; j < m_iColFir; j++)
0288                 {
0289                         y3 = y4;
0290                         y4 = ((j+1)*(rows-1))/m_iColFir;
0291                         Pass2(oldx3,x3,y3,y4);
0292                 }
0293 
0294                 if (i < (m_iRowFir-1))
0295                 {        /* re-use columns no longer needed */
0296                         oldx3 = x3;
0297                         x3 = x4;
0298                         x4 = ((i+2)*(cols-1))/m_iRowFir;
0299                         for (x = x3+1; x <= x4; x++)
0300                         {
0301                                 if (xlow < oldx3)
0302                                 {
0303                                         if (m_ppFnData[x])
0304                                                 delete[] m_ppFnData[x];
0305                                         m_ppFnData[x] = m_ppFnData[xlow];
0306                                         m_ppFnData[ xlow++ ] = NULL;
0307                                 }
0308                                 else
0309                                         if (m_ppFnData[x]==NULL)
0310                                                 m_ppFnData[x] = new CFnStr[rows];
0311 
0312                                 for (y = 0; y < (int)rows; y++)
0313                                         FnctData(x,y)->m_sTopLen = -1;
0314                         }
0315                 }
0316         }
0317 
0318         y4 = 0;
0319         for (j = 0; j < m_iColFir; j++)
0320         {
0321                 y3 = y4;
0322                 y4 = ((j+1)*(rows-1))/m_iColFir;
0323                 Pass2(x3,x4,y3,y4);
0324         }
0325 }
0326 
0327 inline void ccontour::Cntr1(int x1, int x2, int y1, int y2)
0328 {
0329         double f11, f12, f21, f22, f33;
0330         int x3, y3, i, j;
0331 
0332         if ((x1 == x2) || (y1 == y2))   /* if not a real cell, punt */
0333                 return;
0334         f11 = Field(x1, y1);
0335         f12 = Field(x1, y2);
0336         f21 = Field(x2, y1);
0337         f22 = Field(x2, y2);
0338         if ((x2 > x1+1) || (y2 > y1+1)) {       /* is cell divisible? */
0339                 x3 = (x1+x2)/2;
0340                 y3 = (y1+y2)/2;
0341                 f33 = Field(x3, y3);
0342                 i = j = 0;
0343                 if (f33 < f11) i++; else if (f33 > f11) j++;
0344                 if (f33 < f12) i++; else if (f33 > f12) j++;
0345                 if (f33 < f21) i++; else if (f33 > f21) j++;
0346                 if (f33 < f22) i++; else if (f33 > f22) j++;
0347                 if ((i > 2) || (j > 2)) /* should we divide cell? */
0348                 {
0349                         /* subdivide cell */
0350                         Cntr1(x1, x3, y1, y3);
0351                         Cntr1(x3, x2, y1, y3);
0352                         Cntr1(x1, x3, y3, y2);
0353                         Cntr1(x3, x2, y3, y2);
0354                         return;
0355                 }
0356         }
0357         /* install cell in array */
0358         FnctData(x1,y2)->m_sBotLen = FnctData(x1,y1)->m_sTopLen = x2-x1;
0359         FnctData(x2,y1)->m_sLeftLen = FnctData(x1,y1)->m_sRightLen = y2-y1;
0360 }
0361 
0362 inline void ccontour::Pass2(int x1, int x2, int y1, int y2)
0363 {
0364         int left = 0, right = 0, top = 0, bot = 0,old, iNew, i, j, x3, y3;
0365         double yy0 = 0, yy1 = 0, xx0 = 0, xx1 = 0, xx3, yy3;
0366         double v, f11, f12, f21, f22, f33, fold, fnew, f;
0367         double xoff=m_pLimits[0];
0368         double yoff=m_pLimits[2];
0369 
0370         if ((x1 == x2) || (y1 == y2))   /* if not a real cell, punt */
0371                 return;
0372         f11 = FnctData(x1,y1)->m_dFnVal;
0373         f12 = FnctData(x1,y2)->m_dFnVal;
0374         f21 = FnctData(x2,y1)->m_dFnVal;
0375         f22 = FnctData(x2,y2)->m_dFnVal;
0376         if ((x2 > x1+1) || (y2 > y1+1)) /* is cell divisible? */
0377         {
0378                 x3 = (x1+x2)/2;
0379                 y3 = (y1+y2)/2;
0380                 f33 = FnctData(x3, y3)->m_dFnVal;
0381                 i = j = 0;
0382                 if (f33 < f11) i++; else if (f33 > f11) j++;
0383                 if (f33 < f12) i++; else if (f33 > f12) j++;
0384                 if (f33 < f21) i++; else if (f33 > f21) j++;
0385                 if (f33 < f22) i++; else if (f33 > f22) j++;
0386                 if ((i > 2) || (j > 2)) /* should we divide cell? */
0387                 {
0388                         /* subdivide cell */
0389                         Pass2(x1, x3, y1, y3);
0390                         Pass2(x3, x2, y1, y3);
0391                         Pass2(x1, x3, y3, y2);
0392                         Pass2(x3, x2, y3, y2);
0393                         return;
0394                 }
0395         }
0396 
0397         for (i = 0; i < (int)m_vPlanes.size(); i++)
0398         {
0399                 v = m_vPlanes[i];
0400                 j = 0;
0401                 if (f21 > v) j++;
0402                 if (f11 > v) j |= 2;
0403                 if (f22 > v) j |= 4;
0404                 if (f12 > v) j |= 010;
0405                 if ((f11 > v) ^ (f12 > v))
0406                 {
0407                         if ((FnctData(x1,y1)->m_sLeftLen != 0) &&
0408                                 (FnctData(x1,y1)->m_sLeftLen < FnctData(x1,y1)->m_sRightLen))
0409                         {
0410                                 old = y1;
0411                                 fold = f11;
0412                                 while (1)
0413                                 {
0414                                         iNew = old+FnctData(x1,old)->m_sLeftLen;
0415                                         fnew = FnctData(x1,iNew)->m_dFnVal;
0416                                         if ((fnew > v) ^ (fold > v))
0417                                                 break;
0418                                         old = iNew;
0419                                         fold = fnew;
0420                                 }
0421                                 yy0 = ((old-y1)+(iNew-old)*(v-fold)/(fnew-fold))/(y2-y1);
0422                         }
0423                         else
0424                                 yy0 = (v-f11)/(f12-f11);
0425 
0426                         left = (int)(y1+(y2-y1)*yy0+0.5);
0427                 }
0428                 if ((f21 > v) ^ (f22 > v))
0429                 {
0430                         if ((FnctData(x2,y1)->m_sRightLen != 0) &&
0431                                 (FnctData(x2,y1)->m_sRightLen < FnctData(x2,y1)->m_sLeftLen))
0432                         {
0433                                 old = y1;
0434                                 fold = f21;
0435                                 while (1)
0436                                 {
0437                                         iNew = old+FnctData(x2,old)->m_sRightLen;
0438                                         fnew = FnctData(x2,iNew)->m_dFnVal;
0439                                         if ((fnew > v) ^ (fold > v))
0440                                                 break;
0441                                         old = iNew;
0442                                         fold = fnew;
0443                                 }
0444                                 yy1 = ((old-y1)+(iNew-old)*(v-fold)/(fnew-fold))/(y2-y1);
0445                         }
0446                         else
0447                                 yy1 = (v-f21)/(f22-f21);
0448 
0449                         right = (int)(y1+(y2-y1)*yy1+0.5);
0450                 }
0451                 if ((f21 > v) ^ (f11 > v))
0452                 {
0453                         if ((FnctData(x1,y1)->m_sBotLen != 0) &&
0454                                 (FnctData(x1,y1)->m_sBotLen < FnctData(x1,y1)->m_sTopLen)) {
0455                                 old = x1;
0456                                 fold = f11;
0457                                 while (1) {
0458                                         iNew = old+FnctData(old,y1)->m_sBotLen;
0459                                         fnew = FnctData(iNew,y1)->m_dFnVal;
0460                                         if ((fnew > v) ^ (fold > v))
0461                                                 break;
0462                                         old = iNew;
0463                                         fold = fnew;
0464                                 }
0465                                 xx0 = ((old-x1)+(iNew-old)*(v-fold)/(fnew-fold))/(x2-x1);
0466                         }
0467                         else
0468                                 xx0 = (v-f11)/(f21-f11);
0469 
0470                         bot = (int)(x1+(x2-x1)*xx0+0.5);
0471                 }
0472                 if ((f22 > v) ^ (f12 > v))
0473                 {
0474                         if ((FnctData(x1,y2)->m_sTopLen != 0) &&
0475                                 (FnctData(x1,y2)->m_sTopLen < FnctData(x1,y2)->m_sBotLen)) {
0476                                 old = x1;
0477                                 fold = f12;
0478                                 while (1) {
0479                                         iNew = old+FnctData(old,y2)->m_sTopLen;
0480                                         fnew = FnctData(iNew,y2)->m_dFnVal;
0481                                         if ((fnew > v) ^ (fold > v))
0482                                                 break;
0483                                         old = iNew;
0484                                         fold = fnew;
0485                                 }
0486                                 xx1 = ((old-x1)+(iNew-old)*(v-fold)/(fnew-fold))/(x2-x1);
0487                         }
0488                         else
0489                                 xx1 = (v-f12)/(f22-f12);
0490 
0491                         top = (int)(x1+(x2-x1)*xx1+0.5);
0492                 }
0493 
0494                 switch (j)
0495                 {
0496                         case 7:
0497                         case 010:
0498                                 ExportLine(i,x1,left,top,y2);
0499                                 break;
0500                         case 5:
0501                         case 012:
0502                                 ExportLine(i,bot,y1,top,y2);
0503                                 break;
0504                         case 2:
0505                         case 015:
0506                                 ExportLine(i,x1,left,bot,y1);
0507                         break;
0508                 case 4:
0509                 case 013:
0510                         ExportLine(i,top,y2,x2,right);
0511                         break;
0512                 case 3:
0513                 case 014:
0514                         ExportLine(i,x1,left,x2,right);
0515                         break;
0516                 case 1:
0517                 case 016:
0518                         ExportLine(i,bot,y1,x2,right);
0519                         break;
0520                 case 0:
0521                 case 017:
0522                         break;
0523                 case 6:
0524                 case 011:
0525                         yy3 = (xx0*(yy1-yy0)+yy0)/(1.0-(xx1-xx0)*(yy1-yy0));
0526                         xx3 = yy3*(xx1-xx0)+xx0;
0527                         xx3 = x1+xx3*(x2-x1);
0528                         yy3 = y1+yy3*(y2-y1);
0529                         xx3 = xoff+xx3*m_dDx;
0530                         yy3 = yoff+yy3*m_dDy;
0531                         f = (*m_pFieldFcn)(xx3, yy3,m_pFieldFcnData);
0532                         if (f == v) {
0533                                 ExportLine(i,bot,y1,top,y2);
0534                                 ExportLine(i,x1,left,x2,right);
0535                         } else
0536                                 if (((f > v) && (f22 > v)) || ((f < v) && (f22 < v))) {
0537                                         ExportLine(i,x1,left,top,y2);
0538                                         ExportLine(i,bot,y1,x2,right);
0539                                 } else {
0540                                         ExportLine(i,x1,left,bot,y1);
0541                                         ExportLine(i,top,y2,x2,right);
0542                                 }
0543                 }
0544         }
0545 }
0546 
0547 inline double ccontour::Field(int x, int y)  /* evaluate funct if we must,*/
0548 {
0549         double x1, y1;
0550 
0551         if (FnctData(x,y)->m_sTopLen != -1)  /* is it already in the array */
0552                 return(FnctData(x,y)->m_dFnVal);
0553 
0554         /* not in the array, create new array element */
0555         x1 = m_pLimits[0]+m_dDx*x;
0556         y1 = m_pLimits[2]+m_dDy*y;
0557         FnctData(x,y)->m_sTopLen = 0;
0558         FnctData(x,y)->m_sBotLen = 0;
0559         FnctData(x,y)->m_sRightLen = 0;
0560         FnctData(x,y)->m_sLeftLen = 0;
0561         return (FnctData(x,y)->m_dFnVal = (*m_pFieldFcn)(x1, y1,m_pFieldFcnData));
0562 }
0563 
0564 inline void ccontour::set_planes(const std::vector<double>& vPlanes)
0565 {
0566         // cleaning memory
0567         CleanMemory();
0568 
0569         m_vPlanes = vPlanes;
0570 }
0571 
0572 inline void ccontour::set_field_fcn(double (*_pFieldFcn)(double, double,void*),void* aData)
0573 {
0574         m_pFieldFcnData = aData;
0575         m_pFieldFcn=_pFieldFcn;
0576 }
0577 
0578 inline void ccontour::set_first_grid(int iCol, int iRow)
0579 {
0580         m_iColFir=max_of<int>(iCol,2);
0581         m_iRowFir=max_of<int>(iRow,2);
0582 }
0583 
0584 inline void ccontour::set_secondary_grid(int iCol, int iRow)
0585 {
0586         // cleaning work matrices if allocated
0587         CleanMemory();
0588 
0589         m_iColSec=max_of<int>(iCol,2);
0590         m_iRowSec=max_of<int>(iRow,2);
0591 }
0592 
0593 inline void ccontour::set_limits(double pLimits[4])
0594 {
0595         _ASSERT_(pLimits[0]<pLimits[1],"ccontour::set_limits");
0596         _ASSERT_(pLimits[2]<pLimits[3],"ccontour::set_limits");
0597         for (int i=0;i<4;i++)
0598         {
0599                 m_pLimits[i]=pLimits[i];
0600         }
0601 }
0602 
0603 inline void ccontour::get_limits(double pLimits[4])
0604 {
0605         for (int i=0;i<4;i++)
0606         {
0607                 pLimits[i]=m_pLimits[i];
0608         }
0609 }
0610 
0611 //G.Barrand : from .h to .cxx to avoid _ASSERT_ in .h
0612 inline double ccontour::get_plane(unsigned int i) const {
0613   /*_ASSERT_(i>=0);*/
0614   _ASSERT_(i<m_vPlanes.size(),"ccontour::get_plane");
0615   return m_vPlanes[i];
0616 }
0617 
0618 inline double ccontour::get_yi(int i) const {
0619   if(i<0) ::printf("ccontour::get_yi : %d\n",i);
0620   _ASSERT_(i>=0,"ccontour::get_yi");
0621   return m_pLimits[2] +  i/(m_iColSec+1)*(m_pLimits[3]-m_pLimits[2])/(double)( m_iRowSec );
0622 }
0623 
0624 }
0625 
0626 #endif