// Module PI : Peida Interactive PIAxes // Methodes de trace des axes // R. Ansari - 2002 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #include "sopnamsp.h" #include "machdefs.h" #include #include #include #include #include "piaxes.h" //++ // Class PIAxes // Lib PI // include piaxes.h // // Classe gestionnaire de tracé d'axes. A utiliser dans // un objet PIDrawer. //-- //++ // Links Voir // PIDrawer //-- //++ // Titre Constructeurs et méthodes //-- inline void dble_SWAP(double& a,double& b) {double tmp=a; a=b; b=tmp;} //++ // PIAxes() // Constructeur. //-- /* --Methode-- */ PIAxes::PIAxes() { ConfigureTicks(); ConfigureAutoFontSize(); ConfigureAxesCenter(); setupDone = false; } /* --Methode-- */ PIAxes::~PIAxes() { } //++ // void DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt, \ // unsigned int flags, bool afsz, double fszf) // Trace les axes en utilisant les limites de l'objet PIGraphicUC. // "flags" spécifie les attributs d'axes. Constantes prédéfinies: //| kCentAxes : Axes passant par le centre //| kBoxAxes : Axes entourant le tracé //| kIntTicks, kExtTicks //| kMajTicks, kMinTicks //| kLabelsH, kLabelsV, kLabels //| kAxesDflt = kStdAxes = //| kBoxAxes | kTicks | | kIntTicks | kLabels //| kGridOn, kAxesNone // Si "afsz == true", la taille de fonte est choisie automatiquement avec "fszf" // representant la taille de fonte en fraction de (ymax-ymin) // // void DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt, unsigned int flags=kAxesDflt) // Appel de DrawXYAxes avec les parametres "axesAFSz. fontSz" de l'objet. // // void DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt, \ // double xmin, double xmax, double ymin, double ymax, \ // unsigned int flags, bool afsz, double ) // Tracé d'axes avec spécification des limites d'axes. // // void DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt, \ // double xmin, double xmax, double ymin, double ymax, unsigned int flags=kAxesDflt) // Appel de DrawXYAxes avec les parametres "axesAFSz. fontSz" de l'objet. // // void DrawXCaption(PIGraphicUC* g, string const& xLabel, PIGraphicAtt const& att) // Tracé du label d'axe X. // void DrawYCaption(PIGraphicUC* g, string const& YLabel, PIGraphicAtt const& att) // Tracé du label d'axe Y. //-- /* --Methode-- */ void PIAxes::DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt, unsigned int flags, bool afsz, double fszf) { PIGrCoord xmin, xmax, ymin, ymax; g->GetGrSpace(xmin, xmax, ymin, ymax); DrawXYAxes(g, gratt, (double)xmin, (double)xmax, (double)ymin, (double)ymax, flags, afsz, fszf); } /* --Methode-- */ void PIAxes::DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt, double xmin, double xmax, double ymin, double ymax, unsigned int flags, bool afsz, double fszf) { if ((flags&kTicks)&&!(flags&kIntTicks)&&!(flags&kExtTicks)) flags |= kIntTicks; // Ticks internes par defaut if ((flags&kTicks)&&!(flags&kMajTicks)&&!(flags&kMinTicks)) flags |= kMajTicks; // Ticks majeures par defaut Setup(g, xmin, xmax, ymin, ymax); // g->NoClip(); if (gratt.GetLineAtt() == PI_NotDefLineAtt) g->SelLine(PI_ThinLine); else g->SelLine(gratt.GetLineAtt()); if (gratt.GetColor() == PI_NotDefColor) g->SelForeground(PI_Black); else g->SelForeground(gratt.GetColor()); if(afsz) { double fsz = (yMax-yMin)*fszf; g->SelFontSz(fsz); } if (flags & kCentAxes) { // Les axes double x0axes = (xMin+xMax)/2., y0axes = (yMin+yMax)/2.; if(axesCenter) {x0axes = axesCentX0; y0axes = axesCentY0;} if(x0axesxMax) x0axes = (xMin+xMax)/2.; if(y0axesyMax) y0axes = (yMin+yMax)/2.; g->DrawLine(xMin, y0axes, xMax, y0axes); g->DrawLine(x0axes, yMin, x0axes, yMax); // PIArrowMarker amk = g->GetArrowMarker(); // if (amk == PI_NotDefArrowMarker) PIArrowMarker amk = amk = PI_FTriangleArrowMarker; g->SelArrowMarkerSz(xMajTickLen*2., amk); // g->SelArrowMarker(5, g->GetArrowMarker()); double xm2 = g->DeltaUCX(xMax, yMajTickLen*2.); g->DrawArrowMarker(xMax, y0axes, xm2, y0axes, true); double ym2 = g->DeltaUCY(yMax, xMajTickLen*2.); g->DrawArrowMarker(x0axes, yMax, x0axes, ym2, true); // La grille en pointilles if (flags & kGridOn) DrawGrid(g); // Les ticks majeurs if ((flags & kTicks) && (flags & kMajTicks)) { DrawHTicks(g, y0axes, xMajTickLen, xMajTickLen, xMajTicks); DrawVTicks(g, x0axes, yMajTickLen, yMajTickLen, yMajTicks); } // Les ticks mineurs if ((flags & kTicks) && (flags & kMinTicks)) { DrawHTicks(g, y0axes, xMinTickLen, xMinTickLen, xMinTicks); DrawVTicks(g, x0axes, yMinTickLen, yMinTickLen, yMinTicks); } // Les labels if (flags & kLabelsH) { double declab = 2*xMajTickLen; if (!aYdir) DrawHLabels(g, y0axes-declab, xMajTicks, PI_VerticalTop); else DrawHLabels(g, y0axes+declab, xMajTicks, PI_VerticalTop); } if (flags & kLabelsV) { double declab = 2.*yMajTickLen; if (!aXdir) DrawVLabels(g, x0axes-declab, yMajTicks, PI_HorizontalRight); else DrawVLabels(g, x0axes+declab, yMajTicks, PI_HorizontalRight); } } if (flags & kBoxAxes) { // La boite g->DrawLine(xMin, yMin, xMax, yMin); g->DrawLine(xMax, yMin, xMax, yMax); g->DrawLine(xMax, yMax, xMin, yMax); g->DrawLine(xMin, yMax, xMin, yMin); // Longueur des ticks double extXMajTickLen = flags&kExtTicks ? xMajTickLen : 0; double intXMajTickLen = flags&kIntTicks ? xMajTickLen : 0; double extXMinTickLen = flags&kExtTicks ? xMinTickLen : 0; double intXMinTickLen = flags&kIntTicks ? xMinTickLen : 0; double extYMajTickLen = flags&kExtTicks ? yMajTickLen : 0; double intYMajTickLen = flags&kIntTicks ? yMajTickLen : 0; double extYMinTickLen = flags&kExtTicks ? yMinTickLen : 0; double intYMinTickLen = flags&kIntTicks ? yMinTickLen : 0; // La grille en pointilles if (flags & kGridOn) DrawGrid(g); // Les ticks majeurs if ((flags & kTicks) && (flags & kMajTicks)) { DrawHTicks(g, yMin, intXMajTickLen, extXMajTickLen, xMajTicks); DrawHTicks(g, yMax, extXMajTickLen, intXMajTickLen, xMajTicks); DrawVTicks(g, xMin, extYMajTickLen, intYMajTickLen, yMajTicks); DrawVTicks(g, xMax, intYMajTickLen, extYMajTickLen, yMajTicks); } // Les ticks mineurs if ((flags & kTicks) && (flags & kMinTicks)) { DrawHTicks(g, yMin, intXMinTickLen, extXMinTickLen, xMinTicks); DrawHTicks(g, yMax, extXMinTickLen, intXMinTickLen, xMinTicks); DrawVTicks(g, xMin, extYMinTickLen, intYMinTickLen, yMinTicks); DrawVTicks(g, xMax, intYMinTickLen, extYMinTickLen, yMinTicks); } // Les labels if (flags & kLabelsH) { double declab = xMajTickLen; if (flags & kExtTicks) declab *= 2.; if (!aYdir) { DrawHLabels(g, g->DeltaUCY(yMin, -declab), xMajTicks, PI_VerticalTop); } else { DrawHLabels(g, g->DeltaUCY(yMax, declab), xMajTicks, PI_VerticalTop); } } if (flags & kLabelsV) { double declab = yMajTickLen; if (flags & kExtTicks) declab *= 2.; if (!aXdir) { DrawVLabels(g, g->DeltaUCX(xMin, -declab), yMajTicks, PI_HorizontalRight); } else { DrawVLabels(g, g->DeltaUCX(xMax, declab), yMajTicks, PI_HorizontalRight); } } } g->Clip(); } /* --Methode-- */ void PIAxes::DrawXCaption(PIGraphicUC* g, PIGraphicAtt& att, unsigned int flags, string const& xLabel) { if (xLabel.length() < 1) return; if (!setupDone) { PIGrCoord xmin, xmax, ymin, ymax; g->GetGrSpace(xmin, xmax, ymin, ymax); Setup(g, xmin, xmax, ymin, ymax); } if ( (att.GetFontName() != PI_DefaultFont) || (att.GetFontAtt() != PI_NotDefFontAtt) ) g->SelFont(att.GetFont()); PIColors fcol = att.GetFgColor(); if (fcol != PI_NotDefColor) g->SelForeground(fcol); double fx,fy,fh; if (flags&kBoxAxes) { fh = -0.090*(yMax-yMin); if (g->isAxeYDirUpDown()) fy = yMax; else fy = yMin; } else { fh = 0.04*(yMax-yMin); if(axesCenter) fy = axesCentY0; else fy = 0.5*(yMin+yMax); if(fyyMax) fy = (yMin+yMax)/2.; } if (g->isAxeYDirUpDown()) fh = -fh; fy = g->DeltaUCY(fy, fh); fx = g->DeltaUCX(xMax, -(xMax-xMin)*0.25); g->DrawString(fx, fy, xLabel.c_str(), PI_HorizontalCenter | PI_VerticalCenter); } /* --Methode-- */ void PIAxes::DrawYCaption(PIGraphicUC* g, PIGraphicAtt& att, unsigned int flags, string const& yLabel) { if (yLabel.length() < 1) return; if (!setupDone) { PIGrCoord xmin, xmax, ymin, ymax; g->GetGrSpace(xmin, xmax, ymin, ymax); Setup(g, xmin, xmax, ymin, ymax); } if ( (att.GetFontName() != PI_DefaultFont) || (att.GetFontAtt() != PI_NotDefFontAtt) ) g->SelFont(att.GetFont()); PIColors fcol = att.GetFgColor(); if (fcol != PI_NotDefColor) g->SelForeground(fcol); double fx,fy,fh; if (flags&kBoxAxes) { fh = -0.125*(xMax-xMin); if (g->isAxeXDirRtoL()) fx = xMax; else fx = xMin; } else { fh = 0.04*(xMax-xMin); if(axesCenter) fx = axesCentX0; else fx = 0.5*(xMin+xMax); if(fxxMax) fx = (xMin+xMax)/2.; } if (g->isAxeXDirRtoL()) fh = -fh; fx = g->DeltaUCX(fx, fh); fy = g->DeltaUCY(yMax,-(yMax-yMin)*0.25); unsigned long txtflg = PI_HorizontalCenter | PI_VerticalCenter | PI_TextDirectionVerticalUp; if (g->isAxeYDirUpDown()) txtflg = PI_HorizontalCenter | PI_VerticalCenter | PI_TextDirectionVerticalDown; g->DrawString(fx, fy, yLabel.c_str(), txtflg); } //++ // void ConfigureTicks(int ntickx=10, int nticky=12, \ // double majtl=0.0125, double mintl=0.07) // Configuration du nombre de ticks et taille des ticks. // La taille des ticks est exprimée en fraction de la taille totale // (X/Y max-min). Les paramètres ne sont pas changés si des valeurs // négatives ou nulles sont spécifiées. // void ConfigureAutoFontSize(double fszf=0.0125) // Configuration de la taille de fonte, en mode AutoFontSize. // La taille est exprimée en fraction de la taille totale YMax-Min // void ConfigureAxesCenter(bool fset,double x0,double y0) // Force axe center to be at (x0,y0) or let it be in the middle //-- /* --Methode-- */ void PIAxes::ConfigureTicks(int ntickx, int nticky, double majtl, double mintl) { if (ntickx > 0) xNTicks = ntickx; if (nticky > 0) yNTicks = nticky; if (majtl > 1.e-19) fMajTickLen = majtl; if (mintl > 1.e-19) fMinTickLen = mintl; } /* --Methode-- */ void PIAxes::ConfigureAutoFontSize(bool afsz, double fszf) { axesAFSz = afsz; if (fszf > 1.e-19) fontSz = fszf; } /* --Methode-- */ void PIAxes::ConfigureAxesCenter(bool fset,double x0,double y0) { axesCenter = fset; if(!axesCenter) return; axesCentX0 = x0; axesCentY0 = y0; } /* --Methode-- */ void PIAxes::Setup(PIGraphicUC* g, double xmin, double xmax, double ymin, double ymax) { xMin = xmin; xMax = xmax; yMin = ymin; yMax = ymax; aXdir = g->isAxeXDirRtoL(); aYdir = g->isAxeYDirUpDown(); aXlog = g->isLogScaleX(); aYlog = g->isLogScaleY(); // Reza - Mars 03 - Nb de ticks en parametres int ntick_x = (aXlog) ? xNTicks : xNTicks; if(aXlog) BestTicksLog(xMin,xMax,ntick_x,xMajTicks,xMinTicks); else BestTicks(xMin,xMax,ntick_x,xMajTicks,xMinTicks); int ntick_y = (aYlog) ? yNTicks : yNTicks; if(aYlog) BestTicksLog(yMin,yMax,ntick_y,yMajTicks,yMinTicks); else BestTicks(yMin,yMax,ntick_y,yMajTicks,yMinTicks); // Reza - Mars 03 - Taille des ticks en parametres yMajTickLen = (xMax-xMin)*fMajTickLen; // Au lieu de / 100 yMinTickLen = (xMax-xMin)*fMinTickLen; // Au lieu de / 200 ou 250 xMajTickLen = (yMax-yMin)*fMajTickLen; // Au lieu de / 100 xMinTickLen = (yMax-yMin)*fMinTickLen; // Au lieu de / 200 ou 250 setupDone = true; } /* --Methode-- */ void PIAxes::DrawHTicks(PIGraphicUC* g, double y, double tickUp, double tickDown, vector& xticks) { if(xticks.size()==0) return; for(unsigned int i=0;ixMax) break; g->DrawLine(xticks[i],g->DeltaUCY(y,-tickDown),xticks[i],g->DeltaUCY(y,tickUp)); } } /* --Methode-- */ void PIAxes::DrawVTicks(PIGraphicUC* g, double x, double tickLeft, double tickRight, vector& yticks) { if(yticks.size()==0) return; for(unsigned int i=0;iyMax) break; g->DrawLine(g->DeltaUCX(x,-tickLeft),yticks[i],g->DeltaUCX(x,tickRight),yticks[i]); } } /* --Methode-- */ void PIAxes::DrawHLabels(PIGraphicUC* g, double y, vector& xticks, unsigned long just) { if(xticks.size()==0) return; // Choix du bon format pour les labels des axes string format; double xstep; int npuiss = Le_Bon_Format(xticks,format,xstep); double fac=(npuiss!=0)? fac=pow(10.,(double)npuiss): 1.; char label[64]; double dum,xpixdeb,xpixfin,largpix; g->UC2GrC(xMin-2.*(xMax-xMin),y,xpixfin,dum); for(unsigned int i=0;ixMax) break; //Attention erreur d'arrondi x->0 (on code 5.1698e-26 au lieu de 0) double xx = (fabs(xticks[i]/xstep)<1.e-5) ? 0.: xticks[i]; double dog = fabs(xx/fac); if ((dog<=1.e-5)||(dog>=1.e5)) sprintf(label,"%le",xx/fac); else sprintf(label,format.c_str(),xx/fac); Arrange_Label(label); double largeur = g->CalcStringWidth(label); g->DUC2GrC(largeur,0.,largpix,dum); g->UC2GrC(xticks[i],y,xpixdeb,dum); xpixdeb -= largpix/2.; //cout<<"xticks="<DrawCompString(xm,ym,"x 10",label,NULL,PI_HorizontalCenter|just); } } /* --Methode-- */ void PIAxes::DrawVLabels(PIGraphicUC* g, double x, vector& yticks, unsigned long just) { if(yticks.size()==0) return; // Choix du bon format pour les labels des axes; string format; double ystep; int npuiss = Le_Bon_Format(yticks,format,ystep); double fac=(npuiss!=0)? fac=pow(10.,(double)npuiss): 1.; char label[64]; PIGrCoord asc,desc; double dum,ypixdeb,ypixfin,hautpix,hauteur=g->GetFontHeight(asc,desc); g->DUC2GrC(0.,hauteur,dum,hautpix); g->UC2GrC(x,yMin-2.*(yMax-yMin),dum,ypixfin); for(unsigned int i=0;iyMax) break; double yy = (fabs(yticks[i]/ystep)<1.e-5) ? 0.: yticks[i]; double dog = fabs(yy/fac); if ((dog<=1.e-5)||(dog>=1.e5)) sprintf(label,"%le",yy/fac); else sprintf(label,format.c_str(),yy/fac); Arrange_Label(label); g->UC2GrC(x,yticks[i],dum,ypixdeb); ypixdeb -= hautpix/2.; // -- Attention: ypix=0 est en haut de l'ecran // (ypix croissants vers le bas de l'ecran) // donc bien que yMinyMaxPix //cout<<"yticks="<DrawCompString(x,ym,"x 10",label,NULL,PI_VerticalBottom|just); } } /* --Methode-- */ void PIAxes::DrawGrid(PIGraphicUC* g) { PILineAtt savlineatt = g->GetLineAtt(); g->SelLine(PI_ThinDottedLine); if(xMajTicks.size()>0) for(unsigned int i=0;ixMax) break; g->DrawLine(xMajTicks[i], yMin, xMajTicks[i], yMax); } if(yMajTicks.size()>0) for(unsigned int i=0;iyMax) break; g->DrawLine(xMin, yMajTicks[i], xMax, yMajTicks[i]); } g->SelLine(savlineatt); } //////////////////////////////////////////////////////////////////////// //////////////////// METHODES STATIQUES //////////////////////////////// //////////////////////////////////////////////////////////////////////// /* --Methode-Static-- */ void PIAxes::ReSizeMinMax(bool axelog,double& vmin,double& vmax,double garde) // Calcul du min et du max du display a partir des valeurs min et max a plotter { if(garde<0. || garde>=1.) garde = 0.025; // cout<<"ReSizeMinMax[log="<=xmax-xmin" double fac[9] = {2.,5.,10.,20.,50.,100.,200.,500.,1000.}; for(int k=0;k<9;k++) { //cout<<"BestTicks: "<1) { double steptickmin = steptick/5.; double xfirsttickmin = majticks[0]; while(xfirsttickmin<=xmax+steptickmin/10.) {minticks.push_back(xfirsttickmin); xfirsttickmin+= steptickmin;} } } /* --Methode-Static-- */ void PIAxes::BestTicksLog(double xmin,double xmax,int nticks ,vector& majticks,vector& minticks) // *** Calcul des ticks pour un axe logarithmique { if(nticks<=0) nticks = 1; //cout<<"BestTicksLog: xmin="<3) dmin = dmax/3; else dmin = dmax-1; } if(dmax==dmin) dmax++; else if(dmax=xmax) {if(typf==2) return 0; else return -1;} if(xstep<=0. || xstep>xmax-xmin) xstep = xmax-xmin; double axmin=fabs(xmin), axmax=fabs(xmax); if(axmin>axmax) dble_SWAP(axmin,axmax); double l10amax = log10(axmax), l10xstep = log10(xstep); int il10amax = int(floor(l10amax)); // choix du type de format char ftype = 'e'; int npuiss = 0; if(typf==2) { npuiss = il10amax-1; // nombre entre [0,10] //npuiss = il10amax; // nombre entre [0,1] if(npuiss<-300 || npuiss>300) { ftype='e'; npuiss=0; } else { // On recalcule les valeurs de decision pour axmax/10^npuiss, xstep/10^npuiss l10amax -= (double)npuiss; l10xstep -= (double)npuiss; il10amax = int(floor(l10amax)); ftype = 'f'; } } else if(typf==1) { ftype='e'; } else if(typf==3) { ftype='f'; } else { ftype='e'; // On evite d'ecrire +a.bbbe+ccc -> format %f // Ex: 1.2345e+2 -> 123.45 / -1.2345e+2 -> -123.45 // 1.2345e-1 -> 0.12345 / -1.2345e-1 -> -0.12345 if((axmin>=1e-4 || axmin==0.) && axmax<1e4) ftype='f'; } //printf("BonFormatAxes[npuiss=%d]: xmin=%-21.14e xmax=%-21.14e\n",npuiss,xmin,xmax); //printf(" xstep=%-21.14e log10(xstep/10^%d)=%g\n",xstep,npuiss,l10xstep); //printf(" axmax=%-21.14e log10(axmax/10^%d)=%g diff=%g\n" // ,axmax,npuiss,l10amax,l10amax-l10xstep); // Nombre de digits necessaires pour ecrire axmax et xstep int ndig = il10amax - int(floor(l10xstep)); if(ndig<0) ndig *= -1; ndig += 1; //printf("ndig=%d",ndig); // Add more digits (or suppress digits) ndig += add_digit; if(ndig<0) ndig=0; //printf(" + %d ==> ndig=%d\n",add_digit,ndig); // Calcul du bon format char str[16]; if(ftype=='f') { // Calcul du format %-nn.mmf int mm=-1, nn; if(il10amax<0) { // +0.12345 +0.0012345 +0.0012345 ... mm = ndig - il10amax - 1; nn = mm+3; } else { // +1.2345 +12.345 +123.45 ... mm = ndig - il10amax - 1; nn = ndig+2; } //printf("format %%f : mm=%d nn=%d\n",mm,nn); if(mm<0.) mm=0; if(nne+123 // 1 2 34567 ==> nn=ndig+7 mm=ndig-1 sprintf(str,"%%-%d.%de",ndig+7,ndig-1); } format = str; //printf("format=[%s]\n",format.c_str()); if(typf==2) return npuiss; return ndig; } /* --Methode-- */ int PIAxes::Le_Bon_Format(vector& xticks,string& format,double& xstep) // Methode static de decision du bon format // Decide quel format est le mieux adapte pour ecrire les labels des axes // Decide si une puissance de 10 doit etre deportee en bout d'axe // - Input: // xticks : vecteur des ticks a ecrire (calcule par BestTicks) // - Output: // format : format a utiliser // xstep : step entre 2 graduations // - Return: // npuiss : si format choisit avec ecriture // avec label des puissances de 10 deporte // 0 : sinon { format="%g"; xstep=1.; if(xticks.size()<=1) return 0; // On decide du format xstep=xticks[1]-xticks[0]; int npuiss = BonFormatAxes(xticks[0],xticks[xticks.size()-1],xstep,format,2,1); if(npuiss>=-2 && npuiss<=2) { npuiss = 0; BonFormatAxes(xticks[0],xticks[xticks.size()-1],xstep,format,3,1); } return npuiss; } void PIAxes::Arrange_Label(char *label) // --- Mise en forme optimale du label numerique // Enleve les blancs, les zeros, le point et les e00 // inutiles a la fin d'un label { size_t lenl=strlen(label); if(lenl==0) return; // --- On enleve les blancs et plus au debut du label if(label[0]==' ' || label[0]=='+') { char *str=new char[lenl+2]; strcpy(str,label); unsigned i=0; for(i=0;i=0;i--) { if(label[i]!=' ') break; label[i]='\0'; } lenl=strlen(label); } // --- On enleve les e... E... non-significatifs // ex: a.be-zzz a.be+zzz a.bezzz avec zzz=0,00,000,... // Attention on n'enleve pas si: a.be+10 // Attention on ne fait rien si: e+10 char* e=index(label,'e'); if(e==NULL) e=index(label,'E'); if(e) { for(int i=lenl-1;i>=0;i--) { if(isdigit(label[i]) && label[i]!='0') break; if(label[i]=='e' || label[i]=='E') {label[i]='\0'; lenl=strlen(label); break;} } } // --- On enleve les zeros non-significatifs a la fin du label // On enleve des zeros ou le point si: ab. ab.czzz avec zzz=0,00,000,... // Attention on n'enleve pas de zeros si: abzzz // Attention a ne pas enlever des zeros si on a ab.ccce+a0 // Attention on traite 0eaaa -> 0 if(index(label,'.')==NULL) return; // Recherche d'un point string stre; if(e) {if(e==label) return; stre=e; *e='\0'; lenl=strlen(label);} {for(int i=lenl-1;i>=0;i--) { if(label[i]=='0') label[i]='\0'; else if(label[i]=='.') { if(i>0) label[i]='\0'; else { // Attention: ".e+10" -> "1e+10" MAIS "." -> "0" if(e) strcpy(label,"1"); else strcpy(label,"0"); } break; } else break; // Ni un point ni un zero }} if(e) { if(strlen(label)==1) if(label[0]=='0') return; strcat(label,stre.c_str()); } }