Virtual U.org
Get Personal Training on VU Today
    
Top shadow
 
 register/help
User Name:

Password:

OPIECHRT.CPP Source File
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

OPIECHRT.CPP

Go to the documentation of this file.
00001 //Filename    : OPIECHRT.CPP
00002 //Description : Object PieChart
00003 //Owner                 : Kevin(Ho)
00004 
00005 #include <ALL.H>
00006 #include <COLOR.H>
00007 #include <OINFO.H>
00008 #include <OVGA.H>
00009 #include <OSYS.H>
00010 #include <OFONT.H>
00011 #include <OMOUSE.H>
00012 #include <OPIECHRT.H>
00013 #include <OIFACE.H>
00014 
00015 #include <math.h>
00016 
00017 //--------- Define macro constant -----------//
00018 
00019 #define MAX_LEN_LABEL "000"
00020 
00021 static int default_series_color[] = {
00022     V_BLUE,
00023     V_GREEN,
00024     V_RED,
00025     V_YELLOW,
00026     V_VIOLET,
00027     V_BROWN,
00028     V_ORANGE,
00029     V_PINK,
00030     V_BLACK,
00031     V_WHITE,
00032 };                                                // 10 default series colors
00033 
00034 enum {  DEFAULT_SERIES_COLOR_NUM = 10 };
00035 
00036 enum {
00037     LEGEND_SIZE = 11,
00038     LEGEND_X_SPACING = 12,
00039     LEGEND_Y_SPACING = 2,
00040 };
00041 
00042 enum {  COMMON_OFFSET = 2         };
00043 
00044 //-------------- Define static vars ------------//
00045 
00046 //static char paint_flag = 0;
00047 
00048 //-------- Begin of function PieChart::PieChart ----//
00050 PieChart::PieChart() {
00051     init_flag = 0;
00052     piechart_bitmap = NULL;
00053 }
00054 
00055 //---------- End of function PieChart::PieChart ----//
00056 
00057 //-------- Begin of function PieChart::~PieChart -----//
00059 PieChart::~PieChart() {
00060     deinit();
00061 }
00062 
00063 //---------- End of function PieChart::~PieChart -----//
00064 
00065 //-------- Begin of function PieChart::init --------//
00098 void PieChart::init(int x1, int y1, int x2, int y2, int dataNum,
00099                     void *dataArray, char dataTypeFlag,
00100                     int *xStart, int *xEnd, char *xLabel, char *yLabel,
00101                     char **legendArray, char transparentFlag,
00102                     char orientationFlag, char valueFlag,
00103                     int numFormat, int *seriesColor, int axisColor) {
00104     err_when(dataNum > DEFAULT_SERIES_COLOR_NUM && !seriesColor);
00105     err_when(dataNum <= 0);
00106     err_when(*xEnd < *xStart);
00107 
00108     graph_width = x2 - x1 - 6;
00109 
00110     err_when(graph_width < 0);
00111 
00112     piechart_x1 = x1;
00113     piechart_y1 = y1;
00114     piechart_x2 = x2;
00115     piechart_y2 = y2;
00116 
00117     centerx = (piechart_x1+piechart_x2)/2;
00118     centery = (piechart_y1+piechart_y2)/2;
00119     int radius1 = (piechart_x2-piechart_x1)/2-3*COMMON_OFFSET;
00120     int radius2 = (piechart_y2-piechart_y1)/2-3*COMMON_OFFSET;
00121     radius = (radius1>radius2)?radius2:radius1;
00122     series_num = dataNum;
00123     data_num = dataNum;
00124     data_array = dataArray;
00125     data_type_flag = dataTypeFlag;
00126     x_start = xStart;
00127     x_end = xEnd;
00128 
00129     x_label = xLabel;
00130     y_label = yLabel;
00131     legend_array = legendArray;
00132 
00133     transparent_flag = transparentFlag;
00134     orientation_flag = orientationFlag;
00135     value_flag = valueFlag;
00136     num_format = num_format;
00137 
00138     series_color = seriesColor ? seriesColor : default_series_color;
00139     axis_color = axisColor;
00140 
00141     init_flag = 1;
00142 
00143     y_label_max_len = font_chartsm.text_width(MAX_LEN_LABEL);
00144     set_font(&font_chartsm);
00145 
00146 }
00147 
00148 //------------- End of function PieChart::init -----------//
00149 
00150 //-------- Begin of function PieChart::deinit ------------//
00152 void PieChart::deinit() {
00153     if (piechart_bitmap) {
00154         mem_del(piechart_bitmap);
00155         piechart_bitmap = NULL;
00156     }
00157 
00158     init_flag = 0;
00159 }
00160 
00161 //------------- End of function PieChart::deinit ---------//
00162 
00163 //-------- Begin of function PieChart::set_font ------------//
00165 void PieChart::set_font(Font *fontPtr) {
00166     if (!init_flag)
00167         return;
00168 
00169     font_ptr = fontPtr;
00170 
00171     calc_pos();
00172 }
00173 
00174 //------------- End of function PieChart::set_font ---------//
00175 
00176 //-------- Begin of function PieChart::calc_pos ------------//
00181 void PieChart::calc_pos() {
00182     if (legend_array) {
00183         short textWidth = 0, textHeight = font_ptr->max_font_height;
00184 
00185         for (int i = 0; i < series_num; i++) {
00186             if (font_ptr->text_width(legend_array[i]) > textWidth)
00187                 textWidth = font_ptr->text_width(legend_array[i]);
00188         }
00189 
00190         err_when(textWidth + LEGEND_X_SPACING * 2 > graph_width);
00191 
00192         legend_x_num = (graph_width - LEGEND_X_SPACING*2) / (textWidth + LEGEND_X_SPACING*2);
00193         legend_y_num = (series_num / legend_x_num) + ((series_num % legend_x_num) ? 1 : 0);
00194 
00195         graph_height = piechart_y2 - piechart_y1 - legend_y_num * (textHeight + LEGEND_Y_SPACING) - 6;
00196 
00197         err_when(graph_height <= 0);
00198 
00199         legend_width = (graph_width - LEGEND_X_SPACING*2) / legend_x_num;
00200         legend_height = textHeight + LEGEND_Y_SPACING;
00201     }
00202     else {
00203         legend_width = legend_height = legend_x_num = legend_y_num = 0;
00204         graph_height = piechart_y2 - piechart_y1 - 6;
00205     }
00206 
00207     short YLabelWidth = y_label ? (orientation_flag ? font_ptr->max_font_height : font_ptr->text_width(y_label)) : -COMMON_OFFSET;
00208     short XLabelHeight = x_label ? (font_ptr->max_font_height) : -COMMON_OFFSET;
00209     series_x1 = piechart_x1 + 4 + COMMON_OFFSET*4 + YLabelWidth + y_label_max_len;
00210     series_y1 = piechart_y1 + 4 + COMMON_OFFSET*6;
00211     series_x2 = piechart_x2 - 4 - COMMON_OFFSET*12;
00212     series_y2 = piechart_y1 + graph_height - COMMON_OFFSET*3 - (font_ptr->max_font_height) - XLabelHeight;
00213 }
00214 
00215 //------------ End of function PieChart::calc_pos ---------//
00216 
00217 //-------- Begin of function PieChart::paint --------------//
00219 void PieChart::paint() {
00220     if (transparent_flag) {
00221         user_interface.brighten(piechart_x1+4, piechart_y1+4, piechart_x2-2, piechart_y2-2);
00222         piechart_bitmap = vga_back.save_area(piechart_x1+4, piechart_y1+4, piechart_x2-2, piechart_y2-2, piechart_bitmap);
00223     }
00224 
00225     //  paint_flag = 1;
00226     refresh();
00227 }
00228 
00229 //------------- End of function PieChart::paint -----------//
00230 
00231 //-------- Begin of function PieChart::refresh ------------//
00233 void PieChart::refresh() {
00234     //  vga.use_back();
00235 
00236     if (transparent_flag) {
00237         user_interface.rect(piechart_x1, piechart_y1, piechart_x2, piechart_y2, 1);
00238         vga_back.rest_area(piechart_bitmap, 0, 0);
00239     }
00240     else {
00241         user_interface.bar(piechart_x1, piechart_y1, piechart_x2, piechart_y2);
00242         user_interface.panel(piechart_x1+3, piechart_y1+3, piechart_x2-4, piechart_y2-4);
00243     }
00244     draw_series();
00245 
00246     //  if (paint_flag)
00247     //          paint_flag = 0;
00248     //          vga.blt_buf(piechart_x1, piechart_y1, piechart_x2+2, piechart_y2+2);
00249     //  else
00250 
00251 }
00252 
00253 //------------- End of function PieChart::refresh ---------//
00254 
00255 //---------- Begin of function PieChart::draw_legend ------------//
00257 void PieChart::draw_legend() {
00258     for (int i = 0; i < series_num; i++) {
00259         short legendX = piechart_x1 + 4 + (i % legend_x_num) * legend_width + LEGEND_X_SPACING;
00260         short legendY = piechart_y1 + 4 + graph_height + (i / legend_x_num) * legend_height;
00261         user_interface.bar( legendX+LEGEND_X_SPACING, legendY+LEGEND_Y_SPACING,
00262                             legendX+LEGEND_X_SPACING+LEGEND_SIZE, legendY+LEGEND_Y_SPACING+LEGEND_SIZE,
00263                             series_color[i] );
00264         font_ptr->put( legendX+LEGEND_X_SPACING*2+LEGEND_SIZE, legendY+LEGEND_Y_SPACING, legend_array[i] );
00265     }
00266 }
00267 
00268 //------------ End of function PieChart::draw_legend ------------//
00269 
00270 //---------- Begin of function PieChart::draw_axis_label --------//
00272 void PieChart::draw_axis_label() {
00273     short textHeight = font_ptr->max_font_height;
00274 
00275     if (x_label) {
00276         font_ptr->center_put( series_x1, series_y2+COMMON_OFFSET*2+textHeight,
00277                               series_x2, piechart_y1+graph_height-COMMON_OFFSET, x_label );
00278     }
00279 
00280     if (y_label) {
00281         short textWidth = font_ptr->text_width(y_label) + 1;
00282 
00283         if (orientation_flag) {
00284             short *fontBuf = (short *) sys.common_data_buf;
00285             err_when(textWidth * textHeight * sizeof(short) > COMMON_DATA_BUF_SIZE);
00286 
00287             for (int i = 0; i < textWidth * textHeight; i++)
00288                 *fontBuf++ = transparent_code_w;
00289 
00290             font_ptr->put_to_bufferW(fontBuf = (short *) sys.common_data_buf, textWidth * sizeof(short), 0, 0, y_label);
00291 
00292             short xStart = piechart_x1 + 4 + COMMON_OFFSET * 2;
00293             short yStart = (series_y1 + series_y2 - textWidth) / 2;
00294 
00295             for (short x = 0; x < textHeight; x++) {
00296                 for (short y = textWidth - 1; y >= 0; y--, fontBuf++) {
00297                     if (*fontBuf != transparent_code_w)
00298                         *vga_back.buf_ptr(xStart+x, yStart+y) = *fontBuf;
00299                 }
00300             }
00301         }
00302         else {
00303             font_ptr->center_put( piechart_x1+4+COMMON_OFFSET*2, series_y1,
00304                                   piechart_x1+4+COMMON_OFFSET*2+textWidth, series_y2, y_label);
00305         }
00306     }
00307 }
00308 
00309 //------------ End of function PieChart::draw_axis_label --------//
00310 
00311 //---------- Begin of function PieChart::find_scale -------------//
00313 void PieChart::find_scale() {
00314     double data, maxVal = 0.0;
00315     x_axis_pos = 0;
00316 
00317     for (int i = 0; i < series_num * data_num; i++) {
00318         switch (data_type_flag) {
00319         case DATA_DOUBLE:
00320             data = ((double*)data_array)[i];
00321             break;
00322         case DATA_FLOAT:
00323             data = double(((float*)data_array)[i]);
00324             break;
00325         case DATA_INT:
00326             data = double(((int*)data_array)[i]);
00327             break;
00328         case DATA_LONG:
00329             data = double(((long*)data_array)[i]);
00330             break;
00331         }
00332         if (fabs(data) > maxVal)
00333             maxVal = fabs(data);
00334         if (!x_axis_pos && data < 0.0)
00335             x_axis_pos = 1;
00336     }
00337     if (maxVal>0)
00338         max_scale = pow(10,ceil(log10(maxVal)));
00339     else
00340         max_scale = 5;
00341 }
00342 
00343 //------------ End of function PieChart::find_scale -------------//
00344 
00345 //---------- Begin of function PieChart::draw_scale -------------//
00347 void PieChart::draw_scale() {
00348     find_scale();
00349 
00350     short xAxisPos;
00351 
00352     //------ Draw y-axis -------//
00353 
00354     if (x_axis_pos)
00355         vga_back.bar(series_x1, series_y1-COMMON_OFFSET*2, series_x1+1, series_y2+COMMON_OFFSET*2, axis_color);
00356     else
00357         vga_back.bar(series_x1, series_y1-COMMON_OFFSET*2, series_x1+1, series_y2, axis_color);
00358 
00359     short scaleNum = (series_y2-series_y1-font_ptr->max_font_height) / (font_ptr->max_font_height*3/2);
00360     if ( scaleNum > 0 )
00361         scaleNum = short(pow(2,floor(log10(double(scaleNum))/log10(2.0))));
00362     else
00363         scaleNum = 0;
00364     short scaleStep = (series_y2-series_y1) / scaleNum;
00365     double scaleValue;
00366     for (int i = 0; i <= scaleNum; i++) {
00367         if ( (x_axis_pos && i == scaleNum / 2) || !(x_axis_pos || i) )
00368             vga_back.bar(series_x1, xAxisPos=series_y2-i*scaleStep-1, series_x2+COMMON_OFFSET*8, series_y2-i*scaleStep, axis_color);
00369         else
00370             vga_back.bar(series_x1, series_y2-i*scaleStep, series_x1+COMMON_OFFSET*2, series_y2-i*scaleStep, axis_color);
00371 
00372         if (x_axis_pos)
00373             scaleValue = max_scale*2/scaleNum*i - max_scale;
00374         else
00375             scaleValue = max_scale/scaleNum*i;
00376 
00377         switch (data_type_flag) {
00378         case DATA_FLOAT:
00379         case DATA_DOUBLE:
00380             font_ptr->right_put(series_x1-COMMON_OFFSET, series_y2-i*scaleStep-font_ptr->max_font_height/2, m.format(scaleValue,num_format));
00381             break;
00382         case DATA_INT:
00383         case DATA_LONG:
00384             font_ptr->right_put(series_x1-COMMON_OFFSET, series_y2-i*scaleStep-font_ptr->max_font_height/2, m.format(long(scaleValue),num_format));
00385         }
00386     }
00387 
00388     //------ Draw x-axis -------//
00389 
00390     short maxLabelWidth = font_ptr->text_width(m.format(*x_end, 4))+COMMON_OFFSET*2;
00391     x_axis_step = (series_x2-series_x1) / (data_num-1);
00392     short displayInc = 1;
00393     while (displayInc * x_axis_step / maxLabelWidth < 1) displayInc++;
00394     int xAxisStep = (*x_end - *x_start) / (data_num - 1);
00395     for (i = 0; i < data_num-1; i += displayInc) {
00396         vga_back.bar(series_x2-i*x_axis_step, xAxisPos-COMMON_OFFSET*2, series_x2-i*x_axis_step, xAxisPos, axis_color);
00397         font_ptr->center_put((series_x2-i*x_axis_step)-maxLabelWidth/2-COMMON_OFFSET, xAxisPos+COMMON_OFFSET,
00398                              (series_x2-i*x_axis_step)+maxLabelWidth/2+COMMON_OFFSET, xAxisPos+COMMON_OFFSET+font_ptr->max_font_height, m.format(*x_end-xAxisStep*i, 4));
00399     }
00400 }
00401 
00402 //------------ End of function PieChart::draw_scale -------------//
00403 
00404 //---------- Begin of function PieChart::draw_series ------------//
00406 void PieChart::draw_series() {
00407     switch (data_type_flag) {
00408     case DATA_FLOAT: draw_series_float(); break;
00409     case DATA_DOUBLE: draw_series_double(); break;
00410     case DATA_INT: draw_series_int(); break;
00411     case DATA_LONG: draw_series_long(); break;
00412     }
00413 }
00414 
00415 //------------ End of function PieChart::draw_series ------------//
00416 
00417 //---------- Begin of function PieChart::draw_pie ------------//
00419 void PieChart::draw_pie(double theta1, double theta2, int piecolor) {
00420     //assume theta2 > theta 1
00421     double t1=theta1, t2=theta2;
00422     double sint3,cost3,t3,t4,t5,x,y;
00423     double skip=1.0;
00424 
00425     if(theta1==theta2)return;
00426 
00427     t3=0.5*(t1+t2);
00428     sint3=sin(t3);
00429     cost3=cos(t3);
00430     t4=2*(skip/(t2-t1));
00431     t5=skip/radius;
00432     x=centerx;
00433     y=centery;
00434     while(t1<=t2) {
00435         vga_back.thick_line(
00436             (int)x, (int)y, centerx+(int)(radius*cos(t1)), centery+(int)(radius*sin(t1)),
00437             vga_back.translate_color(series_color[piecolor]));
00438         vga_back.thick_line(
00439             (int)x, (int)y, centerx+(int)(radius*cos(t2)), centery+(int)(radius*sin(t2)),
00440             vga_back.translate_color(series_color[piecolor]));
00441 
00442         x+=t4*cost3;
00443         y+=t4*sint3;
00444         t1+=t5;
00445         t2-=t5;
00446     }
00447     t1=theta1;
00448     t2=theta2;
00449     while(t1<=t2) {
00450         vga_back.thick_line(
00451             centerx+(int)(radius*cos(t2)), centery+(int)(radius*sin(t2)),
00452             centerx+(int)(radius*cos(t2-=t5)), centery+(int)(radius*sin(t2)),
00453             vga_back.translate_color(V_GRAY-5));
00454         vga_back.thick_line(
00455             centerx+(int)(radius*cos(t1)), centery+(int)(radius*sin(t1)),
00456             centerx+(int)(radius*cos(t1+=t5)), centery+(int)(radius*sin(t1)),
00457             vga_back.translate_color(V_GRAY-5));
00458         x+=t4*cost3;
00459         y+=t4*sint3;
00460     }
00461 
00462 }
00463 
00464 //---------- End of function PieChart::draw_pie ------------//
00465 
00466 //---------- Begin of function PieChart::draw_series_int ------------//
00468 void PieChart::draw_series_int() {
00469     int *dataArray = (int *) data_array;
00470     long total=0;
00471     double theta1,theta2;
00472 
00473     for (int i = 0; i < data_num; i++)
00474         total+=(long)(dataArray[i]);
00475 
00476     if(total<1E-9)total=1;
00477     theta2=0.0;
00478     for (i = 0; i < data_num; i++) {
00479         theta1=theta2;
00480         theta2+=6.2832*(double)dataArray[i]/total;
00481         draw_pie(theta1,theta2,i);
00482 
00483         if((theta1!=theta2)
00484            &&(fabs(theta2-theta1-6.2832)>1e-9)) {
00485             vga_back.thick_line(
00486                 centerx,
00487                 centery,
00488                 centerx+(int)(radius*cos(theta1)),
00489                 centery+(int)(radius*sin(theta1)),
00490                 vga_back.translate_color(V_GRAY-5));
00491             vga_back.thick_line(
00492                 centerx,
00493                 centery,
00494                 centerx+(int)(radius*cos(theta2)),
00495                 centery+(int)(radius*sin(theta2)),
00496                 vga_back.translate_color(V_GRAY-5));
00497         }
00498     }
00499 
00500 }
00501 
00502 //------------ End of function PieChart::draw_series_long ------------//
00503 
00504 void PieChart::draw_series_long() {
00505     long *dataArray = (long *) data_array;
00506     long total=0;
00507     double theta1,theta2;
00508 
00509     for (int i = 0; i < data_num; i++)
00510         total+=(long)(dataArray[i]);
00511     if(total<1E-9)total=1;
00512 
00513     theta2=0.0;
00514     for (i = 0; i < data_num; i++) {
00515         theta1=theta2;
00516         theta2+=6.2832*(double)dataArray[i]/total;
00517         draw_pie(theta1,theta2,i);
00518     }
00519     theta1=0.0;
00520     for (i = 0; i <= data_num; i++) {
00521         vga_back.thick_line(
00522             centerx, centery,
00523             centerx+(int)(radius*cos(theta1)), centery+(int)(radius*sin(theta1)),
00524             vga_back.translate_color(V_GRAY-5));
00525         theta1+=6.2832*(double)dataArray[i]/total;
00526     }
00527 }
00528 
00529 //------------ End of function PieChart::draw_series_long ------------//
00530 
00531 //------------ End of function PieChart::draw_series_float ------------//
00532 
00533 void PieChart::draw_series_float() {
00534     float *dataArray = (float *) data_array;
00535     float total=0;
00536     double theta1,theta2;
00537 
00538     for (int i = 0; i < data_num; i++)
00539         total+=(float)(dataArray[i]);
00540 
00541     if(total<1E-9)total=1;
00542 
00543     theta2=0.0;
00544     for (i = 0; i < data_num; i++) {
00545         theta1=theta2;
00546         theta2+=6.2832*(double)dataArray[i]/total;
00547         draw_pie(theta1,theta2,i);
00548     }
00549     theta1=0.0;
00550     for (i = 0; i <= data_num; i++) {
00551         vga_back.thick_line(
00552             centerx, centery,
00553             centerx+(int)(radius*cos(theta1)), centery+(int)(radius*sin(theta1)),
00554             vga_back.translate_color(V_GRAY-5));
00555         theta1+=6.2832*(double)dataArray[i]/total;
00556     }
00557 
00558 }
00559 
00560 //------------ End of function PieChart::draw_series_float ------------//
00561 
00562 //------------ End of function PieChart::draw_series_long ------------//
00563 
00564 void PieChart::draw_series_double() {
00565     double *dataArray = (double *) data_array;
00566     double total=0;
00567     double theta1,theta2;
00568 
00569     for (int i = 0; i < data_num; i++)
00570         total+=(double)(dataArray[i]);
00571 
00572     if(total<1E-9)total=1;
00573 
00574     theta2=0.0;
00575     for (i = 0; i < data_num; i++) {
00576         theta1=theta2;
00577         theta2+=6.2832*(double)dataArray[i]/total;
00578         draw_pie(theta1,theta2,i);
00579     }
00580 
00581     theta1=0.0;
00582     for (i = 0; i <= data_num; i++) {
00583         vga_back.thick_line(
00584             centerx, centery,
00585             centerx+(int)(radius*cos(theta1)), centery+(int)(radius*sin(theta1)),
00586             vga_back.translate_color(V_GRAY-5));
00587         theta1+=6.2832*(double)dataArray[i]/total;
00588     }
00589 
00590 }
00591 
00592 //------------ End of function PieChart::draw_series_float ------------//
00593 
00594 //---------- Begin of function PieChart::draw_value -------------------//
00596 void PieChart::draw_value(void *value, int color, short x, short y, int dataType) {
00597     char *valueString;
00598     switch (data_type_flag) {
00599     case DATA_FLOAT:
00600         valueString = m.format(*((float *) value), num_format); break;
00601     case DATA_DOUBLE:
00602         valueString = m.format(*((double *) value), num_format); break;
00603     case DATA_INT:
00604         valueString = m.format(*((int *) value), num_format); break;
00605     case DATA_LONG:
00606         valueString = m.format(*((long *) value), num_format); break;
00607     }
00608 
00609     short textHeight = font_ptr->max_font_height;
00610     short textWidth = font_ptr->text_width(valueString) + 1;
00611     /*  
00612         short *bitmap = (short *) sys.common_data_buf;
00613         err_when( (2 + textWidth * textHeight) * sizeof(short) > COMMON_DATA_BUF_SIZE );
00614         *bitmap++ = textWidth;
00615         *bitmap++ = textHeight;
00616 
00617         short *shortPtr = bitmap;
00618         for (int i = 0; i < textWidth * textHeight; i++)
00619         *shortPtr++ = transparent_code_w;
00620 
00621         font_ptr->put_to_bufferW(bitmap, textWidth * sizeof(short), 0, 0, valueString);
00622 
00623         shortPtr = bitmap;
00624         for (i = 0; i < textWidth * textHeight; i++, shortPtr++)
00625         if (*shortPtr != transparent_code_w)
00626         *shortPtr = color;
00627 
00628         vga_back.put_bitmapW_trans(x, y, (short *) sys.common_data_buf);
00629     */
00630     font_chartsm.put(x+3,y,valueString);
00631 }
00632 
00633 //---------- Begin of function PieChart::draw_value -------------------//

Generated on Fri Aug 23 01:38:10 2002 for VirtualU by doxygen1.2.17