Remove graphics.h file.
[scilab.git] / scilab / modules / graphics / src / c / DrawObjects.c
1 /*------------------------------------------------------------------------
2  *    Graphic library 
3  *    Copyright INRIA
4  *    newGraph Library header
5  *    Matthieu PHILIPPE,   INRIA 2001-2002
6  *    Djalel ABDEMOUCHE,   INRIA 2002-2004
7  *    Fabrice Leray,       INRIA 2004-2006
8  *    Jean-Baptiste Silvy, INRIA 2006-xxxxdrawmerge
9  *    Comment:
10  *    This file contains all functions used to Draw the content of a window.
11  *    The main functions is sciDrawObj that draws the objects recursively.
12  ------------------------------------------------------------------------/-*/
13 #include <math.h>
14
15 #include <stdio.h> 
16 #include <string.h>
17 #include <stdlib.h>
18 #include <stdarg.h>
19 #include <time.h>
20
21 #include "DrawObjects.h"
22 #include "GetProperty.h"
23 #include "bcg.h"
24 #include "SetProperty.h"
25 #include "BuildObjects.h"
26 #include "DestroyObjects.h"
27 #include "ObjectStructure.h"
28 #include "Axes.h"
29 #include "Xcall1.h"
30 #include "Champ.h"
31 #include "StringBox.h"
32 #include "handleDrawing/drawTextEntity.h"
33 #include "handleDrawing/drawFigureEntity.h"
34 #include "handleDrawing/drawSubWinEntity.h"
35 #include "handleDrawing/drawCompoundEntity.h"
36 #include "handleDrawing/drawLegendEntity.h"
37 #include "handleDrawing/drawFecEntity.h"
38 #include "handleDrawing/drawSegsEntity.h"
39 #include "handleDrawing/drawGrayplotEntity.h"
40 #include "handleDrawing/drawPolylineEntity.h"
41 #include "handleDrawing/drawArcEntity.h"
42 #include "handleDrawing/drawRectangleEntity.h"
43 #include "handleDrawing/drawAxesEntity.h"
44 #include "handleDrawing/drawMergeEntity.h"
45 #include "handleDrawing/drawSurfaceEntity.h"
46 #include "periScreen.h" /* to be removed */
47 #include "PloEch.h"
48 #include "axesScale.h"
49 #include "sciprint.h"
50
51 #include "math_graphics.h"
52 #include "graphicSession.h"
53 #include "Format.h"
54 #include "axesScale.h"
55 #include "drawMarks.h"
56 #include "BasicAlgos.h"
57
58 #include "MALLOC.h" /* MALLOC */
59
60 #ifdef WITH_TK
61 #include "../../../tclsci/includes/GedManagement.h"
62 #endif
63
64 #if _MSC_VER
65 extern HDC TryToGetDC(HWND hWnd);
66 #endif
67
68 #define         round(a)        (int)(((a)<0.0)?(a)-.5:(a)+.5)
69
70 extern double C2F(dsort)();/*DJ.A merge*/ 
71 extern int scilab_shade(integer *polyx, integer *polyy, integer *fill, integer polysize, integer flag);
72 #ifdef _MSC_VER
73 extern void Scistring (char *str);
74 #endif
75
76 void GradFixedlog( double minVal, double maxVal, double * ticks, int nbGrads );
77 int sciGetLogExponent( double minBound, double maxBound, double * expMin, double * expMax );
78
79 unsigned short defcolors[] = {
80   0,   0,   0, /* Black: DEFAULTBLACK */
81   0,   0, 255, /* Blue */
82   0, 255,   0, /* Green */
83   0, 255, 255, /* Cyan */
84   255,   0,   0, /* Red */
85   255,   0, 255, /* Magenta */
86   255,   255,   0, /* Yellow */
87   255, 255, 255, /* White: DEFAULTWHITE */
88   0,   0, 144, /* Blue4 */
89   0,   0, 176, /* Blue3 */
90   0,   0, 208, /* Blue2 */
91   135, 206, 255, /* LtBlue */
92   0, 144,   0, /* Green4 */
93   0, 176,   0, /* Green3 */
94   0, 208,   0, /* Green2 */
95   0, 144, 144, /* Cyan4 */
96   0, 176, 176, /* Cyan3 */
97   0, 208, 208, /* Cyan2 */
98   144,   0,   0, /* Red4 */
99   176,   0,   0, /* Red3 */
100   208,   0,   0, /* Red2 */
101   144,   0, 144, /* Magenta4 */
102   176,   0, 176, /* Magenta3 */
103   208,   0, 208, /* Magenta2 */
104   128,  48,   0, /* Brown4 */
105   160,  64,   0, /* Brown3 */
106   192,  96,   0, /* Brown2 */
107   255, 128, 128, /* Pink4 */
108   255, 160, 160, /* Pink3 */
109   255, 192, 192, /* Pink2 */
110   255, 224, 224, /* Pink */
111   255, 215,   0  /* Gold */
112 };
113
114 int cf_type = 1 ;
115
116 int get_cf_type(void)
117 {
118         return cf_type;
119 }
120
121 void set_cf_type(int val)
122 {
123         cf_type=val;
124 }
125
126
127
128 /**sciGetDC
129  * Returns the HDC of the figure window (not the parent)
130  */
131 #ifdef _MSC_VER
132 HDC        /* BCG Type priWin !! decommente par SS ???? */ 
133 sciGetDC (sciPointObj * pobj)
134 {
135   switch (sciGetEntityType (pobj))
136     {
137     case SCI_FIGURE:
138     case SCI_SUBWIN:
139       return (HDC)TryToGetDC (sciGetScilabXgc (pobj)->CWindow);
140       break;
141     default:
142       return sciGetDC (sciGetParent (pobj));
143       break;
144     }
145   return (HDC ) NULL;        /* Type HDC ! "periWin-bgc"*/
146 }
147 #endif
148
149
150 void sciRedrawFigure()
151 {
152   sciSetReplay (TRUE);
153   sciDrawObj (sciGetCurrentFigure ());
154   sciSetReplay (FALSE);
155    
156 }
157
158 void sciRedrawF(value)
159      int *value;   
160
161   sciPointObj *figure; 
162   integer cur,na,verb=0;
163   figure= (sciPointObj *) sciIsExistingFigure(value); 
164   /* F.Leray 13.04.04 : Test if returned sciPointObj* is NULL (means Figure has been destroyed) */
165
166   if(figure == (sciPointObj *)  NULL)
167     {
168       /* Do nothing */
169     }
170   else
171     {
172       C2F (dr) ("xget", "window",&verb,&cur,&na,PI0,PI0,PI0,PD0,PD0,PD0,PD0,4L,6L);
173       C2F (dr) ("xset", "window",value,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,4L,6L);
174       /* sciSetCurrentObj(figure); */ /*F.Leray 25.03.04*/
175       sciSetReplay (TRUE);
176       sciDrawObj (figure);
177       sciSetReplay (FALSE);
178       C2F (dr) ("xset", "window",&cur,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,4L,6L);
179     }
180 }
181
182 void sciXbasc()
183 {  
184   static sciPointObj *mafigure;
185   static sciPointObj *masousfen;  
186  
187   mafigure= (sciPointObj *) sciGetCurrentFigure(); 
188   DestroyAllGraphicsSons((sciPointObj *)mafigure);
189   
190    
191   if ((masousfen = ConstructSubWin (mafigure, 'o')) != NULL){
192     sciSetCurrentObj(masousfen);
193     sciSetOriginalSubWin (mafigure, masousfen);}
194   sciDrawObj(sciGetCurrentFigure ());      
195 }       
196
197 /* Completely destroy the handle hierearchy */
198 /* when switching from new to old figure_style */
199 /* see intgset.c */
200 void sciXClearFigure()
201 {  
202   static sciPointObj *mafigure;
203   struct BCG * XGC = (struct BCG*) NULL;
204   int v = 1, verb = 0;
205   double dv = 0.;
206
207   mafigure= (sciPointObj *) sciGetCurrentFigure(); 
208
209
210 #ifdef WITH_TK
211             /* close ged to prevent errors when using it */
212             sciDestroyGed( sciGetNum( mafigure ) ) ;
213 #endif
214
215   DestroyAllGraphicsSons((sciPointObj *)mafigure);
216   DestroyFigure (mafigure); 
217   C2F(dr)("xget","gc",&verb,&v,&v,&v,&v,&v,(double *)&XGC,&dv,&dv,&dv,5L,10L);
218   XGC->mafigure = (sciPointObj *) NULL;
219 }       
220
221 void sciXclear()
222 {
223   static sciPointObj *masousfen, *tmpsousfen;
224   sciSons *psonstmp; 
225      
226   tmpsousfen= (sciPointObj *) sciGetSelectedSubWin (sciGetCurrentFigure());
227   psonstmp = sciGetSons (sciGetCurrentFigure());
228   
229   while (psonstmp != (sciSons *) NULL)  
230     {  
231       if(sciGetEntityType (psonstmp->pointobj) == SCI_SUBWIN)
232         {
233           masousfen= (sciPointObj *)psonstmp->pointobj;
234           sciSetSelectedSubWin (masousfen);
235           sciSetdrawmode (FALSE); 
236         }
237       psonstmp = psonstmp->pnext;
238     }
239   sciSetSelectedSubWin (tmpsousfen);
240   sciDrawObj(sciGetCurrentFigure ());      
241 }
242
243 void sciXdraw()
244 {
245   static sciPointObj *masousfen, *tmpsousfen;
246   sciSons *psonstmp; 
247    
248   tmpsousfen= (sciPointObj *) sciGetSelectedSubWin (sciGetCurrentFigure ());
249   psonstmp = sciGetSons (sciGetCurrentFigure ());
250   
251   
252   while (psonstmp != (sciSons *) NULL)  
253     {  
254       if(sciGetEntityType (psonstmp->pointobj) == SCI_SUBWIN)
255         {
256           masousfen= (sciPointObj *)psonstmp->pointobj;
257           sciSetSelectedSubWin (masousfen);
258           sciSetdrawmode (TRUE); 
259         }
260       psonstmp = psonstmp->pnext;
261     }
262   sciSetSelectedSubWin (tmpsousfen); 
263   sciDrawObj(sciGetCurrentFigure ());
264            
265 }
266
267
268 /* update the scale and retrieve the bounding box of the axis */
269 void updateScale3d( sciPointObj * pobj    ,
270                     double        dbox[6] ,
271                     double        xbox[8] ,
272                     double        ybox[8] ,
273                     double        zbox[8]  )
274 {
275   int    flag     ;
276   int    i        ;
277   double xmmin    ;
278   double xmmax    ;
279   double ymmin    ;
280   double ymmax    ;
281   double wmax     ;
282   double hmax     ;
283   integer aaint[] = {2,10,2,10} ;
284   sciSubWindow * ppsubwin =  pSUBWIN_FEATURE (pobj);
285
286   sci_update_frame_bounds_3d( pobj ) ;
287        
288   dbox[0] =  ppsubwin->FRect[0] ; /*xmin*/
289   dbox[1] =  ppsubwin->FRect[2] ; /*xmax*/
290   dbox[2] =  ppsubwin->FRect[1] ; /*ymin*/
291   dbox[3] =  ppsubwin->FRect[3] ; /*ymax*/
292   dbox[4] =  ppsubwin->FRect[4] ; /*zmin*/
293   dbox[5] =  ppsubwin->FRect[5] ; /*zmax*/
294
295   if( ppsubwin->cube_scaling )
296   {
297     dbox[0] =  0.; 
298     dbox[1] =  1.;
299     dbox[2] =  0.;
300     dbox[3] =  1.;
301     dbox[4] =  0.;
302     dbox[5] =  1.;
303   }
304
305
306   /** changement de coordonnees 3d */
307   flag = ( ppsubwin->axes.flag[1] + 1 ) / 2 ; /* F.Leray Adding HERE 19.04.04 */
308
309   Cscale.alpha = ppsubwin->alpha ;
310   Cscale.theta = ppsubwin->theta ;
311       
312   /* update Cscale.m from the new viewing angles */
313   sciUpdateScaleAngles( ppsubwin->theta, ppsubwin->alpha ) ;
314       
315   for ( i = 0 ; i < 6 ; i++ ) 
316   { 
317     if ( flag == 0 )
318     { 
319       dbox[i] = Cscale.bbox1[i];
320     }
321     else
322     { 
323       Cscale.bbox1[i] = dbox[i];
324     }
325   }
326
327   /* get the vertices of the axes box */
328   sciGetAxisBox( dbox, xbox, ybox, zbox ) ;
329       
330   /** Calcul des echelles en fonction de la taille du dessin **/
331   if ( flag == 1 || flag == 3 ) /* ALL the expanded cases : flag[1] = 1 or 2 or 5 or 6 */
332   {
333     xmmin =  Mini(xbox,8L) ;
334     xmmax =  Maxi(xbox,8L) ; /* search for x Min/Max on all the edges (there are 8 edges that compose the box) F.Leray 13.10.04 */
335     ymmax = -Mini(ybox,8L) ; /* same thing on ybox vector ( 1) why - (minus) ? see 2) )*/
336     ymmin = -Maxi(ybox,8L);
337   }
338   
339   if ( flag == 2 || flag == 3 ) /* ALL the isometric cases : flag[1] = 3 or 4 or 5 or 6 */
340   {
341     int verbose = 0 ;
342     int narg        ;
343     int wdim[2]     ;
344     double FRect[4] ;
345     double WRect[4] ;
346     double ARect[4] ;
347     char   logf_[2]  ;
348     /* get current window size */
349     C2F(dr)("xget","wdim",&verbose,wdim,&narg, PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
350     getscale2d(WRect,FRect,logf_,ARect);
351     wmax=linint((double)wdim[0] * WRect[2]);
352     hmax=linint((double)wdim[1] * WRect[3]); 
353   }
354   
355   if ( flag == 2 ) /* the "NON expanded isometric" cases : flag[1] = 3 or 4 */
356   {
357     double R  ;
358     double xo ;
359     double yo ;
360     double zo ;
361     double dx ;
362     double dy ;
363     double dz ;
364     
365     /* radius and center of the sphere circumscribing the box */
366     dx = dbox[1] - dbox[0] ;
367     dy = dbox[3] - dbox[2] ;
368     dz = dbox[5] - dbox[4] ;
369     
370     R  = sqrt( dx*dx + dy*dy + dz*dz)/2;
371     xo = ( xbox[0] + xbox[6] ) / 2.0 ;
372     yo = ( ybox[0] + ybox[6] ) / 2.0 ;
373     zo = ( zbox[0] + zbox[6] ) / 2.0 ;
374     
375     xmmin=   xo - R ;
376     xmmax=   xo + R ;
377     ymmax=  -yo + R ;
378     ymmin=  -yo - R ;
379   }
380
381   if (flag==2 || flag==3)
382   {
383     double hx ;
384     double hy  ;
385     hx=xmmax-xmmin;
386     hy=ymmax-ymmin;
387     if ( hx/(double)wmax  < hy/(double)hmax ) 
388     {
389       double hx1 ;
390       hx1   = wmax * hy / hmax ;
391       xmmin = xmmin - ( hx1 - hx ) / 2.0 ;
392       xmmax = xmmax + ( hx1 - hx ) / 2.0 ;
393     }
394     else 
395     {
396       double hy1 ;
397       hy1 = hmax * hx / wmax ;
398       ymmin = ymmin - ( hy1 - hy ) / 2.0 ;
399       ymmax = ymmax + ( hy1 - hy ) / 2.0 ;
400     }
401   }
402
403   if (flag != 0 ) /* != using current 3D scale */
404   {
405     double FRect[4] ;
406     /* FRect = [Xmin,Ymin,Xmax,Ymax] */
407     FRect[0] =  xmmin ;
408     FRect[1] = -ymmax ;
409     FRect[2] =  xmmax ;
410     FRect[3] = -ymmin ; /* 2) ... (why - (minus) ? )*/
411     set_scale("tftttf",NULL,FRect,aaint,"nn",NULL);
412     Cscale.metric3d = flag; 
413   }
414 }
415
416
417 /**Nextind
418  * @author Djalel Abdemouche 10/2003
419  * Should be in Action.c file
420  */
421 void Nextind(integer ind1, integer *ind2, integer *ind3)
422 {
423   *ind2 = ind1+1;
424   *ind3 = ind1-1;
425   if (ind1 > 3)
426     {
427       if (*ind2 == 8) *ind2 = 4;
428       if (*ind3 == 3) *ind3 = 7;
429     }
430   else
431     {
432       if (*ind2 == 4) *ind2 = 0;
433       if (*ind3 == -1) *ind3 = 3;
434     }
435 }
436
437
438
439
440 BOOL Ishidden(sciPointObj *pobj)
441 {
442   double alpha;
443   if (sciGetEntityType(pobj) == SCI_SUBWIN){
444     alpha = pSUBWIN_FEATURE (pobj)->alpha;
445     if ((alpha <0.0 ) && (alpha > -90.0))
446       return TRUE;
447     if ((alpha <360.0 ) && (alpha > 270.0)) /* missing case added to fix bug 839 F.Leray */
448       return TRUE;
449     if ((alpha <-180.0 ) && (alpha > -270.0))
450       return TRUE;
451     if ((alpha <180.0 ) && (alpha > 90.0))
452       return TRUE;
453   }
454   return FALSE;
455 }
456
457 /* When alpha is close to a singularity (90,-90,270...), use to determine how to draw the x and y graduations */
458 /* depending on cof */
459 BOOL IsDownAxes(sciPointObj *pobj)
460 {
461   double alpha,cof;
462   
463   if (sciGetEntityType(pobj) == SCI_SUBWIN){
464     alpha = pSUBWIN_FEATURE (pobj)->alpha;   
465     if (!(pSUBWIN_FEATURE (pobj)->isoview))
466       cof=10.0;
467     else
468       cof = 5.0; /* F.Leray : hard fixed here */
469     /* Correction Warnings Attention Precision*/
470     /*   cof= (double) (Min(5.0,ceil(Max( */
471     /*                                abs((int)ppsubwin->axes.xlim[1]-(int)ppsubwin->axes.xlim[0])/ */
472     /*                                abs((int)ppsubwin->axes.ylim[1]-(int)ppsubwin->axes.ylim[0]), */
473     /*                                abs((int)ppsubwin->axes.ylim[1]-(int)ppsubwin->axes.ylim[0])/ */
474     /*                                abs((int)ppsubwin->axes.xlim[1]-(int)ppsubwin->axes.xlim[0]))))); */
475     if (cof == 0 ) cof =5;
476     if ((alpha <=(-90.0+cof) ) && (alpha >= (-90.0-cof))) 
477       return TRUE;
478     if ((alpha <=(-270.0+cof) ) && (alpha >= (-270.0-cof)))
479       return TRUE;
480     if ((alpha <=(90.0+cof) ) && (alpha >= (90.0-cof)))
481       return TRUE;
482     if ((alpha <=(270.0+cof) ) && (alpha >= (270.0-cof)))
483       return TRUE;
484   }
485   return FALSE;
486 }
487
488 /* compute the graduation of the segment [minVal,maxVal] knowing the number of ticks */
489 void GradFixedlog( double minVal, double maxVal, double * ticks, int nbGrads )
490 {
491   int initSize ;
492   int i ;
493
494   /* intialize the array as usual */
495   GradLog( minVal, maxVal, ticks, &initSize, FALSE ) ;
496
497   if ( initSize > nbGrads )
498   {
499     /* we create a smaller vector from a bigger one */
500     int nbRemove = initSize - nbGrads ;
501     
502     BOOL * removedTicks ;
503     if( ( removedTicks = MALLOC( initSize * sizeof(BOOL) ) ) == NULL )
504     {
505       return ;
506     }
507
508     for ( i = 0 ; i < initSize ; i++ )
509     {
510       removedTicks[i] = FALSE ;
511     }
512
513     /* we now remove the nbremove indexes : round( ( 0.5 + i ) * size / nbRemove ) */
514     /* i=0..nbReg-1 should do the thing */
515     for ( i = 0 ; i < nbRemove ; i++ )
516     {
517       int remIndex = 1 + (int) round(  i  * ((double) initSize - 2 ) / ( (double) nbRemove ) ) ;
518       removedTicks[remIndex] = TRUE ;
519     }
520
521     removeBadTicks( ticks, removedTicks, &initSize ) ;
522
523     FREE( removedTicks ) ;
524
525   }
526
527 }
528
529
530 /* compute the automatic graduation of the segment [_min,_max] and store it in _grads */
531 /* the number of graduation may be fixed if compNgrads is TRUE or automaticaly computed */
532 /* otherwise. */
533 int GradLog( double   _min   ,
534              double   _max   ,
535              double * _grads ,
536              int    * n_grads,
537              int      compNgrads )
538 {
539   int i;
540   int log_min, log_max;
541   int size;
542   
543   if ( compNgrads )
544   {
545     GradFixedlog( _min, _max, _grads, *n_grads ) ;
546     return 0 ;
547   }
548
549   log_max =  (int) ceil(_max);
550   log_min =  (int) floor(_min);
551   
552
553   size = log_max - log_min +1;
554   /*  tab=(int *)MALLOC(size*sizeof(int)); */
555   
556   /*   for(i=0;i<size;i++) tab[i]=log_min+i; */
557
558   *n_grads = 0 ;
559
560   if(size<=7)    {
561       for(i=0;i<size;i++)
562         {
563           /*    _grads[i] = exp10(tab[i]); */
564           _grads[i] = log_min+i;
565           *n_grads = (*n_grads) + 1;
566           /*      sciprint("Juste en sortie, _grads[%d] = %lf\n",i, _grads[i]); */
567         }
568     }
569   else
570     {
571       int pas = 0, old_pas= 0,j;
572       int val = size, passed = 0;
573       
574       for(j=val-1;j>1;j--)
575         if(val%j == 0){
576           old_pas = pas;
577           pas=j; 
578           passed = 1;
579
580           if((7*pas)<=val){ 
581             if(old_pas != 0) {pas = old_pas; }
582             break;
583           }
584         }
585       
586       if(passed != 1 || (size/pas)>15 ) pas = size;
587             
588       if(pas==size)
589         {
590           _grads[0] = log_min;
591           _grads[1] = log_max;
592           *n_grads =2;
593         }
594       else
595       {
596         for(i=0;i<=(int )(size/pas);i++)
597           {
598             _grads[i] = log_min+(i*pas);
599             
600             *n_grads = (*n_grads) + 1;
601             /*      sciprint("Juste en sortie, _grads[%d] = %lf\n",i, _grads[i]); */
602           }
603       }
604     }
605   
606   return 0;
607 }
608
609 /**
610  * get the exponent used for log axis from given data bounds
611  * @return 0 if OK, -1 if negative bounds.
612  */
613 int sciGetLogExponent( double minBound, double maxBound, double * expMin, double * expMax )
614 {
615   if ( minBound > 0 )
616   {
617     *expMin = floor( log10( minBound ) ) ;
618     *expMax = ceil(  log10( maxBound ) ) ;
619     return 0 ;
620   }
621   *expMax = 1.0 ;
622   *expMin = 0.0 ;
623   return -1 ;
624 }
625
626 /* get the displayed bounds of an axis */
627 void sciGetDisplayedBounds( sciPointObj * pSubWin,
628                             double      * xmin   ,
629                             double      * xmax   ,
630                             double      * ymin   ,
631                             double      * ymax   ,
632                             double      * zmin   ,
633                             double      * zmax    )
634 {
635   sciSubWindow * ppsubwin =  pSUBWIN_FEATURE ( pSubWin ) ;
636     /*****************************************************************
637      * get initial bounds
638    *****************************************************************/
639   if( sciGetZooming( pSubWin ) )
640   {
641     *xmin = ppsubwin->ZRect[0] ; 
642     *ymin = ppsubwin->ZRect[1] ; 
643     *xmax = ppsubwin->ZRect[2] ;
644     *ymax = ppsubwin->ZRect[3] ;
645     *zmin = ppsubwin->ZRect[4] ;
646     *zmax = ppsubwin->ZRect[5] ;
647   }
648   else
649   {
650     *xmin = ppsubwin->SRect[0] ;
651     *ymin = ppsubwin->SRect[2] ;
652     *xmax = ppsubwin->SRect[1] ;
653     *ymax = ppsubwin->SRect[3] ;
654     *zmin = ppsubwin->SRect[4] ;
655     *zmax = ppsubwin->SRect[5] ;
656   }
657   
658   
659    
660   /*****************************************************************
661    * modify  bounds and aaint  if using log scaling X axis
662    *****************************************************************/
663   if ( ppsubwin->logflags[0] == 'l' )
664   {
665     if ( sciGetLogExponent( *xmin, *xmax, xmin, xmax ) != 0 )
666     {
667       sciprint("Warning: Can't use Log on X-axis xmin is negative. \n");
668     }
669   }
670
671   /*****************************************************************
672    * modify  bounds and aaint  if using log scaling Y axis
673    *****************************************************************/
674   if ( ppsubwin->logflags[1] == 'l' )
675   {
676     if ( sciGetLogExponent( *ymin, *ymax, ymin, ymax ) != 0 )
677     {
678       sciprint("Warning: Can't use Log on Y-axis ymin is negative. \n");
679     }
680   }
681
682   /*****************************************************************
683    * modify  bounds and aaint  if using log scaling Z axis
684    *****************************************************************/
685   if ( ppsubwin->logflags[2] == 'l' )
686   {
687     if ( sciGetLogExponent( *zmin, *zmax, zmin, zmax ) != 0 )
688     {
689       sciprint("Warning: Can't use Log on Z-axis zmin is negative. \n");
690     }
691   }
692
693 }
694
695 /* F.Leray au 13.10.04 completly review for new axes graduations */
696 /*** F.Leray 02.04.04 */
697 /* FUNCTION FOR 2D UPDATE ONLY !!!!! <=> beginning of axis_3ddraw (in 2d HERE of course! ) */
698 /* Copy on update_frame_bounds */
699 BOOL sci_update_frame_bounds_2d(sciPointObj *pobj)
700 {
701   double xmax, xmin, ymin, ymax, zmin, zmax ;
702   double hx,hy,hx1,hy1;
703   int i;
704   
705   sciSubWindow * ppsubwin =  pSUBWIN_FEATURE (pobj);
706   double FRect[4],WRect[4],ARect[4]; 
707   char logscale[2];
708   
709   /* Temp variables only used when called from update_specification_bounds */
710   /* to know if we have to redraw all the figure */
711   double ExistingFRect[4]; /* the Existing FRect at start to be compared at the end of this routine */
712   /* in order to determine wheter or not the bounds have changed... */
713   int nbsubtics[2];
714   int nbgrads[2];
715   /* End of Temp variables */
716   
717   for(i=0;i<4;i++) ExistingFRect[i] =  ppsubwin->FRect[i]; /* store old initial bounds*/
718
719   for(i=0;i<2;i++) nbsubtics[i] = ppsubwin->axes.nbsubtics[i];
720   nbgrads[0] = ppsubwin->axes.nxgrads;
721   nbgrads[1] = ppsubwin->axes.nygrads;
722   
723   /* nbtics on z put to 0 */
724   /*   ppsubwin->axes.nzgrads = 0; */
725   
726
727   sciGetDisplayedBounds( pobj, &xmin, &xmax, &ymin, &ymax, &zmin, &zmax ) ;
728
729
730   /* _grad Init. to 0. */
731   for(i=0;i<20;i++) 
732     {
733       ppsubwin->axes.xgrads[i] = 0.;
734       ppsubwin->axes.ygrads[i] = 0.;
735     }
736    
737  
738   if ( ppsubwin->logflags[0]=='n') { /* x-axis */
739     TheTicks(&xmin, &xmax, &(ppsubwin->axes.xgrads[0]), &ppsubwin->axes.nxgrads, FALSE); 
740     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTics(pobj,ppsubwin->axes.nxgrads,'n',NULL,ppsubwin->axes.nbsubtics[0]); /* Nb of subtics computation and storage */ /* F.Leray 07.10.04 */
741   }
742   else{ /* log. case */
743     GradLog(xmin,xmax,ppsubwin->axes.xgrads,&ppsubwin->axes.nxgrads, FALSE );
744     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTics(pobj,ppsubwin->axes.nxgrads,'l',ppsubwin->axes.xgrads,0);
745   }
746    
747   if ( ppsubwin->logflags[1]=='n') { /* y-axis */
748     TheTicks(&ymin, &ymax, &(ppsubwin->axes.ygrads[0]), &ppsubwin->axes.nygrads, FALSE);
749     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTics(pobj,ppsubwin->axes.nygrads,'n',NULL, ppsubwin->axes.nbsubtics[1]); /* Nb of subtics computation and storage */ /* F.Leray 07.10.04 */
750   }
751   else{ /* log. case */
752     GradLog(ymin,ymax,ppsubwin->axes.ygrads,&ppsubwin->axes.nygrads, FALSE );
753     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTics(pobj,ppsubwin->axes.nygrads,'l',ppsubwin->axes.ygrads,0);
754   }
755    
756   if(ppsubwin->tight_limits == FALSE )
757     {
758       xmin = ppsubwin->axes.xgrads[0];
759       xmax = ppsubwin->axes.xgrads[ ppsubwin->axes.nxgrads - 1];
760       ymin = ppsubwin->axes.ygrads[0];
761       ymax = ppsubwin->axes.ygrads[ ppsubwin->axes.nygrads - 1];
762     }
763
764   /*****************************************************************
765    * modify  bounds if  isoview requested 
766    *****************************************************************/
767   if ( ppsubwin->isoview == TRUE) {      
768     int verbose=0,wdim[2],narg; 
769         
770     C2F(dr)("xget","wdim",&verbose,wdim,&narg, PI0, PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
771     hx=xmax-xmin;
772     hy=ymax-ymin;
773     getscale2d(WRect,FRect,logscale,ARect);
774     
775     wdim[0]=linint((double)wdim[0] *WRect[2]);
776     wdim[1]=linint((double)wdim[1] *WRect[3]);
777     
778     if ( hx/(double)wdim[0]  <hy/(double) wdim[1] ) {
779       hx1=wdim[0]*hy/wdim[1];
780       xmin=xmin-(hx1-hx)/2.0;
781       xmax=xmax+(hx1-hx)/2.0;
782     }
783     else {
784       hy1=wdim[1]*hx/wdim[0];
785       ymin=ymin-(hy1-hy)/2.0;
786       ymax=ymax+(hy1-hy)/2.0;
787     }
788     
789     /* F.Leray 28.09.04 */
790     /* I need to recompute the correct xgrads and ygrads vector to have a good display */
791      
792     if ( ppsubwin->logflags[0]=='n') { /* x-axis */
793       TheTicks(&xmin, &xmax, &(ppsubwin->axes.xgrads[0]), &ppsubwin->axes.nxgrads, FALSE);
794       ppsubwin->axes.nbsubtics[0] = ComputeNbSubTics(pobj,ppsubwin->axes.nxgrads,'n',NULL, ppsubwin->axes.nbsubtics[0]); /* Nb of subtics computation and storage */ /* F.Leray 07.10.04 */
795     }
796     else{ /* log. case */
797       GradLog(xmin,xmax,ppsubwin->axes.xgrads,&ppsubwin->axes.nxgrads, FALSE);
798       ppsubwin->axes.nbsubtics[0] = ComputeNbSubTics(pobj,ppsubwin->axes.nxgrads,'l',ppsubwin->axes.xgrads,0);
799     }
800
801  
802
803     if ( ppsubwin->logflags[1]=='n') { /* y-axis */
804       TheTicks(&ymin, &ymax, &(ppsubwin->axes.ygrads[0]), &ppsubwin->axes.nygrads, FALSE);
805       ppsubwin->axes.nbsubtics[1] = ComputeNbSubTics(pobj,ppsubwin->axes.nygrads,'n',NULL, ppsubwin->axes.nbsubtics[1]); /* Nb of subtics computation and storage */ /* F.Leray 07.10.04 */
806     }
807     else{ /* log. case */
808       GradLog(ymin,ymax,ppsubwin->axes.ygrads,&ppsubwin->axes.nygrads, FALSE );
809       ppsubwin->axes.nbsubtics[1] = ComputeNbSubTics(pobj,ppsubwin->axes.nygrads,'l',ppsubwin->axes.ygrads,0);
810     }
811    
812    
813     /* END ISO if */
814   }
815   
816   /* Changement ci-dessous F.Leray 21.09.04 */
817   ppsubwin->axes.xlim[0]=xmin;
818   ppsubwin->axes.xlim[1]=xmax;
819   ppsubwin->axes.xlim[2]=0;
820   ppsubwin->axes.ylim[0]=ymin;
821   ppsubwin->axes.ylim[1]=ymax;
822   ppsubwin->axes.ylim[2]=0;
823    
824    
825    
826   /*****************************************************************
827    * set the actual bounds in subwindow data structure
828    *****************************************************************/
829    
830    
831   ppsubwin->FRect[0]=xmin;
832   ppsubwin->FRect[2]=xmax;
833   ppsubwin->FRect[1]=ymin;
834   ppsubwin->FRect[3]=ymax;
835    
836   ppsubwin->axes.xlim[3] = ppsubwin->axes.nxgrads;
837   ppsubwin->axes.ylim[3] = ppsubwin->axes.nygrads;
838    
839   /*   ppsubwin->axes.reverse[0] = FALSE; /\*TRUE;*\/  /\* TEST en DUR F.Leray ICIIIIIIIIIIIII 12.10.04 *\/ */
840   /*    ppsubwin->axes.reverse[1] = FALSE; /\*TRUE;*\/  */
841    
842    
843   set_scale("tftftf",NULL,ppsubwin->FRect,NULL,ppsubwin->logflags,NULL); 
844    
845    
846   for(i=0;i<4;i++)
847     if(ppsubwin->FRect[i] != ExistingFRect[i]){
848       return TRUE;
849       break;
850     } 
851    
852   for(i=0;i<2;i++) 
853     if(nbsubtics[i] != ppsubwin->axes.nbsubtics[i]){
854       return TRUE;
855       break;
856     }
857    
858   if(nbgrads[0] != ppsubwin->axes.nxgrads) return TRUE;
859   if(nbgrads[1] != ppsubwin->axes.nygrads) return TRUE;
860    
861   return FALSE;
862 }
863
864 /**update_3dbounds -> renammed sci_update_frame_bounds_3d
865  * @author Djalel Abdemouche 10/2003
866  * Should be in Plo2dEch.c file
867  */
868 BOOL sci_update_frame_bounds_3d(sciPointObj *pobj)
869 {
870   double xmin,xmax,ymin,ymax,zmin,zmax; 
871   int i;
872   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (pobj); 
873
874   /* Temp variables only used when called from update_specification_bounds */
875   /* to know if we have to redraw all the figure */
876   double ExistingFRect[6]; /* the Existing FRect at start to be compared at the end of this routine */
877   /* in order to determine wheter or not the bounds have changed... */
878   int nbsubtics[3];
879   int nbgrads[3];
880   /* End of Temp variables */
881
882   for(i=0;i<6;i++) ExistingFRect[i] =  ppsubwin->FRect[i]; /* store old initial bounds*/
883   
884   for(i=0;i<3;i++) nbsubtics[i] = ppsubwin->axes.nbsubtics[i];
885   nbgrads[0] = ppsubwin->axes.nxgrads;
886   nbgrads[1] = ppsubwin->axes.nygrads;
887   nbgrads[2] = ppsubwin->axes.nzgrads;
888
889   sciGetDisplayedBounds( pobj, &xmin, &xmax, &ymin, &ymax, &zmin, &zmax ) ;
890   
891
892   /* _grad Init. to 0. */
893   for(i=0;i<20;i++) 
894     {
895       ppsubwin->axes.xgrads[i] = 0.;
896       ppsubwin->axes.ygrads[i] = 0.;
897       ppsubwin->axes.zgrads[i] = 0.;
898     }
899    
900   
901   if ( ppsubwin->logflags[0]=='n') { /* x-axis */
902     TheTicks(&xmin, &xmax, &(ppsubwin->axes.xgrads[0]), &ppsubwin->axes.nxgrads, FALSE);
903     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTics(pobj,ppsubwin->axes.nxgrads,'n',NULL,ppsubwin->axes.nbsubtics[0]); /* Nb of subtics computation and storage */
904   }
905   else{ /* log. case */
906     GradLog(xmin,xmax,ppsubwin->axes.xgrads,&ppsubwin->axes.nxgrads, FALSE );
907     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTics(pobj,ppsubwin->axes.nxgrads,'l',ppsubwin->axes.xgrads,0);
908   }
909   
910   if ( ppsubwin->logflags[1]=='n') { /* y-axis */
911     TheTicks(&ymin, &ymax, &(ppsubwin->axes.ygrads[0]), &ppsubwin->axes.nygrads, FALSE);
912     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTics(pobj,ppsubwin->axes.nygrads,'n',NULL, ppsubwin->axes.nbsubtics[1]); /* Nb of subtics computation and storage */
913   }
914   else{ /* log. case */
915     GradLog(ymin,ymax,ppsubwin->axes.ygrads,&ppsubwin->axes.nygrads, FALSE );
916     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTics(pobj,ppsubwin->axes.nygrads,'l',ppsubwin->axes.ygrads,0);
917   }
918   
919   if ( ppsubwin->logflags[2]=='n') { /* z-axis */
920     TheTicks(&zmin, &zmax, &(ppsubwin->axes.zgrads[0]), &ppsubwin->axes.nzgrads, FALSE);
921     ppsubwin->axes.nbsubtics[2] = ComputeNbSubTics(pobj,ppsubwin->axes.nzgrads,'n',NULL, ppsubwin->axes.nbsubtics[2]); /* Nb of subtics computation and storage */
922   }
923   else{ /* log. case */
924     GradLog(zmin,zmax,ppsubwin->axes.zgrads,&ppsubwin->axes.nzgrads, FALSE );
925     ppsubwin->axes.nbsubtics[2] = ComputeNbSubTics(pobj,ppsubwin->axes.nzgrads,'l',ppsubwin->axes.zgrads,0);
926   }
927   
928   if(ppsubwin->tight_limits == FALSE )
929     {
930       xmin = ppsubwin->axes.xgrads[0];
931       xmax = ppsubwin->axes.xgrads[ ppsubwin->axes.nxgrads - 1];
932       ymin = ppsubwin->axes.ygrads[0];
933       ymax = ppsubwin->axes.ygrads[ ppsubwin->axes.nygrads - 1];
934       zmin = ppsubwin->axes.zgrads[0];
935       zmax = ppsubwin->axes.zgrads[ ppsubwin->axes.nzgrads - 1];
936     }
937
938   ppsubwin->axes.xlim[0]=xmin;
939   ppsubwin->axes.xlim[1]=xmax;
940   ppsubwin->axes.xlim[2]=0;
941   ppsubwin->axes.ylim[0]=ymin;
942   ppsubwin->axes.ylim[1]=ymax;
943   ppsubwin->axes.ylim[2]=0;
944   ppsubwin->axes.zlim[0]=zmin; /* rajout pour z */
945   ppsubwin->axes.zlim[1]=zmax;
946   ppsubwin->axes.zlim[2]=0;
947      
948   ppsubwin->FRect[0]=xmin;
949   ppsubwin->FRect[2]=xmax;
950   ppsubwin->FRect[1]=ymin;
951   ppsubwin->FRect[3]=ymax;
952   ppsubwin->FRect[4]=zmin;
953   ppsubwin->FRect[5]=zmax;
954     
955   ppsubwin->axes.xlim[3] = ppsubwin->axes.nxgrads;
956   ppsubwin->axes.ylim[3] = ppsubwin->axes.nygrads;
957   ppsubwin->axes.zlim[3] = ppsubwin->axes.nzgrads;
958    
959   set_scale("tftftf",NULL,ppsubwin->FRect,NULL,ppsubwin->logflags,NULL); 
960      
961   wininfo("alpha=%.1f,theta=%.1f",ppsubwin->alpha,ppsubwin->theta); 
962     
963   for(i=0;i<6;i++)
964     if(ppsubwin->FRect[i] != ExistingFRect[i]){
965       return TRUE;
966       break;
967     } 
968     
969   for(i=0;i<3;i++) 
970     if(nbsubtics[i] != ppsubwin->axes.nbsubtics[i]){
971       return TRUE;
972       break;
973     }
974   
975   if(nbgrads[0] != ppsubwin->axes.nxgrads) return TRUE;
976   if(nbgrads[1] != ppsubwin->axes.nygrads) return TRUE;
977   if(nbgrads[2] != ppsubwin->axes.nzgrads) return TRUE;
978   
979   return FALSE;  
980 }
981
982
983
984
985
986
987
988 int ComputeNbSubTics(sciPointObj * pobj, int nbtics, char logflag, double * grads, int nbsubtics_input)
989 {
990   int ticsval[] =    {2 ,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
991   int subticsval[] = {10,7,5,5,4,4,3,2,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 };
992   int i;
993   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (pobj);
994
995
996   if(logflag =='l'){
997     if((grads[1]-grads[0])==1) /* intervalle de type ...10^n 10^(n+1)...*/
998       {
999         return 9; /* 9 subtics to have a pretty tics/grid in log.*/
1000       }
1001     else
1002       {
1003         return 1; /* no subtics at all (1 but draw on a tics place) */
1004       }
1005   }
1006   else{
1007     if(ppsubwin->flagNax == FALSE) /* if auto subtics mode == ON */
1008       { 
1009         for(i=0;i<19;i++)
1010           if(nbtics == ticsval[i])
1011             {
1012               return subticsval[i];
1013             }
1014       }
1015     else /* if auto subtics mode == OFF already computed in Plo2dn.c, Champ.c routines... */
1016       {  /* or given via a.subtics=[nbsubtics_on_x, nbsubtics_on_y, nbsubtics_on_z] command */
1017         return nbsubtics_input;
1018       }
1019   }
1020   
1021   return -1;
1022 }
1023
1024 /* test on x and y axes only : used in 2D routines only */
1025 BOOL GetIsAxes2D(sciPointObj *psubwin)
1026 {
1027   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (psubwin);
1028   
1029   if((ppsubwin->axes.axes_visible[0] == FALSE)
1030      && (ppsubwin->axes.axes_visible[1] == FALSE))
1031     return FALSE;
1032   else
1033     return TRUE;
1034 }
1035
1036 int ComputeCorrectXindAndInsideUD(double Teta,double Alpha, double *dbox, integer *xind, integer *InsideU, integer *InsideD)
1037 {
1038   double xbox[8], ybox[8], zbox[8];
1039
1040   Teta = 0.1; /* Little offset to compute correct values for xind,  InsideU and InsideD */
1041
1042   /* update Cscale.m from the new viewing angles */
1043   sciUpdateScaleAngles( Teta, Alpha ) ;
1044  
1045   sciGetAxisBox( dbox, xbox, ybox, zbox ) ;
1046  
1047   sciAxesVerticesIndices( InsideU, InsideD, xbox, ybox, xind ) ;
1048
1049   return 0;
1050 }
1051
1052 /* don't waste time on %NaN */
1053 int CheckIfiisNan(int j, int dim, int * tab)
1054 {
1055   int i;
1056
1057   for(i=0;i<dim;i++)
1058   {
1059     if(tab[i] == j)
1060       return -1;
1061   }
1062
1063   return 0;
1064 }
1065
1066
1067
1068 int ComputeGoodTrans3d( sciPointObj * psubwin, int n, int *xm, int *ym, double * fx, double *fy, double *fz)
1069 {
1070   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
1071
1072   
1073   double tmp_fx = *fx;
1074   double tmp_fy = *fy;
1075   double tmp_fz = *fz;
1076   
1077   if(ppsubwin->logflags[0] == 'l')
1078     tmp_fx = exp10(tmp_fx);
1079   
1080   if(ppsubwin->logflags[1] == 'l')
1081     tmp_fy = exp10(tmp_fy);
1082   
1083   if(ppsubwin->logflags[2] == 'l')
1084     tmp_fz = exp10(tmp_fz);
1085   
1086   trans3d(psubwin, n, xm, ym, &tmp_fx, &tmp_fy, &tmp_fz);
1087   
1088   return 0;
1089 }
1090
1091
1092 /**DrawAxesIfRequired
1093  * Draws Axes (only the basic  graphicobject under subwindows) in its SubWindow or figure
1094  * if and only if pFIGURE_FEATURE(pobj)->auto_redraw == TRUE !!
1095  * Only used inside High Level functions calls (sucha as plot2d, plot3d...)
1096  * @param sciPointObj * pobj: the pointer to the entity
1097  * @return  int 0 if OK, -1 if not
1098  */
1099 void DrawAxesIfRequired(sciPointObj * pobj)
1100 {
1101   sciPointObj * pfigure = sciGetParentFigure(pobj);
1102   
1103   if( pFIGURE_FEATURE(pfigure)->auto_redraw && pFIGURE_FEATURE(pfigure)->visible )
1104   {
1105     DrawAxes(pobj);
1106   }
1107   
1108 }
1109
1110 /* Routine used inside Plo2dn.c, Champ.c, Gray.c... */
1111 /* to force the drawing of the axes after a new object is created */
1112 void DrawAxes(sciPointObj * pobj)
1113 {
1114   sciPointObj * psubwin = sciGetParentSubwin(pobj);
1115   /*   sciPointObj * pfigure = sciGetParentFigure(pobj); */
1116   char STRFLAG[4];
1117   integer x[6], v, markidsizenew[2];
1118   double dv;
1119
1120   if (!sciGetVisibility(pobj)) return;
1121   
1122   x[0] = sciGetForeground (psubwin);
1123   x[2] = sciGetLineWidth (psubwin);
1124   x[3] = sciGetLineStyle (psubwin);
1125   markidsizenew[0] = sciGetMarkStyle(psubwin);
1126   markidsizenew[1] = sciGetLineWidth (psubwin);
1127   x[4] = 0;
1128   v = 0;
1129   dv = 0;
1130
1131   
1132   sciSetSelectedSubWin(psubwin); 
1133   
1134   set_scale ("tttftt", pSUBWIN_FEATURE (psubwin)->WRect, pSUBWIN_FEATURE (psubwin)->FRect,
1135              NULL, pSUBWIN_FEATURE (psubwin)->logflags, 
1136              pSUBWIN_FEATURE (psubwin)->ARect); 
1137      
1138   if (!pSUBWIN_FEATURE (psubwin)->is3d)   /* we are in 2D mode...*/
1139     {
1140       /* F.Leray 07.12.04 */
1141       /* TO CORRECT the bug 1115 : Big object (grayplots) could cover axes*/
1142       C2F (dr) ("xset","dashes",x,x,x+4,x+4,x+4,&v,&dv,&dv,&dv,&dv,5L,4096);
1143       C2F (dr) ("xset","foreground",x,x,x+4,x+4,x+4,&v,&dv,&dv,&dv,&dv,5L,4096);
1144       C2F (dr) ("xset","thickness",x+2,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1145       C2F (dr) ("xset","mark",&markidsizenew[0],&markidsizenew[1],PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1146
1147       rebuild_strflag(psubwin,STRFLAG);
1148       axis_draw2 (STRFLAG); /* Axes is rebuilt here to avoid being covered by the new created object */
1149     }
1150 }
1151
1152
1153 /* Used only when switching from a plot3d to a plot2d or 
1154  * when typing: a=gca();
1155  *              a.view='2d' and we were in 3d 
1156  * to have a good update of 3d graphics scale in 2D
1157  * whenever we are in auto_redraw OFF  */
1158 void UpdateSubwinScale(sciPointObj * pobj)
1159 {
1160   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (pobj);
1161   sciPointObj * currentsubwin = NULL;
1162   BOOL vis_save = FALSE;
1163   double xbox[8],ybox[8],zbox[8];
1164   static integer InsideU[4],InsideD[4];
1165         
1166   currentsubwin = (sciPointObj *)sciGetSelectedSubWin (sciGetCurrentFigure ());
1167
1168   sciSetSelectedSubWin(pobj); 
1169   
1170   /*   set_scale ("tttftt", pSUBWIN_FEATURE (pobj)->WRect, pSUBWIN_FEATURE (pobj)->FRect, */
1171   /*         NULL, pSUBWIN_FEATURE (pobj)->logflags,  */
1172   /*         pSUBWIN_FEATURE (pobj)->ARect);  */
1173   
1174   if (ppsubwin->is3d) 
1175     {  /* 3D Coordinates */ /* verifier si c'est encore utile SS */
1176       /*To have directly all the possible ISOVIEW Modes*/
1177       long isoflag = (long)(ppsubwin->axes.flag[1]+1)/2; 
1178       
1179       if(ppsubwin->isoview == TRUE) {
1180         if(isoflag ==2 || isoflag == 3){                }
1181         else {
1182           if((ppsubwin->axes.flag[1] == 0)
1183              || (ppsubwin->axes.flag[1] == 2))
1184             /* The default isoview mode is type=4 3d isometric bounds 
1185                derived from the data, to similarily type=2  */
1186             ppsubwin->axes.flag[1] = 4; 
1187           else if(ppsubwin->axes.flag[1] == 1)
1188             ppsubwin->axes.flag[1] = 3;
1189         }
1190       }
1191       else {
1192         if((ppsubwin->axes.flag[1] == 3) 
1193            || (ppsubwin->axes.flag[1] == 5))
1194           ppsubwin->axes.flag[1] = 1; /* computed from ebox*/
1195         else if((ppsubwin->axes.flag[1] == 4) 
1196                 || (ppsubwin->axes.flag[1] == 6))
1197           /* The default NON-isoview mode is 2 computed from data*/
1198           ppsubwin->axes.flag[1] = 2; 
1199       }
1200       
1201
1202       vis_save = sciGetVisibility(pobj);
1203
1204       sciSetVisibility(pobj,FALSE);
1205       axis_3ddraw(pobj,xbox,ybox,zbox,InsideU,InsideD); /* TEST on sciGetVisibility inside */
1206       /* because axis_3ddraw displays 3d axes BUT ALSO compute + reset the 3d scale BEFORE !! */
1207       sciSetVisibility(pobj,vis_save);
1208     }
1209   else /* we are in 2D mode...*/
1210     {
1211       sci_update_frame_bounds_2d(pobj);
1212     }
1213
1214   sciSetSelectedSubWin(currentsubwin); 
1215   
1216 }
1217
1218 int Gen3DPoints(integer type,integer *polyx, integer *polyy, integer *fill, integer whiteid, double zmin, double zmax, double *x, double *y, double *z, integer i, integer j, integer jj1, integer *p, integer dc, integer fg, sciPointObj * psurface)
1219 {
1220   sciPointObj *pobj;
1221   int facteur = 1;
1222
1223   sciPointObj *psubwin = sciGetSelectedSubWin (sciGetCurrentFigure ());
1224   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
1225   sciSurface * ppsurface = pSURFACE_FEATURE (psurface);
1226   
1227   pobj = sciGetSelectedSubWin (sciGetCurrentFigure ()); 
1228   if (trans3d(pobj ,1, &(polyx[  5*jj1]),&(polyy[  5*jj1]),&(x[i]),&(y[j]),&(z[i+(*p)*j]))==0) return 0; 
1229   if (trans3d(pobj ,1, &(polyx[1+  5*jj1]),&(polyy[1+  5*jj1]),&(x[i]),&(y[j+1]),&(z[i+(*p)*(j+1)]))==0) return 0; 
1230   if (trans3d(pobj ,1, &(polyx[2+  5*jj1]),&(polyy[2+  5*jj1]),&(x[i+1]),&(y[j+1]),&(z[(i+1)+(*p)*(j+1)]))==0) return 0; 
1231   if (trans3d(pobj ,1, &(polyx[3+  5*jj1]),&(polyy[3+  5*jj1]),&(x[i+1]),&(y[j]),&(z[(i+1)+(*p)*j]))==0) return 0;   
1232   if (trans3d(pobj ,1, &(polyx[4+  5*jj1]),&(polyy[4+  5*jj1]),&(x[i]),&(y[j]),&(z[i+(*p)*j]))==0) return 0; 
1233   
1234   
1235   if(ppsubwin->axes.reverse[0] == TRUE) facteur = -facteur;
1236   if(ppsubwin->axes.reverse[1] == TRUE) facteur = -facteur;
1237   if(ppsubwin->axes.reverse[2] == TRUE) facteur = -facteur;
1238   
1239   /* try */
1240   facteur = ppsurface->flag_x * ppsurface->flag_y * facteur;
1241   
1242   /* type == flagcolor and dc == color_mode */
1243   /* fg = hidden color */
1244   
1245   if ((((polyx[1+5*jj1]-polyx[0+5*jj1])*(polyy[2+5*jj1]-polyy[0+5*jj1])-
1246         (polyy[1+5*jj1]-polyy[0+5*jj1])*(polyx[2+5*jj1]-polyx[0+5*jj1]))*facteur <  0) && (fg >=0 )) 
1247     {
1248       
1249       /* ------------------- */
1250       /* Beneath the surface */
1251       /* ------------------- */
1252
1253       if (type != 0) /* flagcolor = 1 case : special treatment compared to flagcolor = 0 */
1254                      /* don't know why... F.Leray */
1255         fill[jj1]= (dc < 0 ) ? -fg : fg ;
1256       else           /* flagcolor = 0 :  No shading at all, fixed facecolor. */
1257         fill[jj1]=  (dc != 0 ) ? fg : dc ;
1258     }
1259   else
1260     {
1261
1262       /* ------------------- */
1263       /* Above the surface */
1264       /* ------------------- */
1265
1266      if (type != 0)
1267         {  /* flagcolor = 1 :  Z-level flat shading. */
1268           fill[jj1]=inint((whiteid-1)*((1/4.0*( z[i+(*p)*j]+ z[i+1+(*p)*j]+
1269                                                 z[i+(*p)*(j+1)]+ z[i+1+(*p)*(j+1)])-zmin)
1270                                        /(zmax-zmin)))+1;
1271           if ( dc < 0 ) fill[jj1]= -fill[jj1];  
1272         }
1273       else
1274         fill[jj1]= dc;     
1275     }
1276   
1277   return(1);
1278   
1279 }
1280
1281
1282
1283 int Merge3dDimension(sciPointObj *pparent)
1284 {
1285   integer N,q; 
1286   sciSons *psonstmp;
1287
1288   /* ========================================================================
1289    * Compute the number of facets, segments,... included in all the subwin 
1290    * children
1291    * Each entities to merge; is decomposed in a set of basic elements 
1292    *  (facet, segment, point,...)
1293    * Each basic element is represented in the Merge structure by the handle of its entity and an 
1294    *   index within this entity
1295    * ========================================================================*/
1296
1297   q=0;
1298   psonstmp = sciGetSons (pparent);
1299   while (psonstmp != (sciSons *) NULL) {   
1300     switch (sciGetEntityType (psonstmp->pointobj)) {  
1301     case SCI_SURFACE:
1302       if (pSURFACE_FEATURE (psonstmp->pointobj)->typeof3d == SCI_PLOT3D) 
1303         N=(pSURFACE_FEATURE (psonstmp->pointobj)->dimzx-1)*(pSURFACE_FEATURE (psonstmp->pointobj)->dimzy-1);
1304       else
1305         N = pSURFACE_FEATURE (psonstmp->pointobj)->dimzy;
1306       break;
1307
1308     case  SCI_POLYLINE:
1309       {
1310         if ( pPOLYLINE_FEATURE(psonstmp->pointobj)->n1 == 0 )
1311         {
1312           N = 0 ;
1313         }
1314         else if (pPOLYLINE_FEATURE (psonstmp->pointobj)->plot != 5)
1315         {/*polyline*/
1316           N = pPOLYLINE_FEATURE (psonstmp->pointobj)->n1-1;
1317           if ((pPOLYLINE_FEATURE (psonstmp->pointobj)->plot != 2) && 
1318             (sciGetIsMark((sciPointObj *)psonstmp->pointobj) == 1))
1319           {
1320             N = N + 1 ;
1321           }
1322         }
1323         else /* patch */
1324         {
1325           N = 1 ;
1326         }
1327       }
1328       break;
1329     case  SCI_SEGS: 
1330       N=pSEGS_FEATURE (psonstmp->pointobj)->Nbr1 / 2 ;
1331       break;
1332     case  SCI_RECTANGLE: 
1333       N = 4;
1334       break;
1335     case SCI_AGREG:
1336       N =  Merge3dDimension(psonstmp->pointobj);
1337       break;
1338     default:
1339       N=0;
1340     }
1341     q+=N;
1342     psonstmp = psonstmp->pnext;
1343   }
1344
1345   return q;
1346 }
1347
1348 int ChildrenCounter(sciPointObj *pparent)
1349 {
1350   int N,q=0;
1351   sciSons * psonstmp = sciGetSons (pparent);
1352   
1353   while (psonstmp != (sciSons *) NULL) {   
1354     switch (sciGetEntityType (psonstmp->pointobj)) {  
1355     case SCI_SURFACE:
1356       N=1;
1357       break;
1358     case  SCI_POLYLINE:
1359       N = 1; 
1360       break;
1361     case  SCI_SEGS: 
1362       N=1;
1363       break;
1364     case  SCI_RECTANGLE: 
1365       N = 1;
1366       break;
1367     case SCI_AGREG:
1368       N = ChildrenCounter(psonstmp->pointobj);
1369       break;
1370     default:
1371       N=0;
1372     }
1373     q+=N;
1374     psonstmp = psonstmp->pnext;
1375   }
1376
1377   return q;
1378 }
1379
1380
1381 void Merge3dBuildTable(sciPointObj *pparent, int *index_in_entity, long *from_entity, int *pos)
1382 {
1383   sciSons *psonstmp;
1384   int i,N;
1385
1386   psonstmp = sciGetSons (pparent);
1387
1388   while (psonstmp != (sciSons *) NULL) {   
1389     switch (sciGetEntityType (psonstmp->pointobj)) {  
1390     case SCI_SURFACE:
1391       if (pSURFACE_FEATURE (psonstmp->pointobj)->typeof3d == SCI_PLOT3D) 
1392         N=(pSURFACE_FEATURE (psonstmp->pointobj)->dimzx-1)*(pSURFACE_FEATURE (psonstmp->pointobj)->dimzy-1);
1393       else
1394         N = pSURFACE_FEATURE (psonstmp->pointobj)->dimzy;
1395       break;
1396     case  SCI_POLYLINE:
1397       if ( pPOLYLINE_FEATURE(psonstmp->pointobj)->n1 == 0 )
1398       {
1399         N = 0 ;
1400       }
1401       else if (pPOLYLINE_FEATURE (psonstmp->pointobj)->plot != 5)
1402       {/*polyline*/
1403         N = pPOLYLINE_FEATURE (psonstmp->pointobj)->n1-1;
1404         if ((pPOLYLINE_FEATURE (psonstmp->pointobj)->plot != 2) && 
1405             (sciGetIsMark((sciPointObj *)psonstmp->pointobj) == 1))
1406         {
1407           N = N + 1 ;
1408         }
1409       }
1410       else /* patch */
1411       {
1412         N = 1 ;
1413       }
1414       break;
1415     case  SCI_SEGS: 
1416       N=pSEGS_FEATURE (psonstmp->pointobj)->Nbr1/2;
1417       break;
1418     case  SCI_RECTANGLE: 
1419       N = 4;
1420       break;
1421     case SCI_AGREG:
1422       Merge3dBuildTable(psonstmp->pointobj, index_in_entity, from_entity, pos);
1423       break;
1424     default:
1425       N = 0;
1426     }
1427     if (sciGetEntityType (psonstmp->pointobj) != SCI_AGREG)
1428       for (i=0 ; i<N; i++) {
1429         index_in_entity[*pos]=i;
1430         from_entity[*pos]=(long) sciGetHandle (psonstmp->pointobj);
1431         *pos=*pos+1;
1432       }
1433     psonstmp = psonstmp->pnext;
1434   }
1435 }
1436
1437
1438 void Merge3d(sciPointObj *psubwin)
1439 {
1440   integer q,k; 
1441   sciPointObj *pmerge; 
1442   int *index_in_entity;
1443   long *from_entity;
1444   
1445   if(sciGetEntityType (psubwin) != SCI_SUBWIN) return; 
1446   if ((pmerge= sciGetMerge(psubwin)) != (sciPointObj *) NULL)
1447     DestroyMerge(pmerge); 
1448   
1449   /* ========================================================================
1450    * Compute the number of facets, segments,... included in all the subwin 
1451    * children
1452    * ========================================================================*/
1453   
1454   
1455   q =  Merge3dDimension(psubwin);
1456   
1457   
1458   /* ========================================================================
1459    * allocate tables for index and handles
1460    * ========================================================================*/
1461   
1462   /* q now contains the total number of elements */
1463   if ((index_in_entity = (int *) MALLOC (q * sizeof (int))) == (int *)NULL) {
1464     sciprint("Merge3d : not enough memory to allocate \n");
1465     return;
1466   }
1467   if ((from_entity   = (long *) MALLOC (q * sizeof (long))) == (long *) NULL) {
1468     sciprint("Merge3d : not enough memory to allocate \n");
1469     FREE(index_in_entity);
1470   }
1471   
1472   /* ========================================================================
1473    * fill the index and handles tables
1474    * ========================================================================*/
1475   k=0;
1476   Merge3dBuildTable(psubwin, index_in_entity, from_entity, &k);
1477   
1478   /* ========================================================================
1479    * create the Merge data structure
1480    * ========================================================================*/
1481   
1482   if ((pmerge=ConstructMerge ((sciPointObj *) psubwin,q,index_in_entity,from_entity)) == (sciPointObj *) NULL) {
1483     FREE(index_in_entity);
1484     FREE(from_entity);
1485     sciprint ("\r\n No merge supported");}
1486   else /* inform the subwindow to display Merge instead of individual children */
1487     pSUBWIN_FEATURE (psubwin)->facetmerge = TRUE;
1488   
1489 }
1490
1491 /*------------------------------------------------------------------------------------------*/
1492 /**
1493  * draw the figure number numFigure.
1494  */
1495 void sciDrawFigure( int numFigure )
1496 {
1497   int curFigure = sciGetNumFigure( sciGetCurrentFigure() ) ;
1498   sciSetUsedWindow( numFigure ) ;
1499   sciDrawObj( sciGetCurrentFigure() ) ;
1500   sciSetUsedWindow( curFigure ) ;
1501 }
1502 /*------------------------------------------------------------------------------------------*/
1503
1504 /*-------------------------------------------------------------------------------------------*/
1505 /* sciRefreshObj                                                                             */
1506 /* draw an object but before select the rigth figure for display                             */
1507 /*-------------------------------------------------------------------------------------------*/
1508 int sciRefreshObj( sciPointObj * pobj )
1509 {
1510   
1511   int parentId = sciGetNum( sciGetParentFigure( pobj ) ) ;
1512   int currentId             ;
1513   int status                ;
1514   int verboseGet        = 0 ;
1515   int iDontKnowWhatItIs     ;
1516   /* get current Id in ScilabXgc */
1517   C2F (dr) ("xget", "window",&verboseGet,&currentId,&iDontKnowWhatItIs,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1518
1519   /* set the parent figure of the object as the current figure */
1520   if ( parentId != currentId )
1521   {
1522     C2F (dr) ("xset", "window",&parentId,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1523   }
1524   
1525   /* draw the object */
1526   status = sciDrawObjIfRequired( pobj ) ;
1527
1528   /* set back the values */
1529   if ( parentId != currentId )
1530   {
1531     C2F (dr) ("xset", "window",&currentId,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1532   }
1533
1534   return status ;
1535   
1536   
1537 }
1538
1539
1540
1541 /**sciDrawObjIfRequired
1542  * Draws Object (only the basic  graphicobject under subwindows) in its SubWindow or figure
1543  * if and only if pFIGURE_FEATURE(pobj)->auto_redraw == TRUE !!
1544  * Only used inside High Level functions calls (sucha as plot2d, plot3d...)
1545  * @param sciPointObj * pobj: the pointer to the entity
1546  * @return  int 0 if OK, -1 if not
1547  */
1548 int
1549 sciDrawObjIfRequired (sciPointObj * pobj)
1550 {
1551   sciPointObj * pfigure = sciGetParentFigure(pobj);
1552
1553   if( pFIGURE_FEATURE(pfigure)->auto_redraw && pFIGURE_FEATURE(pfigure)->visible )
1554   {
1555     sciDrawObj(pobj);
1556   }
1557
1558   return 0;
1559 }
1560
1561 /**sciDrawObj
1562  * Draws Object (only the basic  graphicobject under subwindows) in its SubWindow or figure
1563  * @param sciPointObj * pobj: the pointer to the entity
1564  * @return  int 0 if OK, -1 if not
1565  */
1566 int
1567 sciDrawObj (sciPointObj * pobj)
1568 {
1569   
1570   /*sciPointObj * curSubWin = sciGetSelectedSubWin( sciGetCurrentFigure() ) ;*/
1571   
1572   /* driver test */  
1573   if((GetDriverId() != 0) && ( isGraphicSessionOpened() )){
1574     return -1;
1575   }
1576
1577   switch (sciGetEntityType (pobj))
1578     {
1579     case SCI_FIGURE:
1580       return drawFigureEntity( pobj ) ;
1581       break;
1582     case SCI_SUBWIN:
1583       return drawSubWinEntity( pobj ) ;
1584       break ;
1585     case SCI_AGREG:
1586       return drawCompoundEntity( pobj ) ;
1587       break;
1588     case SCI_LEGEND:
1589       return drawLegendEntity( pobj ) ;
1590       break;   
1591     case SCI_FEC:
1592       return drawFecEntity( pobj ) ;
1593       break;      
1594     case SCI_SEGS:
1595       return drawSegsEntity( pobj ) ;
1596       break;
1597     case SCI_GRAYPLOT:
1598       return drawGrayplotEntity( pobj ) ;
1599       break;
1600     case SCI_POLYLINE:   
1601       return drawPolylineEntity( pobj ) ;
1602       break;
1603     case SCI_ARC:
1604       return drawArcEntity( pobj ) ;
1605       break;
1606     case SCI_RECTANGLE:
1607       return drawRectangleEntity( pobj ) ;
1608       break;
1609     case SCI_TEXT:
1610       return drawTextEntity( pobj ) ;
1611       break;
1612     case SCI_AXES:
1613       return drawAxesEntity(pobj) ;
1614       break;
1615     case SCI_MERGE:
1616       return drawMergeEntity(pobj) ;
1617       break ;
1618     case SCI_SURFACE:
1619       return drawSurfaceEntity(pobj) ;
1620       break;
1621     case SCI_LIGHT:
1622     case SCI_PANNER:
1623     case SCI_SBH:
1624     case SCI_SBV:
1625     case SCI_MENU:
1626     case SCI_MENUCONTEXT:
1627     case SCI_STATUSB:
1628     default:
1629       return -1;
1630       break;
1631     }
1632   /*sciSetSelectedSubWin (curSubWin);*/
1633   return -1;
1634 }
1635
1636
1637
1638
1639 /* F.Leray 25.02.05 */
1640 /* This function is used to determine how the pixel data*/
1641 /* is given to Xt method (like XDrawLines) */
1642 /* 0 : pixel itself */
1643 /* 1 : pixel's interval */
1644 /* Explanation :*/
1645 /* i.e.in X11 (same thing using Win32 driver), with x2=x1+1 and y1=y2, we have : */
1646 /*   XDrawLine(x1,y1,x1,y1)  does nothing (no pixel lit) */
1647 /*   XDrawLine(x1,y1,x2,y2)  ONE pixel lit */
1648 /* BUT the corresponding function with driver Gif (and others?) give us: */
1649 /* for now (and only for marks), I make a trick using a pixel_offset set to 0 or 1 */
1650 /* depending on the driver. */
1651
1652 /* slight modif from Bruno : if fact GetDriverId return also 0 */
1653 /* if gtk is enable so I have added a call to withgtk to get the */
1654 /* the good pixel_offset */
1655
1656
1657
1658 int AdaptGraduationsOnYBottomLeft(int iof, int x, int y, int size, integer *Ticsdir, int *fontid, sciPointObj * psubwin, double yminval, double ymaxval, double fx, double fy, double fz)
1659 {
1660   int i;
1661   int nbtics, nbsubtics;
1662   int lastyindex;
1663   int old_rect[4];
1664   int nb_grads_max = 0;
1665   int vx[2], vy[2];
1666   int xm, ym;
1667   double grads_tmp[20];
1668   char c_format[5];
1669   integer barlengthx = 0,barlengthy = 0;
1670   integer rect[4],posi[2];
1671   integer textcolor = -1;
1672   int logrect[4] ;
1673   int XX = 0 ;
1674   int YY = 0 ;
1675   int pas;
1676   double fact_h = 1.5, fact_w = 1.5;
1677   int compteur = 0;
1678
1679   int possible_pas, possible_compteur;
1680   
1681   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
1682   
1683   for(i=0;i<4;i++) { old_rect[i] = 0 ; } /* Init. old_rect to force first grad. to be displayed */
1684   
1685   lastyindex = ppsubwin->axes.nygrads - 1;
1686   
1687   if(lastyindex == 0)
1688     ChooseFormatForOneGrad(c_format,&(ppsubwin->axes.ygrads[0]));
1689   else
1690     ChoixFormatE(c_format,
1691                  ppsubwin->axes.ygrads[0],
1692                  ppsubwin->axes.ygrads[lastyindex],
1693                  ((ppsubwin->axes.ygrads[lastyindex])-(ppsubwin->axes.ygrads[0]))/(lastyindex));
1694   
1695   nbtics = ppsubwin->axes.nygrads;
1696   nbsubtics = ppsubwin->axes.nbsubtics[1];
1697   
1698   
1699   for(i=0;i<nbtics;i++) grads_tmp[i] = ppsubwin->axes.ygrads[i];
1700
1701   for(i=0;i<nbtics;i++)
1702     {
1703       char foo[256];
1704       double ytmp = ppsubwin->axes.ygrads[i];
1705                   
1706                   
1707       sprintf(foo,c_format,ytmp);
1708
1709       /***************************************************************/
1710       /************************* COMMON PART *************************/
1711       /***************************************************************/
1712       if(ppsubwin->axes.reverse[1] == TRUE)
1713         ytmp = InvAxis(ppsubwin->FRect[1],ppsubwin->FRect[3],ytmp);
1714                   
1715       ComputeGoodTrans3d(psubwin,1,&xm,&ym,&fx,&ytmp,&fz);
1716                   
1717       vx[0]=xm;vy[0]=ym;
1718                   
1719       barlengthx= (integer) (( Ticsdir[0])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
1720       barlengthy= (integer) (( Ticsdir[1])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
1721
1722       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L); /* fix bug noticed by R.N. */
1723       C2F(dr)("xstringl",foo,&x,&y,rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1724                       
1725       
1726       if (IsDownAxes(psubwin)){
1727         vx[1]=vx[0];
1728         vy[1]=vy[0]+iof/2;
1729         posi[0] = inint(xm-rect[2]/2);
1730         posi[1]=inint( vy[0] + iof + rect[3]);}
1731       else{
1732         vx[1]=vx[0]+barlengthx;
1733         vy[1]=vy[0]+barlengthy;
1734 /*      posi[0] = inint( xm+2*barlengthx-rect[2]/2);  */
1735         posi[0] = inint( xm+2*barlengthx-rect[2]);
1736         posi[1]=inint( ym + 2*barlengthy + rect[3]);}
1737       
1738       /* compute bounding of "10"  string used for log scale ON and auto_ticks ON */
1739       C2F(dr)("xstringl","10",&XX,&YY,logrect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1740       
1741       
1742       if(CheckDisplay(fact_h, fact_w, ppsubwin->logflags[1],foo,posi,fontid,old_rect) == 0)
1743         continue; /*  graduation too close, DO NOT display the graduation ! */
1744       
1745       
1746       C2F(dr)("xset","pattern",&textcolor,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1747       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1748       if ( ppsubwin->logflags[1] == 'l' )
1749         {
1750           int smallersize = fontid[1]-2;
1751           int old_rect10[4];
1752           int posi10[2];
1753
1754           posi10[0] = posi[0] - logrect[2];
1755           posi10[1] = posi[1] + logrect[3];
1756           
1757           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1758           
1759           C2F(dr)("xstringl","10",(&posi10[0]),(&posi10[1]),old_rect10,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1760           
1761           posi[0] = old_rect10[0] + old_rect10[2];
1762           posi[1] = (int) (old_rect10[1] - old_rect10[3]*.1);
1763           
1764           C2F(dr)("xset","font",fontid,&smallersize,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1765           C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1766           
1767           /* update old_rect */
1768           old_rect[2] = (int)(fact_w*(old_rect[2] + (double)old_rect10[2]));
1769           old_rect[3] = (int)(fact_h*(old_rect[3] + old_rect10[3] + (int) (old_rect10[3]*.1)));
1770           old_rect[0] = old_rect10[0];
1771           old_rect[1] = old_rect[1];
1772           
1773           nb_grads_max++;
1774           
1775           /* put back the current fontid */
1776           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1777         }
1778       else{
1779         /* update old_rect */
1780         C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1781         old_rect[3] = (int)(fact_h* old_rect[3]);
1782         old_rect[2] = (int)(fact_w* old_rect[2]);
1783         nb_grads_max++;
1784       }
1785     }
1786   
1787   if(ppsubwin->logflags[1] != 'l')
1788     if(nb_grads_max == 1) /* only one grad. can be displayed : we choose to display the average value (max+min)/2 */
1789       {
1790         ppsubwin->axes.ygrads[0] = (grads_tmp[0]+grads_tmp[lastyindex])/2.;
1791         ppsubwin->axes.nygrads = 1;
1792         
1793         if ( !ppsubwin->flagNax )
1794         {
1795           /* don't change the number if it aldready has been specified */
1796           ppsubwin->axes.nbsubtics[1] = 1 ;
1797         }
1798         return 0;
1799       }
1800   
1801   
1802   pas = nbtics - 2; /* pas == grads number - 2 */
1803   
1804   possible_pas = -99;
1805   possible_compteur = -99;
1806   
1807   while(pas > 0)
1808     {
1809       int tmp = 0;
1810       compteur = 0;
1811       for(;;)
1812         {
1813           tmp = tmp + pas;
1814           compteur++;
1815           
1816           if((tmp == (nbtics - 1)) && (compteur < nb_grads_max)){
1817             possible_pas = pas;
1818             possible_compteur = ++compteur;
1819             break;
1820           }
1821           
1822           if(tmp > (nbtics - 1))
1823             break;
1824         }
1825       
1826       pas--;
1827     }
1828   
1829   
1830   if(possible_compteur != -99){
1831     compteur = possible_compteur;
1832     pas = possible_pas;
1833     
1834     for(i=0;i<compteur;i++)
1835       ppsubwin->axes.ygrads[i] = grads_tmp[i*pas];
1836     
1837     ppsubwin->axes.nygrads = compteur;
1838     
1839     /* Nb of subtics computation and storage */
1840     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
1841     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTicsFor3dUse(psubwin,
1842                                                            ppsubwin->axes.nygrads,
1843                                                            ppsubwin->logflags[1],
1844                                                            ppsubwin->axes.ygrads,
1845                                                            ppsubwin->axes.nbsubtics[1]);
1846   }
1847   else{
1848     ppsubwin->axes.ygrads[0] = grads_tmp[0];
1849     ppsubwin->axes.ygrads[1] = grads_tmp[lastyindex];
1850     ppsubwin->axes.nygrads = 2;
1851     /* Nb of subtics computation and storage */
1852     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
1853     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTicsFor3dUse(psubwin,
1854                                                            ppsubwin->axes.nygrads,
1855                                                            ppsubwin->logflags[1],
1856                                                            ppsubwin->axes.ygrads,
1857                                                            ppsubwin->axes.nbsubtics[1]);
1858     
1859     if(ppsubwin->logflags[1] == 'n'){
1860       if(nb_grads_max > 4) {
1861         /* we could display at least 4 graduations but we did not find a proper interval... */
1862         /* To avoid to display only the min and max (see above), we add 2 newly created grads by interpolating between min and max */
1863         double pas_ = (grads_tmp[lastyindex]-grads_tmp[0])/3;
1864         for(i=0;i<3;i++){
1865           ppsubwin->axes.ygrads[i] = grads_tmp[0] + i*pas_;
1866         }
1867         
1868         ppsubwin->axes.ygrads[3] = grads_tmp[lastyindex]; /* exact max */
1869         ppsubwin->axes.nygrads = 4;
1870         /* Nb of subtics computation and storage */
1871         ppsubwin->axes.nbsubtics[1] = ComputeNbSubTicsFor3dUse(psubwin,
1872                                                                ppsubwin->axes.nygrads,
1873                                                                'n',
1874                                                                ppsubwin->axes.ygrads,
1875                                                                ppsubwin->axes.nbsubtics[1]);
1876       }
1877     }
1878   }
1879   
1880   return 0;
1881 }
1882
1883
1884 int AdaptGraduationsOnXBottomLeft(int iof, int x, int y, int size, integer *Ticsdir, int *fontid, sciPointObj * psubwin, double xminval, double xmaxval, double fx, double fy, double fz)
1885 {
1886   int i;
1887   int nbtics, nbsubtics;
1888   int lastxindex;
1889   int old_rect[4];
1890   int nb_grads_max = 0;
1891   int vx[2], vy[2];
1892   int xm, ym;
1893   double grads_tmp[20];
1894   char c_format[5];
1895   integer barlengthx = 0,barlengthy = 0;
1896   integer rect[4],posi[2]; 
1897   integer textcolor = -1;
1898   int logrect[4],XX,YY;
1899   int pas;
1900   double fact_h = 1.5, fact_w = 1.5;
1901   int compteur = 0;
1902
1903   int possible_pas, possible_compteur;
1904   
1905   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
1906   
1907   for(i=0;i<4;i++) old_rect[i] = 0; /* Init. old_rect to force first grad. to be displayed */
1908   
1909   lastxindex = ppsubwin->axes.nxgrads - 1;
1910   
1911   if(lastxindex == 0)
1912     ChooseFormatForOneGrad(c_format,&(ppsubwin->axes.xgrads[0]));
1913   else
1914     ChoixFormatE(c_format,
1915                  ppsubwin->axes.xgrads[0],
1916                  ppsubwin->axes.xgrads[lastxindex],
1917                  ((ppsubwin->axes.xgrads[lastxindex])-(ppsubwin->axes.xgrads[0]))/(lastxindex));
1918   
1919   nbtics = ppsubwin->axes.nxgrads;
1920   nbsubtics = ppsubwin->axes.nbsubtics[0];
1921   
1922   
1923   for(i=0;i<nbtics;i++) grads_tmp[i] = ppsubwin->axes.xgrads[i];
1924
1925   for(i=0;i<nbtics;i++)
1926     {
1927       char foo[256]; 
1928       double xtmp = ppsubwin->axes.xgrads[i];
1929                   
1930 /*       if(xtmp<xminval || xtmp>xmaxval)  */
1931 /*      { */
1932 /*        /\*   sciprint("je rejete la valeur: %lf\n\n",xtmp); *\/ */
1933 /*        continue; /\* cas ou TL est ON et on a des graduations qui ne seront pas affichees de tte facon *\/ */
1934 /*        /\* donc autant ne pas aller plus loin dans l'algo... *\/ */
1935 /*      } */
1936                   
1937       sprintf(foo,c_format,xtmp);
1938
1939       /***************************************************************/
1940       /************************* COMMON PART *************************/
1941       /***************************************************************/
1942       if(ppsubwin->axes.reverse[0] == TRUE)
1943         xtmp = InvAxis(ppsubwin->FRect[0],ppsubwin->FRect[2],xtmp);
1944                   
1945       ComputeGoodTrans3d(psubwin,1,&xm,&ym,&xtmp,&fy,&fz);
1946                   
1947       vx[0]=xm;vy[0]=ym; 
1948                   
1949       barlengthx= (integer) (( Ticsdir[0])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
1950       barlengthy= (integer) (( Ticsdir[1])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
1951
1952       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L); /* fix bug noticed by R.N. */
1953       C2F(dr)("xstringl",foo,&x,&y,rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1954       
1955
1956 /*       if (IsDownAxes(psubwin)){ */
1957 /*      vx[1]=vx[0]; */
1958 /*      vy[1]=vy[0]+iof/2; */
1959 /*      posi[0] = inint(xm-rect[2]/2);  */
1960 /*      posi[1]=inint( vy[0] + iof + rect[3]);} */
1961 /*       else{ */
1962 /*      vx[1]=vx[0]+barlengthx; */
1963 /*      vy[1]=vy[0]+barlengthy; */
1964 /*      posi[0] = inint( xm+2*barlengthx); */
1965 /*      posi[1]=inint( ym + 2*barlengthy + rect[3]);} */
1966                       
1967       if (IsDownAxes(psubwin)){
1968         vx[1]=vx[0];
1969         vy[1]=vy[0]+iof/2;
1970         posi[0] = inint(xm-rect[2]/2); 
1971         posi[1]=inint( vy[0] + iof + rect[3]);}
1972       else{
1973         vx[1]=vx[0]+barlengthx;
1974         vy[1]=vy[0]+barlengthy;
1975         posi[0] = inint( xm+2*barlengthx-rect[2]); 
1976         posi[1]=inint( ym + 2*barlengthy + rect[3]);}
1977       
1978       /* compute bounding of "10"  string used for log scale ON and auto_ticks ON */
1979       C2F(dr)("xstringl","10",&XX,&YY,logrect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);       
1980       
1981       
1982       if(CheckDisplay(fact_h, fact_w, ppsubwin->logflags[0],foo,posi,fontid,old_rect) == 0)
1983         continue; /*  graduation too close, DO NOT display the graduation ! */
1984       
1985       
1986       C2F(dr)("xset","pattern",&textcolor,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1987       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1988       if ( ppsubwin->logflags[0] == 'l' )
1989         {
1990           int smallersize = fontid[1]-2;
1991           int old_rect10[4];
1992           int posi10[2];
1993
1994           posi10[0] = posi[0] - logrect[2];
1995           posi10[1] = posi[1] + logrect[3];
1996           
1997           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
1998           
1999           C2F(dr)("xstringl","10",(&posi10[0]),(&posi10[1]),old_rect10,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2000           
2001           posi[0] = old_rect10[0] + old_rect10[2];
2002           posi[1] = (int) (old_rect10[1] - old_rect10[3]*.1);
2003           
2004           C2F(dr)("xset","font",fontid,&smallersize,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2005           C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2006           
2007           /* update old_rect */
2008           old_rect[2] = (int)(fact_w*(old_rect[2] + old_rect10[2]));
2009           old_rect[3] = (int)(fact_h*(old_rect[3] + old_rect10[3] + (int) (old_rect10[3]*.1)));
2010           old_rect[0] = old_rect10[0];
2011           old_rect[1] = old_rect[1];
2012           
2013           nb_grads_max++;
2014           
2015           /* put back the current fontid */
2016           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2017         }
2018       else{
2019         /* update old_rect */
2020         C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2021         old_rect[3] = (int)(fact_h* old_rect[3]);
2022         old_rect[2] = (int)(fact_w* old_rect[2]);
2023         nb_grads_max++;
2024       }
2025     }
2026   
2027   if(ppsubwin->logflags[0] != 'l')
2028     if(nb_grads_max == 1) /* only one grad. can be displayed : we choose to display the average value (max+min)/2 */
2029       {
2030         ppsubwin->axes.xgrads[0] = (grads_tmp[0]+grads_tmp[lastxindex])/2.;
2031         ppsubwin->axes.nxgrads = 1;
2032         if ( !ppsubwin->flagNax )
2033         {
2034           ppsubwin->axes.nbsubtics[0] = 1;
2035         }
2036         return 0;
2037       }
2038   
2039   
2040   pas = nbtics - 2; /* pas == grads number - 2 */
2041   
2042   possible_pas = -99;
2043   possible_compteur = -99;
2044   
2045   while(pas > 0)
2046     {
2047       int tmp = 0;
2048       compteur = 0;
2049       for(;;)
2050         {
2051           tmp = tmp + pas;
2052           compteur++;
2053           
2054           if((tmp == (nbtics - 1)) && (compteur < nb_grads_max)){
2055             possible_pas = pas;
2056             possible_compteur = ++compteur;
2057             break;
2058           }
2059           
2060           if(tmp > (nbtics - 1))
2061             break;
2062         }
2063       
2064       pas--;
2065     }
2066   
2067   
2068   if(possible_compteur != -99){
2069     compteur = possible_compteur;
2070     pas = possible_pas;
2071     
2072     for(i=0;i<compteur;i++)
2073       ppsubwin->axes.xgrads[i] = grads_tmp[i*pas];
2074     
2075     ppsubwin->axes.nxgrads = compteur;
2076     
2077     /* Nb of subtics computation and storage */
2078     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2079     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,
2080                                                            ppsubwin->axes.nxgrads,
2081                                                            ppsubwin->logflags[0],
2082                                                            ppsubwin->axes.xgrads,
2083                                                            ppsubwin->axes.nbsubtics[0]); 
2084   }
2085   else{
2086     ppsubwin->axes.xgrads[0] = grads_tmp[0];
2087     ppsubwin->axes.xgrads[1] = grads_tmp[lastxindex];
2088     ppsubwin->axes.nxgrads = 2;
2089     /* Nb of subtics computation and storage */
2090     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2091     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,
2092                                                            ppsubwin->axes.nxgrads,
2093                                                            ppsubwin->logflags[0],
2094                                                            ppsubwin->axes.xgrads,
2095                                                            ppsubwin->axes.nbsubtics[0]); 
2096     
2097     if(ppsubwin->logflags[0] == 'n'){
2098       if(nb_grads_max > 4) {
2099         /* we could display at least 4 graduations but we did not find a proper interval... */
2100         /* To avoid to display only the min and max (see above), we add 2 newly created grads by interpolating between min and max */
2101         double pas_ = (grads_tmp[lastxindex]-grads_tmp[0])/3;
2102         for(i=0;i<3;i++){
2103           ppsubwin->axes.xgrads[i] = grads_tmp[0] + i*pas_;
2104         }
2105         
2106         ppsubwin->axes.xgrads[3] = grads_tmp[lastxindex]; /* exact max */
2107         ppsubwin->axes.nxgrads = 4;
2108         
2109         /* Nb of subtics computation and storage */
2110         /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2111         ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,
2112                                                                ppsubwin->axes.nxgrads,
2113                                                                'n',
2114                                                                ppsubwin->axes.xgrads,
2115                                                                ppsubwin->axes.nbsubtics[0]); 
2116       }
2117     }
2118   }
2119   
2120   return 0;
2121 }
2122
2123
2124
2125 int AdaptGraduationsOnYBottomRight(int iof, int x, int y, int size, integer *Ticsdir, int *fontid, sciPointObj * psubwin, double yminval, double ymaxval, double fx, double fy, double fz)
2126 {
2127   int i;
2128   int nbtics, nbsubtics;
2129   int lastyindex;
2130   int old_rect[4];
2131   int nb_grads_max = 0;
2132   int vx[2], vy[2];
2133   int xm, ym;
2134   double grads_tmp[20];
2135   char c_format[5];
2136   integer barlengthx = 0,barlengthy = 0;
2137   integer rect[4],posi[2]; 
2138   integer textcolor = -1;
2139   int logrect[4] ;
2140   int XX = 0 ;
2141   int YY = 0 ;
2142   int pas;
2143   double fact_h = 1.5, fact_w = 1.5;
2144   int compteur = 0;
2145
2146   int possible_pas, possible_compteur;
2147   
2148   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
2149   
2150   for(i=0;i<4;i++) old_rect[i] = 0; /* Init. old_rect to force first grad. to be displayed */
2151   
2152   lastyindex = ppsubwin->axes.nygrads - 1;
2153   
2154   if(lastyindex == 0)
2155     ChooseFormatForOneGrad(c_format,&(ppsubwin->axes.ygrads[0]));
2156   else
2157     ChoixFormatE(c_format,
2158                  ppsubwin->axes.ygrads[0],
2159                  ppsubwin->axes.ygrads[lastyindex],
2160                  ((ppsubwin->axes.ygrads[lastyindex])-(ppsubwin->axes.ygrads[0]))/(lastyindex));
2161   
2162   nbtics = ppsubwin->axes.nygrads;
2163   nbsubtics = ppsubwin->axes.nbsubtics[1];
2164   
2165   
2166   for(i=0;i<nbtics;i++) grads_tmp[i] = ppsubwin->axes.ygrads[i];
2167
2168   for(i=0;i<nbtics;i++)
2169     {
2170       char foo[256]; 
2171       double ytmp = ppsubwin->axes.ygrads[i];
2172                   
2173       sprintf(foo,c_format,ytmp);
2174
2175       /***************************************************************/
2176       /************************* COMMON PART *************************/
2177       /***************************************************************/
2178       if(ppsubwin->axes.reverse[1] == TRUE)
2179         ytmp = InvAxis(ppsubwin->FRect[1],ppsubwin->FRect[3],ytmp);
2180                   
2181       ComputeGoodTrans3d(psubwin,1,&xm,&ym,&fx,&ytmp,&fz);
2182                   
2183       vx[0]=xm;vy[0]=ym; 
2184                   
2185       barlengthx= (integer) (( Ticsdir[0])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
2186       barlengthy= (integer) (( Ticsdir[1])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
2187
2188       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L); /* fix bug noticed by R.N. */
2189       C2F(dr)("xstringl",foo,&x,&y,rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2190       
2191
2192       if (IsDownAxes(psubwin)){
2193         vx[1]=vx[0];
2194         vy[1]=vy[0]+iof/2;
2195         posi[0] = inint(xm-rect[2]/2); 
2196         posi[1]=inint( vy[0] + iof + rect[3]);}
2197       else{
2198         vx[1]=vx[0]+barlengthx;
2199         vy[1]=vy[0]+barlengthy;
2200         posi[0] = inint( xm+2*barlengthx);
2201         posi[1]=inint( ym + 2*barlengthy + rect[3]);}
2202                       
2203       
2204       /* compute bounding of "10"  string used for log scale ON and auto_ticks ON */
2205       C2F(dr)("xstringl","10",&XX,&YY,logrect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);       
2206       
2207       
2208       if(CheckDisplay(fact_h, fact_w, ppsubwin->logflags[1],foo,posi,fontid,old_rect) == 0)
2209         continue; /*  graduation too close, DO NOT display the graduation ! */
2210       
2211       
2212       C2F(dr)("xset","pattern",&textcolor,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2213       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2214       if ( ppsubwin->logflags[1] == 'l' )
2215         {
2216           int smallersize = fontid[1]-2;
2217           int old_rect10[4];
2218           int posi10[2];
2219
2220           posi10[0] = posi[0] - logrect[2];
2221           posi10[1] = posi[1] + logrect[3];
2222           
2223           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2224           
2225           C2F(dr)("xstringl","10",(&posi10[0]),(&posi10[1]),old_rect10,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2226           
2227           posi[0] = old_rect10[0] + old_rect10[2];
2228           posi[1] = (int) (old_rect10[1] - old_rect10[3]*.1);
2229           
2230           C2F(dr)("xset","font",fontid,&smallersize,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2231           C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2232           
2233           /* update old_rect */
2234           old_rect[2] = (int)(fact_w*(old_rect[2] + old_rect10[2]));
2235           old_rect[3] = (int)(fact_h*(old_rect[3] + old_rect10[3] + (int) (old_rect10[3]*.1)));
2236           old_rect[0] = old_rect10[0];
2237           old_rect[1] = old_rect[1];
2238           
2239           nb_grads_max++;
2240           
2241           /* put back the current fontid */
2242           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2243         }
2244       else{
2245         /* update old_rect */
2246         C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2247         old_rect[3] = (int)(fact_h* old_rect[3]);
2248         old_rect[2] = (int)(fact_w* old_rect[2]);
2249         nb_grads_max++;
2250       }
2251     }
2252   
2253   if(ppsubwin->logflags[1] != 'l')
2254     if(nb_grads_max == 1) /* only one grad. can be displayed : we choose to display the average value (max+min)/2 */
2255       {
2256         ppsubwin->axes.ygrads[0] = (grads_tmp[0]+grads_tmp[lastyindex])/2.;
2257         ppsubwin->axes.nygrads = 1;
2258         if ( !ppsubwin->flagNax )
2259         {
2260           ppsubwin->axes.nbsubtics[1] = 1;
2261         }
2262         return 0;
2263       }
2264   
2265   
2266   pas = nbtics - 2; /* pas == grads number - 2 */
2267   
2268   possible_pas = -99;
2269   possible_compteur = -99;
2270   
2271   while(pas > 0)
2272     {
2273       int tmp = 0;
2274       compteur = 0;
2275       for(;;)
2276         {
2277           tmp = tmp + pas;
2278           compteur++;
2279           
2280           if((tmp == (nbtics - 1)) && (compteur < nb_grads_max)){
2281             possible_pas = pas;
2282             possible_compteur = ++compteur;
2283             break;
2284           }
2285           
2286           if(tmp > (nbtics - 1))
2287             break;
2288         }
2289       
2290       pas--;
2291     }
2292   
2293   
2294   if(possible_compteur != -99){
2295     compteur = possible_compteur;
2296     pas = possible_pas;
2297     
2298     for(i=0;i<compteur;i++)
2299       ppsubwin->axes.ygrads[i] = grads_tmp[i*pas];
2300     
2301     ppsubwin->axes.nygrads = compteur;
2302     
2303     /* Nb of subtics computation and storage */
2304     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2305     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTicsFor3dUse(psubwin,
2306                                                            ppsubwin->axes.nygrads,
2307                                                            ppsubwin->logflags[1],
2308                                                            ppsubwin->axes.ygrads,
2309                                                            ppsubwin->axes.nbsubtics[1]);
2310   }
2311   else{
2312     ppsubwin->axes.ygrads[0] = grads_tmp[0];
2313     ppsubwin->axes.ygrads[1] = grads_tmp[lastyindex];
2314     ppsubwin->axes.nygrads = 2;
2315
2316     /* Nb of subtics computation and storage */
2317     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2318     ppsubwin->axes.nbsubtics[1] = ComputeNbSubTicsFor3dUse(psubwin,
2319                                                            ppsubwin->axes.nygrads,
2320                                                            ppsubwin->logflags[1],
2321                                                            ppsubwin->axes.ygrads,
2322                                                            ppsubwin->axes.nbsubtics[1]);
2323     
2324     if(ppsubwin->logflags[1] == 'n'){
2325       if(nb_grads_max > 4) {
2326         /* we could display at least 4 graduations but we did not find a proper interval... */
2327         /* To avoid to display only the min and max (see above), we add 2 newly created grads by interpolating between min and max */
2328         double pas_ = (grads_tmp[lastyindex]-grads_tmp[0])/3;
2329         for(i=0;i<3;i++){
2330           ppsubwin->axes.ygrads[i] = grads_tmp[0] + i*pas_;
2331         }
2332         
2333         ppsubwin->axes.ygrads[3] = grads_tmp[lastyindex]; /* exact max */
2334         ppsubwin->axes.nygrads = 4;
2335         /* Nb of subtics computation and storage */
2336         /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2337         ppsubwin->axes.nbsubtics[1] = ComputeNbSubTicsFor3dUse(psubwin,
2338                                                                ppsubwin->axes.nygrads,
2339                                                                'n',
2340                                                                ppsubwin->axes.ygrads,
2341                                                                ppsubwin->axes.nbsubtics[1]);
2342       }
2343     }
2344   }
2345   
2346   return 0;
2347 }
2348
2349
2350 int AdaptGraduationsOnXBottomRight(int iof, int x, int y, int size, integer *Ticsdir, int *fontid, sciPointObj * psubwin, double xminval, double xmaxval, double fx, double fy, double fz)
2351 {
2352   int i;
2353   int nbtics, nbsubtics;
2354   int lastxindex;
2355   int old_rect[4];
2356   int nb_grads_max = 0;
2357   int vx[2], vy[2];
2358   int xm, ym;
2359   double grads_tmp[20];
2360   char c_format[5];
2361   integer barlengthx = 0,barlengthy = 0;
2362   integer rect[4],posi[2]; 
2363   integer textcolor = -1;
2364   int logrect[4] ;
2365   int XX = 0;
2366   int YY = 0 ;
2367   int pas;
2368   double fact_h = 1.5, fact_w = 1.5;
2369   int compteur = 0;
2370
2371   int possible_pas, possible_compteur;
2372   
2373   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
2374   
2375   for(i=0;i<4;i++) old_rect[i] = 0; /* Init. old_rect to force first grad. to be displayed */
2376   
2377   lastxindex = ppsubwin->axes.nxgrads - 1;
2378   
2379   if(lastxindex == 0)
2380     ChooseFormatForOneGrad(c_format,&(ppsubwin->axes.xgrads[0]));
2381   else
2382     ChoixFormatE(c_format,
2383                  ppsubwin->axes.xgrads[0],
2384                  ppsubwin->axes.xgrads[lastxindex],
2385                  ((ppsubwin->axes.xgrads[lastxindex])-(ppsubwin->axes.xgrads[0]))/(lastxindex));
2386   
2387   nbtics = ppsubwin->axes.nxgrads;
2388   nbsubtics = ppsubwin->axes.nbsubtics[0];
2389   
2390   
2391   for(i=0;i<nbtics;i++) grads_tmp[i] = ppsubwin->axes.xgrads[i];
2392
2393   for(i=0;i<nbtics;i++)
2394     {
2395       char foo[256]; 
2396       double xtmp = ppsubwin->axes.xgrads[i];
2397                   
2398       sprintf(foo,c_format,xtmp);
2399
2400       /***************************************************************/
2401       /************************* COMMON PART *************************/
2402       /***************************************************************/
2403       if(ppsubwin->axes.reverse[0] == TRUE)
2404         xtmp = InvAxis(ppsubwin->FRect[0],ppsubwin->FRect[2],xtmp);
2405                   
2406       ComputeGoodTrans3d(psubwin,1,&xm,&ym,&xtmp,&fy,&fz);
2407                   
2408       vx[0]=xm;vy[0]=ym; 
2409                   
2410       barlengthx= (integer) (( Ticsdir[0])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
2411       barlengthy= (integer) (( Ticsdir[1])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
2412
2413       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L); /* fix bug noticed by R.N. */
2414       C2F(dr)("xstringl",foo,&x,&y,rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2415       
2416
2417       if (IsDownAxes(psubwin)){
2418         vx[1]=vx[0];
2419         vy[1]=vy[0]+iof/2;
2420         posi[0] = inint(xm-rect[2]/2); 
2421         posi[1]=inint( vy[0] + iof + rect[3]);}
2422       else{
2423         vx[1]=vx[0]+barlengthx;
2424         vy[1]=vy[0]+barlengthy;
2425         posi[0] = inint( xm+2*barlengthx);
2426         posi[1]=inint( ym + 2*barlengthy + rect[3]);}
2427                       
2428       
2429       /* compute bounding of "10"  string used for log scale ON and auto_ticks ON */
2430       C2F(dr)("xstringl","10",&XX,&YY,logrect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);       
2431       
2432       
2433       if(CheckDisplay(fact_h, fact_w, ppsubwin->logflags[0],foo,posi,fontid,old_rect) == 0)
2434         continue; /*  graduation too close, DO NOT display the graduation ! */
2435       
2436       
2437       C2F(dr)("xset","pattern",&textcolor,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2438       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2439       if ( ppsubwin->logflags[0] == 'l' )
2440         {
2441           int smallersize = fontid[1]-2;
2442           int old_rect10[4];
2443           int posi10[2];
2444
2445           posi10[0] = posi[0] - logrect[2];
2446           posi10[1] = posi[1] + logrect[3];
2447           
2448           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2449           
2450           C2F(dr)("xstringl","10",(&posi10[0]),(&posi10[1]),old_rect10,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2451           
2452           posi[0] = old_rect10[0] + old_rect10[2];
2453           posi[1] = (int) (old_rect10[1] - old_rect10[3]*.1);
2454           
2455           C2F(dr)("xset","font",fontid,&smallersize,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2456           C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2457           
2458           /* update old_rect */
2459           old_rect[2] = (int)(fact_w*(old_rect[2] + old_rect10[2]));
2460           old_rect[3] = (int)(fact_h*(old_rect[3] + old_rect10[3] + (int) (old_rect10[3]*.1)));
2461           old_rect[0] = old_rect10[0];
2462           old_rect[1] = old_rect[1];
2463           
2464           nb_grads_max++;
2465           
2466           /* put back the current fontid */
2467           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2468         }
2469       else{
2470         /* update old_rect */
2471         C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2472         old_rect[3] = (int)(fact_h* old_rect[3]);
2473         old_rect[2] = (int)(fact_w* old_rect[2]);
2474         nb_grads_max++;
2475       }
2476     }
2477   
2478   if(ppsubwin->logflags[0] != 'l')
2479     if(nb_grads_max == 1) /* only one grad. can be displayed : we choose to display the average value (max+min)/2 */
2480       {
2481         ppsubwin->axes.xgrads[0] = (grads_tmp[0]+grads_tmp[lastxindex])/2.;
2482         ppsubwin->axes.nxgrads = 1;
2483         if ( !ppsubwin->flagNax )
2484         {
2485           ppsubwin->axes.nbsubtics[0] = 1;
2486         }
2487         return 0;
2488       }
2489   
2490   
2491   pas = nbtics - 2; /* pas == grads number - 2 */
2492   
2493   possible_pas = -99;
2494   possible_compteur = -99;
2495   
2496   while(pas > 0)
2497     {
2498       int tmp = 0;
2499       compteur = 0;
2500       for(;;)
2501         {
2502           tmp = tmp + pas;
2503           compteur++;
2504           
2505           if((tmp == (nbtics - 1)) && (compteur < nb_grads_max)){
2506             possible_pas = pas;
2507             possible_compteur = ++compteur;
2508             break;
2509           }
2510           
2511           if(tmp > (nbtics - 1))
2512             break;
2513         }
2514       
2515       pas--;
2516     }
2517   
2518   
2519   if(possible_compteur != -99){
2520     compteur = possible_compteur;
2521     pas = possible_pas;
2522     
2523     for(i=0;i<compteur;i++)
2524       ppsubwin->axes.xgrads[i] = grads_tmp[i*pas];
2525     
2526     ppsubwin->axes.nxgrads = compteur;
2527     
2528     /* Nb of subtics computation and storage */
2529     /* ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,ppsubwin->axes.nxgrads,ppsubwin->logflags[0], */
2530 /*                                                         ppsubwin->axes.xgrads,Max((int) abs((13-compteur)/2),2)); */
2531     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,
2532                                                            ppsubwin->axes.nxgrads,
2533                                                            ppsubwin->logflags[0],
2534                                                            ppsubwin->axes.xgrads,
2535                                                            ppsubwin->axes.nbsubtics[0]);
2536   }
2537   else{
2538     ppsubwin->axes.xgrads[0] = grads_tmp[0];
2539     ppsubwin->axes.xgrads[1] = grads_tmp[lastxindex];
2540     ppsubwin->axes.nxgrads = 2;
2541     /* /\* Nb of subtics computation and storage *\/ */
2542 /*     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,ppsubwin->axes.nxgrads,ppsubwin->logflags[0], */
2543 /*                                                         ppsubwin->axes.xgrads,Max((int) abs((13-compteur)/2),2));  */
2544     ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,
2545                                                            ppsubwin->axes.nxgrads,
2546                                                            ppsubwin->logflags[0],
2547                                                            ppsubwin->axes.xgrads,
2548                                                            ppsubwin->axes.nbsubtics[0]);
2549     if(ppsubwin->logflags[0] == 'n'){
2550       if(nb_grads_max > 4) {
2551         /* we could display at least 4 graduations but we did not find a proper interval... */
2552         /* To avoid to display only the min and max (see above), we add 2 newly created grads by interpolating between min and max */
2553         double pas_ = (grads_tmp[lastxindex]-grads_tmp[0])/3;
2554         for(i=0;i<3;i++){
2555           ppsubwin->axes.xgrads[i] = grads_tmp[0] + i*pas_;
2556         }
2557         
2558         ppsubwin->axes.xgrads[3] = grads_tmp[lastxindex]; /* exact max */
2559         ppsubwin->axes.nxgrads = 4;
2560         /* Nb of subtics computation and storage */
2561         /* ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin, */
2562 /*                                                                ppsubwin->axes.nxgrads, */
2563 /*                                                                'n', */
2564 /*                                                             ppsubwin->axes.xgrads, */
2565 /*                                                                Max((int) abs((13-compteur)/2),2) ); */
2566         ppsubwin->axes.nbsubtics[0] = ComputeNbSubTicsFor3dUse(psubwin,
2567                                                                ppsubwin->axes.nxgrads,
2568                                                                'n',
2569                                                                ppsubwin->axes.xgrads,
2570                                                                ppsubwin->axes.nbsubtics[0] );
2571       }
2572     }
2573   }
2574   
2575   return 0;
2576 }
2577
2578 int AdaptGraduationsOnZ(int x, int y, int size, integer *Ticsdir, int *fontid, sciPointObj * psubwin, double zminval, double zmaxval, double fx, double fy, double fz)
2579 {
2580   int i;
2581   int nbtics, nbsubtics;
2582   int lastzindex;
2583   int old_rect[4];
2584   int nb_grads_max = 0;
2585   int vx[2], vy[2];
2586   int xm, ym;
2587   double grads_tmp[20];
2588   char c_format[5];
2589   integer barlengthx = 0,barlengthy = 0;
2590   integer rect[4],posi[2]; 
2591   integer textcolor = -1;
2592   int logrect[4] ;
2593   int XX = 0 ;
2594   int YY = 0 ;
2595   int pas;
2596   double fact_h = 1.5, fact_w = 1.;
2597   int compteur;
2598
2599   int possible_pas, possible_compteur;
2600   
2601   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
2602   
2603   for(i=0;i<4;i++) old_rect[i] = 0; /* Init. old_rect to force first grad. to be displayed */
2604   
2605
2606
2607   lastzindex = ppsubwin->axes.nzgrads - 1;
2608   
2609   if(lastzindex == 0)
2610     ChooseFormatForOneGrad(c_format,&(ppsubwin->axes.zgrads[0]));
2611   else
2612     ChoixFormatE(c_format,
2613                  ppsubwin->axes.zgrads[0],
2614                  ppsubwin->axes.zgrads[lastzindex],
2615                  ((ppsubwin->axes.zgrads[lastzindex])-(ppsubwin->axes.zgrads[0]))/(lastzindex));
2616   
2617   nbtics = ppsubwin->axes.nzgrads;
2618   nbsubtics = ppsubwin->axes.nbsubtics[2];
2619
2620
2621   for(i=0;i<nbtics;i++) grads_tmp[i] = ppsubwin->axes.zgrads[i];
2622   
2623   for(i=0;i<nbtics;i++)
2624     {
2625       char foo[256];
2626       double ztmp = ppsubwin->axes.zgrads[i];
2627
2628       sprintf(foo,c_format,ztmp);
2629       
2630       /***************************************************************/
2631       /************************* COMMON PART *************************/
2632       /***************************************************************/
2633       if(ppsubwin->axes.reverse[2] == TRUE)
2634         ztmp = InvAxis(ppsubwin->FRect[4],ppsubwin->FRect[5],ztmp);
2635       
2636       ComputeGoodTrans3d(psubwin,1,&xm,&ym,&fx,&fy,&ztmp);
2637             
2638       
2639       vx[0]=xm;vy[0]=ym;
2640       
2641       barlengthx= (integer) (( Ticsdir[0])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
2642       barlengthy= (integer) (( Ticsdir[1])/sqrt((double) Ticsdir[0]*Ticsdir[0]+Ticsdir[1]*Ticsdir[1])*size);
2643       vx[1]=vx[0]+barlengthx;
2644       vy[1]=vy[0]+barlengthy;
2645       
2646       /* foo is set above with sprintf(foo,c_format,xtmp); */
2647               
2648       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L); /* fix bug noticed by R.N. */
2649       C2F(dr)("xstringl",foo,&x,&y,rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2650       posi[0] = inint( xm+2*barlengthx - rect[2]); 
2651       posi[1]=inint( ym + 2*barlengthy + rect[3]/2);
2652
2653
2654       /* compute bounding of "10"  string used for log scale ON and auto_ticks ON */
2655       C2F(dr)("xstringl","10",&XX,&YY,logrect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);       
2656       
2657       
2658       if(CheckDisplay(fact_h, fact_w, ppsubwin->logflags[2],foo,posi,fontid,old_rect) == 0)
2659         continue; /*  graduation too close, DO NOT display the graduation ! */
2660               
2661       C2F(dr)("xset","pattern",&textcolor,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2662       C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2663       if ( ppsubwin->logflags[2] == 'l' )
2664         {
2665           int smallersize = fontid[1]-2;
2666           int old_rect10[4];
2667           int posi10[2];
2668           
2669           posi10[0] = posi[0] - logrect[2];
2670           posi10[1] = posi[1] + logrect[3];
2671           
2672           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2673           
2674           C2F(dr)("xstringl","10",(&posi10[0]),(&posi10[1]),old_rect10,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2675           
2676           posi[0] = old_rect10[0] + old_rect10[2];
2677           posi[1] = (int) (old_rect10[1] - old_rect10[3]*.1);
2678           
2679           C2F(dr)("xset","font",fontid,&smallersize,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2680           C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2681           
2682           /* update old_rect */
2683           old_rect[2] = (int)(fact_w*(old_rect[2] + old_rect10[2]));
2684           old_rect[3] = (int)(fact_h*(old_rect[3] + old_rect10[3] + (int) (old_rect10[3]*.1)));
2685           old_rect[0] = old_rect10[0];
2686           old_rect[1] = old_rect[1];
2687           
2688           nb_grads_max++;
2689           
2690           
2691           /* put back the current fontid */
2692           C2F(dr)("xset","font",fontid,fontid+1,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2693         }
2694       else{
2695         /* update old_rect */
2696         C2F(dr)("xstringl",foo,(&posi[0]),(&posi[1]),old_rect,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
2697         old_rect[3] = (int)(fact_h* old_rect[3]);
2698         old_rect[2] = (int)(fact_w* old_rect[2]);
2699         nb_grads_max++;
2700       }
2701     }
2702   
2703   
2704   if(ppsubwin->logflags[2] != 'l')
2705     if(nb_grads_max == 1) /* only one grad. can be displayed : we choose to display the average value (max+min)/2 */
2706       {
2707         ppsubwin->axes.zgrads[0] = (grads_tmp[0]+grads_tmp[lastzindex])/2.;
2708         ppsubwin->axes.nzgrads = 1;
2709         if ( !ppsubwin->flagNax )
2710         {
2711           ppsubwin->axes.nbsubtics[2] = 1;
2712         }
2713         return 0;
2714       }
2715   
2716   pas = nbtics - 2; /* pas == grads number - 2 */
2717
2718   possible_pas = -99;
2719   possible_compteur = -99;
2720
2721   while(pas > 0)
2722     {
2723       int tmp = 0;
2724       compteur = 0;
2725       for(;;)
2726         {
2727           tmp = tmp + pas;
2728           compteur++;
2729           
2730           if((tmp == (nbtics - 1)) && (compteur < nb_grads_max)){
2731             possible_pas = pas;
2732             possible_compteur = ++compteur;
2733             break;
2734           }
2735           
2736           if(tmp > (nbtics - 1))
2737             break;
2738         }
2739       
2740       pas--;
2741     }
2742   
2743   if(possible_compteur != -99){
2744     compteur = possible_compteur;
2745     pas = possible_pas;
2746     
2747     for(i=0;i<compteur;i++)
2748       ppsubwin->axes.zgrads[i] = grads_tmp[i*pas];
2749     
2750     ppsubwin->axes.nzgrads = compteur;
2751     
2752     /* Nb of subtics computation and storage */
2753     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2754     ppsubwin->axes.nbsubtics[2] = ComputeNbSubTicsFor3dUse(psubwin,
2755                                                            ppsubwin->axes.nzgrads,
2756                                                            ppsubwin->logflags[2],
2757                                                            ppsubwin->axes.zgrads,
2758                                                            ppsubwin->axes.nbsubtics[2]); 
2759   }
2760   else{
2761     ppsubwin->axes.zgrads[0] = grads_tmp[0];
2762     ppsubwin->axes.zgrads[1] = grads_tmp[lastzindex];
2763     ppsubwin->axes.nzgrads = 2;
2764     /* Nb of subtics computation and storage */
2765     /* jb Silvy 01/2006 : default value was Max((int) abs((13-compteur)/2),2) */
2766     ppsubwin->axes.nbsubtics[2] = ComputeNbSubTicsFor3dUse(psubwin,
2767                                                            ppsubwin->axes.nzgrads,
2768                                                            ppsubwin->logflags[2],
2769                                                            ppsubwin->axes.zgrads,
2770                                                            ppsubwin->axes.nbsubtics[2]); 
2771   }
2772   
2773   return 0;
2774 }
2775
2776
2777
2778 int ComputeNbSubTicsFor3dUse(sciPointObj * pobj, int nbtics, char logflag, double * grads, int nbsubtics_input)
2779 {
2780   int ticsval[] =    {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
2781   int subticsval[] = {6,4,4,3,3,3,2,2,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1};
2782   int i;
2783   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (pobj);
2784
2785
2786   if(logflag =='l'){
2787     if( (grads[1]-grads[0]) == 1 ) /* intervalle de type ...10^n 10^(n+1)...*/
2788       {
2789         return 9; /* 9 subtics to have a pretty tics/grid in log.*/
2790       }
2791     else
2792       {
2793         return 1; /* no subtics at all (1 but draw on a tics place) */
2794       }
2795   }
2796   else
2797   {
2798     if(ppsubwin->flagNax == FALSE) /* if auto subtics mode == ON */
2799     { 
2800       for(i=0;i<19;i++)
2801       {
2802         if(nbtics == ticsval[i])
2803         {
2804           return subticsval[i];
2805         }
2806       }
2807     }
2808     else /* if auto subtics mode == OFF already computed in Plo2dn.c, Champ.c routines... */
2809     {  /* or given via a.subtics=[nbsubtics_on_x, nbsubtics_on_y, nbsubtics_on_z] command */
2810       return nbsubtics_input;
2811     }
2812   }
2813   
2814   return -1;
2815 }
2816
2817
2818 int ChooseFormatForOneGrad(char *c_format, double *grad)
2819 {
2820   int compteur = 0;
2821   double epsilon = 1e-16;
2822   
2823   if((double)(abs((int)*grad)) < epsilon){ /* case where grad is strictly equal to 0. */
2824     *grad = 0.;
2825     strcpy(c_format,"%d");
2826     return 0;
2827   }
2828   
2829   while((int) (*grad) == 0){
2830     compteur++;
2831     *grad = 10*(*grad);
2832     
2833     if(compteur > 100){
2834       Scierror(999,"Error in function ChooseFormatForOneGrad\n");
2835       return -1;
2836     }
2837   }
2838   
2839   sprintf(c_format,"%%.%df",compteur);
2840   
2841   return 0;
2842 }
2843
2844
2845
2846 /*-------------------------------------------------------------------------------------*/
2847 /* compute the 8 vertices (xbox[i],ybox[i],zbox[i]) of an axis aligned box knowing */
2848 /* xmin, xmax, ymin, ymax, zmin and zmax in limits */
2849 void sciGetAxisBox( double limits[6], double xbox[8], double ybox[8], double zbox[8] )
2850 {
2851   xbox[0]=TRX(limits[0],limits[2],limits[4]); /* transfo. 3D of [xmin,ymin,zmin] */
2852   ybox[0]=TRY(limits[0],limits[2],limits[4]); /* into [xbox[0],ybox[0],zbox[0] ] */
2853   zbox[0]=TRZ(limits[0],limits[2],limits[4]); /*                                 */ 
2854   
2855   xbox[1]=TRX(limits[0],limits[3],limits[4]); /* transfo. 3D of [xmin,ymax,zmin] */
2856   ybox[1]=TRY(limits[0],limits[3],limits[4]); /* into [xbox[1],ybox[1],zbox[1] ] */
2857   zbox[1]=TRZ(limits[0],limits[3],limits[4]); /*                                 */
2858   
2859   xbox[2]=TRX(limits[1],limits[3],limits[4]); /* transfo. 3D of [xmax,ymax,zmin] */
2860   ybox[2]=TRY(limits[1],limits[3],limits[4]); /* into [xbox[2],ybox[2],zbox[2] ] */
2861   zbox[2]=TRZ(limits[1],limits[3],limits[4]); /*                                 */
2862   
2863   xbox[3]=TRX(limits[1],limits[2],limits[4]); /* transfo. 3D of [xmax,ymin,zmin] */
2864   ybox[3]=TRY(limits[1],limits[2],limits[4]); /* into [xbox[3],ybox[3],zbox[3] ] */
2865   zbox[3]=TRZ(limits[1],limits[2],limits[4]); /*                                 */
2866   
2867   xbox[4]=TRX(limits[0],limits[2],limits[5]); /* transfo. 3D of [xmin,ymin,zmax] */
2868   ybox[4]=TRY(limits[0],limits[2],limits[5]); /* into [xbox[4],ybox[4],zbox[4] ] */
2869   zbox[4]=TRZ(limits[0],limits[2],limits[5]); /*                                 */
2870   
2871   xbox[5]=TRX(limits[0],limits[3],limits[5]); /* transfo. 3D of [xmin,ymax,zmax] */
2872   ybox[5]=TRY(limits[0],limits[3],limits[5]); /* into [xbox[5],ybox[5],zbox[5] ] */
2873   zbox[5]=TRZ(limits[0],limits[3],limits[5]); /*                                 */
2874   
2875   xbox[6]=TRX(limits[1],limits[3],limits[5]); /* transfo. 3D of [xmax,ymax,zmax] */
2876   ybox[6]=TRY(limits[1],limits[3],limits[5]); /* into [xbox[6],ybox[6],zbox[6] ] */
2877   zbox[6]=TRZ(limits[1],limits[3],limits[5]); /*                                 */
2878   
2879   xbox[7]=TRX(limits[1],limits[2],limits[5]); /* transfo. 3D of [xmax,ymin,zmax] */
2880   ybox[7]=TRY(limits[1],limits[2],limits[5]); /* into [xbox[7],ybox[7],zbox[7] ] */
2881   zbox[7]=TRZ(limits[1],limits[2],limits[5]); /*                                 */
2882 }
2883 /*-------------------------------------------------------------------------------------*/
2884 /* update the Csacle value from new viewing angles */
2885 void sciUpdateScaleAngles( double theta, double alpha )
2886 {
2887   double cost = 0.5 ;
2888   double sint = 0.5 ;
2889   double cosa = 0.5 ;
2890   double sina = 0.5 ;
2891
2892   cost = cos( DEG2RAD(theta) ) ;
2893   cosa = cos( DEG2RAD(alpha) ) ;
2894   sint = sin( DEG2RAD(theta) ) ;
2895   sina = sin( DEG2RAD(alpha) ) ;
2896   
2897   Cscale.m[0][0]= -sint        ;
2898   Cscale.m[0][1]=  cost        ;
2899   Cscale.m[0][2]=  0           ;
2900   Cscale.m[1][0]= -cost * cosa ;
2901   Cscale.m[1][1]= -sint * cosa ;
2902   Cscale.m[1][2]=  sina        ;
2903   Cscale.m[2][0]=  cost * sina ;
2904   Cscale.m[2][1]=  sint * sina ;
2905   Cscale.m[2][2]=  cosa        ;
2906
2907 }
2908
2909 /*-------------------------------------------------------------------------------------*/
2910 /* compute the drawing order of the axes box vertices int xind */
2911 void sciAxesVerticesIndices( integer insideU[4],
2912                              integer insideD[4],
2913                              double  xbox[8]   ,
2914                              double  ybox[8]   ,
2915                              integer xind[8]    )
2916 {
2917   int    i      ;
2918   int    ind    ;
2919   int    ind2   ;
2920   int    ind3   ;
2921   double xmaxi  ;
2922   int    tmpind ;
2923
2924   /* F.Leray 23.02.04 Mise a 0 du tableau xind pour corriger bug*/
2925   /* dans le cas ind < 3 ET ybox[tmpind] < ybox[tmpind]*/
2926   for( i = 0 ; i < 8 ; i++ )
2927   { 
2928     xind[i] = 0 ;
2929   }
2930
2931   /* indices */
2932   /* determine the indices for the 3d represention */
2933   xmaxi = ( (double) Maxi(xbox,8L) ) ;
2934   ind = -1 ;
2935   MaxiInd( xbox, 8L, &ind, xmaxi ) ;
2936   if ( ind > 3 )
2937   {
2938     xind[0]=ind;
2939   }
2940   tmpind = ind ;  
2941   MaxiInd(xbox,8L,&ind,xmaxi);
2942   if ( ind > 3 )
2943   {
2944     xind[0] = ind ;
2945   }
2946   if (ybox[tmpind] > ybox[ind] )
2947   {
2948     xind[0] = tmpind ;
2949   }
2950   
2951   if (ind < 0 || ind > 8) 
2952   {
2953     sciprint("xind out of bounds");
2954     xind[0]=0;
2955   }
2956   Nextind(xind[0],&ind2,&ind3);
2957   if (ybox[ind2] > ybox[ind3]) 
2958   {
2959     xind[1]=ind2;insideU[0]=ind3;
2960   }
2961   else 
2962   {
2963     xind[1]=ind3;insideU[0]=ind2;
2964   }
2965   Nextind(ind2,&ind2,&ind3); insideU[1]=xind[0];
2966   insideU[2]=ind2; 
2967   if ( insideU[0] > 3 )
2968   {
2969     insideU[3] = insideU[0] - 4 ;
2970   }
2971   else
2972   {
2973     insideU[3] = insideU[0] + 4 ;
2974   }
2975   xind[2]=ind2;
2976   /* le pointeger en bas qui correspond */        
2977   if ( ind2 > 3 )
2978   {
2979     xind[3] = ind2 - 4 ;
2980   }
2981   else
2982   {
2983     xind[3] = ind2 + 4 ;
2984   }
2985   Nextind(xind[3],&ind2,&ind3);
2986   if (ybox[ind2] < ybox[ind3]) 
2987   {
2988     xind[4]=ind2;insideD[0]=ind3;
2989   }
2990   else  
2991   {
2992     xind[4]=ind3;insideD[0]=ind2;
2993   }
2994   Nextind(ind2,&ind2,&ind3);
2995   insideD[1]=xind[3];
2996   insideD[2]=ind2;
2997   if ( insideD[0] > 3 )
2998   {
2999     insideD[3]=insideD[0] - 4 ;
3000   }
3001   else
3002   {
3003     insideD[3]=insideD[0] + 4 ;
3004   }
3005   xind[5]=ind2;
3006          
3007 }
3008 /*------------------------------------------------------------------------------------------*/
3009 /**
3010  * Update the coordinates of a label to put it in the middle of a segment (normally an axis)
3011  * but with a little orthogonal offset.
3012  * Let Ri i=0:3 be the four corners of the label boudinbg box. The algorithm will put the
3013  * center of the bounding box C on the middle of the segment I. Then we compute for each corner
3014  * the needed translation to put them at a distance given by offset. The translation is done
3015  * along an axis orthogonal to the segment. Finally we transalte the box from I with the longest
3016  * translation, so each corner is at least at the wanted distance.
3017  * @param pLabel pointer to the label to place.
3018  * @param axisStart Starting point of the segment.
3019  * @param axisEnd   The other end of the segment. The order of the two points determine the
3020  *                  side in which the label will be placed.
3021  * @param offsets   The label is not put exactly on the middle of the segment. It is moved
3022  *                  from a little offset orthogonally from the segment.
3023  */
3024 void computeLabelAutoPos( sciPointObj * pLabel, int axisStart[2], int axisEnd[2], int offsets[2] )
3025 {
3026   /* computation are done in double to avoid loss of data */
3027   double centerDir[2]  ; /* give the direction of the line on which is the center. */
3028                          /* it is orthogonal with the axis direction */
3029   double axisMiddle[2] ; /* middle of the axis = ( axisStart + axisEnd ) / 2 */
3030   int    bbox[4][2]    ; /* real bounding box of the label */
3031   double corners[4][2] ; /* the four corners of the boundign box */
3032   double centerDist    ; /* final distance between the center and the axis */
3033   int wantedBlPoint[2] ; /* the position we want for the bottom left point of the axis */
3034   double distance      ;
3035   double rectCenter[2] ;
3036
3037   if ( axisStart[0] == axisEnd[0] && axisStart[1] == axisEnd[1] )
3038   {
3039     /* the axis is invisible. Its label is not displayed also. */
3040     return ;
3041   }
3042
3043   /* normalized vector orthogonal to the axe */
3044   /* its direction (+ or -) determines on which side will be displayed the axis */
3045   centerDir[0] = axisStart[1] - axisEnd[1]   ;
3046   centerDir[1] = axisEnd[0]   - axisStart[0] ;
3047   normalize2d( centerDir ) ;
3048
3049   /* the distance between the aabb and the axis is offsets[0] if the axis is vertical, */
3050   /* offest[1] if horizontal and something in between otherwise */
3051   distance = Abs( (double)offsets[0] * centerDir[0] ) + Abs( (double)offsets[1] * centerDir[1] ) ;
3052
3053   axisMiddle[0] = ( axisStart[0] + axisEnd[0] ) / 2.0 ;
3054   axisMiddle[1] = ( axisStart[1] + axisEnd[1] ) / 2.0 ;
3055   
3056   /* get the size of the label axis aligned bouding box. */
3057   getTextBoundingBox( pLABEL_FEATURE(pLabel)->text, bbox, NULL ) ;
3058
3059   /* get the center of the rectangle */
3060   rectCenter[0] = ( bbox[0][0] + bbox[1][0] + bbox[2][0] + bbox[3][0] ) / 4.0 ;
3061   rectCenter[1] = ( bbox[0][1] + bbox[1][1] + bbox[2][1] + bbox[3][1] ) / 4.0 ;
3062
3063   /* We suppose the box is centered on I and we compute IRi, i=0:3 */
3064   corners[0][0] = bbox[0][0] - rectCenter[0] ;
3065   corners[0][1] = bbox[0][1] - rectCenter[1] ;
3066   corners[1][0] = bbox[1][0] - rectCenter[0] ;
3067   corners[1][1] = bbox[1][1] - rectCenter[1] ;
3068   corners[2][0] = bbox[2][0] - rectCenter[0] ;
3069   corners[2][1] = bbox[2][1] - rectCenter[1] ;
3070   corners[3][0] = bbox[3][0] - rectCenter[0] ;
3071   corners[3][1] = bbox[3][1] - rectCenter[1] ;
3072
3073   /* compute IRi.v, i=0:3 to get the current distance between Ri and the axis. */
3074   /* Then for each Ri we can compute the need displacment along the centerDir to push it */
3075   /* at distance dist of the axis. Finally, the needed displacement is the maximum of the 4. */
3076   centerDist = distance - DOT_PROD_2D( corners[0], centerDir ) ;
3077   centerDist = Max( centerDist, distance - DOT_PROD_2D( corners[1], centerDir ) ) ;
3078   centerDist = Max( centerDist, distance - DOT_PROD_2D( corners[2], centerDir ) ) ;
3079   centerDist = Max( centerDist, distance - DOT_PROD_2D( corners[3], centerDir ) ) ;
3080
3081   /* the wanted center is C = I + a.v */
3082   wantedBlPoint[0] = round( axisMiddle[0] + centerDist * centerDir[0] + corners[0][0] ) ;
3083   wantedBlPoint[1] = round( axisMiddle[1] + centerDist * centerDir[1] + corners[0][1] ) ;
3084
3085   sciSetPosition( pLabel,
3086                   XPixel2Double( wantedBlPoint[0] ),
3087                   YPixel2Double( wantedBlPoint[1] ) ) ;
3088
3089 }
3090 /*------------------------------------------------------------------------------------------*/
3091
3092 #undef round