Add interactive zoom_rect.
[scilab.git] / scilab / modules / graphics / src / c / axesScale.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2004-2006 - INRIA - Fabrice Leray
4  * Copyright (C) 2006 - INRIA - Jean-Baptiste Silvy
5  * 
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at    
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 /*------------------------------------------------------------------------*/
15 /* file: axesScale.c                                                      */
16 /* desc : Contains functions to compute scale changes in a specific       */
17 /*        subwindow.                                                      */
18 /*------------------------------------------------------------------------*/
19
20
21 #include "axesScale.h"
22 #include "math_graphics.h"
23 #include "MALLOC.h"
24 #include "GetProperty.h"
25 #include "SetProperty.h"
26 #include "sciprint.h"
27 #include "PloEch.h"
28 #include "GraphicZoom.h"
29 #include "Vertices.h"
30 #include "localization.h"
31 #include "SetPropertyStatus.h"
32 #include "SetJavaProperty.h"
33 #include "GraphicSynchronizerInterface.h"
34 #include "DrawingBridge.h"
35 #include "CurrentObjectsManagement.h"
36 #include "Interaction.h"
37 #include "DoublyLinkedList.h"
38
39 /*------------------------------------------------------------------------------*/
40 void zoomSubwin(sciPointObj * pSubwin, int posX, int posY, int width, int height);
41 void zoomFigure(sciPointObj * pFigure, int posX, int posY, int width, int height);
42 /*------------------------------------------------------------------------------*/
43 double InvAxis( double min, double max, double u )
44 {
45   /*return (u-min) / (max-min) * min + (u-max) / (min-max) * max ;*/
46   return min + max - u ; /* ahah little simplification */
47 }
48 /*------------------------------------------------------------------------------*/
49 int ReverseDataFor3DXonly( sciPointObj * psubwin, double xvect[], int n1 )
50 {
51   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin) ;
52   int cmp;
53
54   if( ppsubwin->axes.reverse[0] )
55   {
56     /* agir sur x */
57     if( ppsubwin->logflags[0] == 'l' )
58     {
59       for( cmp = 0 ; cmp < n1 ; cmp++ )
60       {
61         xvect[cmp] = log10( xvect[cmp] ) ;
62         xvect[cmp] = InvAxis( ppsubwin->FRect[0], ppsubwin->FRect[2], xvect[cmp] ) ;
63         xvect[cmp] = exp10( xvect[cmp] ) ;
64       }
65     }
66     else
67     {
68       for( cmp = 0 ; cmp < n1 ; cmp++ )
69       {
70         xvect[cmp] = InvAxis( ppsubwin->FRect[0], ppsubwin->FRect[2], xvect[cmp] ) ;
71       }
72     }
73   }
74
75   return 0 ;
76 }
77 /*------------------------------------------------------------------------------*/
78 int ReverseDataFor3DYonly( sciPointObj * psubwin, double yvect[], int n1 )
79 {
80   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
81   int cmp;
82
83   if( ppsubwin->axes.reverse[1] )
84   {
85     /* agir sur y */
86     if(ppsubwin->logflags[1]=='l'){
87       for(cmp=0;cmp<n1;cmp++)
88       {
89         yvect[cmp] = log10(yvect[cmp]);
90         yvect[cmp] = InvAxis(ppsubwin->FRect[1],ppsubwin->FRect[3],yvect[cmp]);
91         yvect[cmp] = exp10(yvect[cmp]);
92       }
93     }
94     else
95     {
96       for(cmp=0;cmp<n1;cmp++)
97       {
98         yvect[cmp] =  InvAxis(ppsubwin->FRect[1],ppsubwin->FRect[3],yvect[cmp]);
99       }
100     }
101   }
102
103   return 0;
104 }
105 /*------------------------------------------------------------------------------*/
106 int ReverseDataFor3DZonly( sciPointObj * psubwin, double zvect[], int n1 )
107 {
108   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
109   int cmp;
110
111   if( zvect == NULL ) { return 0 ; }
112
113   if( ppsubwin->axes.reverse[2] )
114   {
115     /* agir sur z */
116     if(ppsubwin->logflags[2]=='l')
117     {
118       for(cmp=0;cmp<n1;cmp++)
119       {
120         zvect[cmp] = log10(zvect[cmp]);
121         zvect[cmp] = InvAxis(ppsubwin->FRect[4],ppsubwin->FRect[5],zvect[cmp]);
122         zvect[cmp] = exp10(zvect[cmp]);
123       }
124     }
125     else
126     {
127       for(cmp=0;cmp<n1;cmp++)
128       {
129         zvect[cmp] =  InvAxis(ppsubwin->FRect[4],ppsubwin->FRect[5],zvect[cmp]);
130       }
131     }
132   }
133
134   return 0;
135 }
136 /*------------------------------------------------------------------------------*/
137 int ReverseDataFor3D( sciPointObj * psubwin, double xvect[], double yvect[], double zvect[], int n1 )
138 {
139
140   ReverseDataFor3DXonly(psubwin, xvect, n1);
141   ReverseDataFor3DYonly(psubwin, yvect, n1);
142   ReverseDataFor3DZonly(psubwin, zvect, n1);
143
144   return 0;
145 }
146 /*------------------------------------------------------------------------------*/
147 int trans3d( sciPointObj * pobj,
148              integer       n   ,
149              integer       xm[],
150              integer       ym[],
151              double        x[] ,
152              double        y[] ,
153              double        z[]  )
154 {
155   integer i;
156   double tmpx,tmpy,tmpz;
157   double  tmpx1,tmpy1,tmpz1;
158   /* TEST F.Leray 20.04.04: I fix HERE temporarily BOOL cube_scaling = FALSE; */
159   BOOL cube_scaling;
160   /* Test to enable reverse axis in 3D */ /* F.Leray 14.10.04 */
161   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(pobj);
162
163   double *xtmp = NULL;
164   double *ytmp = NULL;
165   double xz1 ;
166   double yz1 ;
167
168   if (sciGetEntityType(pobj) != SCI_SUBWIN) { return 1 ; }
169
170   xtmp = MALLOC(n*sizeof(double));
171   ytmp = MALLOC(n*sizeof(double));
172
173   cube_scaling = pSUBWIN_FEATURE(pobj)->cube_scaling;
174
175   if( !cube_scaling)
176   {
177     if (z == (double *) NULL)
178     {
179       for ( i=0 ; i < n ; i++)
180       {
181         /* F.Leray 19.10.04 */
182         /* Test to export logscale in 3D */
183
184         if(ppsubwin->logflags[0] == 'l')
185         {
186           tmpx = log10(x[i]);
187         }
188         else
189         {
190           tmpx = x[i];
191         }
192
193         if(ppsubwin->logflags[1] == 'l')
194         {
195           tmpy = log10(y[i]);
196         }
197         else
198         {
199           tmpy = y[i];
200         }
201
202         if(ppsubwin->logflags[2] == 'l'){
203           sciprint(_("Warning: Value on z data is negative or zero while logarithmic scale enabled\n"));
204           sciprint(_("Object not drawn\n"));
205           FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
206           return 0;
207         }
208
209         xz1 = TX3D(tmpx,tmpy,0.0);
210         yz1 = TY3D(tmpx,tmpy,0.0);
211         xm[i] = inint( xz1 ) ;
212         ym[i] = inint( yz1 ) ;
213
214         if( isZoom3dOn() )
215         {
216           Store3DPixelValues(pobj,xm[i],ym[i],tmpx,tmpy,0.); /* stockage des xm, ym pour le zoom */
217         }
218
219         if ( finite(xz1)==0||finite(yz1)==0 ){
220           FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
221           return(0);
222         }
223       }
224     }
225     else /* z != NULL */
226     {
227       for ( i=0 ; i < n ; i++) /* cas 3d le + general */
228       {
229
230         /* F.Leray 19.10.04 */
231         /* Test to export logscale in 3D */
232
233         if(ppsubwin->logflags[0] == 'l')
234           tmpx = log10(x[i]);
235         else
236           tmpx = x[i];
237
238         if(ppsubwin->logflags[1] == 'l')
239           tmpy = log10(y[i]);
240         else
241           tmpy = y[i];
242
243         if(ppsubwin->logflags[2] == 'l')
244           tmpz = log10(z[i]);
245         else
246           tmpz = z[i];
247
248         
249         xz1 = TX3D(tmpx,tmpy,tmpz);
250         yz1 = TY3D(tmpx,tmpy,tmpz);
251         xm[i] = inint( xz1 ) ;
252         ym[i] = inint( yz1 ) ;
253
254         if( isZoom3dOn() )
255           Store3DPixelValues(pobj,xm[i],ym[i],tmpx,tmpy,tmpz); /* stockage des xm, ym pour le zoom */
256
257         if ( finite(xz1)==0||finite(yz1)==0 ){
258           FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
259           return(0);
260         }
261         /*      } */
262       }
263       FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
264     }
265   }
266   else   /* cube_scaling == TRUE now */
267   {
268     if (z == (double *) NULL)
269     {
270       for ( i=0 ; i < n ; i++)
271       {
272
273         /* F.Leray 03.11.04 */
274         /* Test to export logscale in 3D */
275
276         if(ppsubwin->logflags[0] == 'l')
277           tmpx = log10(x[i]);
278         else
279           tmpx = x[i];
280
281         if(ppsubwin->logflags[1] == 'l')
282           tmpy = log10(y[i]);
283         else
284           tmpy = y[i];
285
286         if(ppsubwin->logflags[2] == 'l'){
287           sciprint(_("Warning: Value on z data is negative or zero while logarithmic scale enabled\n"));
288           sciprint(_("Object not drawn\n"));
289           FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
290           return 0;
291         }
292
293         tmpx1 = tmpx;
294         tmpy1 = tmpy;
295         tmpz1 = 0.;
296
297         tmpx=(tmpx-pSUBWIN_FEATURE (pobj)->FRect[0])/(pSUBWIN_FEATURE (pobj)->FRect[2]-pSUBWIN_FEATURE (pobj)->FRect[0]);
298         tmpy=(tmpy-pSUBWIN_FEATURE (pobj)->FRect[1])/(pSUBWIN_FEATURE (pobj)->FRect[3]-pSUBWIN_FEATURE (pobj)->FRect[1]);
299         tmpz=(0.-pSUBWIN_FEATURE (pobj)->FRect[4])/(pSUBWIN_FEATURE (pobj)->FRect[5]-pSUBWIN_FEATURE (pobj)->FRect[4]); /* Adding F.Leray 04.11.04 */
300
301         xz1 = TX3D(tmpx,tmpy,tmpz);
302         yz1 = TY3D(tmpx,tmpy,tmpz);
303         xm[i] = inint( xz1 ) ;
304         ym[i] = inint( yz1 ) ;
305
306         if( isZoom3dOn())
307           Store3DPixelValues(pobj,xm[i],ym[i],tmpx1,tmpy1,tmpz1); /* stockage des xm, ym pour le zoom */
308
309         if ( finite(xz1)==0||finite(yz1)==0 ){
310           FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
311           return(0);
312         }
313       }
314     }
315     else /* z != NULL */
316     {
317       for ( i=0 ; i < n ; i++)
318       {
319
320         /* F.Leray 03.11.04 */
321         /* Test to export logscale in 3D */
322
323         if(ppsubwin->logflags[0] == 'l')
324           tmpx = log10(x[i]);
325         else
326           tmpx = x[i];
327
328         if(ppsubwin->logflags[1] == 'l')
329           tmpy = log10(y[i]);
330         else
331           tmpy = y[i];
332
333         if(ppsubwin->logflags[2] == 'l')
334           tmpz = log10(z[i]);
335         else
336           tmpz = z[i];
337
338         tmpx1 = tmpx;
339         tmpy1 = tmpy;
340         tmpz1 = tmpz;
341
342         tmpx= (tmpx-pSUBWIN_FEATURE (pobj)->FRect[0])/(pSUBWIN_FEATURE (pobj)->FRect[2]-pSUBWIN_FEATURE (pobj)->FRect[0]);
343         tmpy= (tmpy-pSUBWIN_FEATURE (pobj)->FRect[1])/(pSUBWIN_FEATURE (pobj)->FRect[3]-pSUBWIN_FEATURE (pobj)->FRect[1]);
344         tmpz= (tmpz-pSUBWIN_FEATURE (pobj)->FRect[4])/(pSUBWIN_FEATURE (pobj)->FRect[5]-pSUBWIN_FEATURE (pobj)->FRect[4]); /* Adding F.Leray 28.04.04 */
345
346         xz1 = TX3D(tmpx,tmpy,tmpz);
347         yz1 = TY3D(tmpx,tmpy,tmpz);
348         xm[i] = inint( xz1 ) ;
349         ym[i] = inint( yz1 ) ;
350
351         if( isZoom3dOn() )
352           Store3DPixelValues(pobj,xm[i],ym[i],tmpx1,tmpy1,tmpz1); /* stockage des xm, ym pour le zoom */
353
354         if ( finite(xz1)==0||finite(yz1)==0 ){
355           FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
356           return(0);
357         }
358       }
359     }
360   }
361   FREE(xtmp); xtmp = NULL; FREE(ytmp); ytmp = NULL;
362   return(1);
363 }
364 /*------------------------------------------------------------------------------*/
365 /**
366  * Specify new zoom box for a subwin object.
367  * @param zoomRect vector [xMin, yMin, xMax, yMax]
368  */
369 int sciZoom2D(sciPointObj * pObj, const double zoomRect[4])
370 {
371   double zoomBox[6];
372
373   // add Z scale to data bounds.
374   sciGetDataBounds(pObj, zoomBox);
375   zoomBox[0] = zoomRect[0];
376   zoomBox[1] = zoomRect[1];
377   zoomBox[2] = zoomRect[2];
378   zoomBox[3] = zoomRect[3];
379
380   return sciZoom3D(pObj, zoomBox);
381
382 }
383 /*------------------------------------------------------------------------------*/
384 /**
385  * Specify a new zoom box for a subwin object
386  * @param zoomBox vector [xMin, yMin, xMax, yMax, zMin, zMax].
387  */
388 int sciZoom3D(sciPointObj * pObj, const double zoomBox[6])
389 {
390   // convert zoomBox to [xMin, xMax, yMin, yMax, zMin, zMax]
391   double zoomBox3D[6];
392   zoomBox3D[0] = zoomBox[0];
393   zoomBox3D[1] = zoomBox[2];
394   zoomBox3D[2] = zoomBox[1];
395   zoomBox3D[3] = zoomBox[3];
396   zoomBox3D[4] = zoomBox[4];
397   zoomBox3D[5] = zoomBox[5];
398
399   if (!checkDataBounds(pObj, zoomBox3D[0], zoomBox3D[1], zoomBox3D[2],
400                        zoomBox3D[3], zoomBox3D[4], zoomBox3D[5]))
401   {
402     return SET_PROPERTY_ERROR;
403   }
404
405   sciSetZoomBox(pObj, zoomBox3D);
406
407   sciSetZooming(pObj, TRUE);
408
409   return SET_PROPERTY_SUCCEED;
410 }
411 /*------------------------------------------------------------------------------*/
412 /**
413  * get the zoom box to dispplay in Scilab for a sunwin object
414  * @param[out] zoomBox [xMin, yMin, xMax, yMax, zMin, zMax];
415  */
416 void sciGetZoom3D(sciPointObj * pObj, double zoomBox[6])
417 {
418   double temp;
419
420   // here we get [xMin, xMax, yMin, yMax, zMin, zMax]
421   // we need to switch xMax and yMin
422   sciGetZoomBox(pObj, zoomBox);
423   temp = zoomBox[1];
424   zoomBox[1] = zoomBox[2];
425   zoomBox[2] = temp;
426 }
427 /*------------------------------------------------------------------------------*/
428 /**
429  * Try to zoom on a single subwindow using a selection area
430  */
431 void zoomSubwin(sciPointObj * pSubwin, int posX, int posY, int width, int height)
432 {
433   if (sciJavaZoomRect(pSubwin, posX, posY, width, height))
434   {
435     /* subwindow has been zoomed */
436     /* force zooming */
437     sciSetZooming(pSubwin, TRUE);
438
439     // window has changed
440     forceRedraw(pSubwin);
441   }
442 }
443 /*------------------------------------------------------------------------------*/
444 /**
445  * Zoom a figure using an already computed selection area
446  */
447 void zoomFigure(sciPointObj * pFigure, int posX, int posY, int width, int height)
448 {
449   /* try to zoom on all the subwindows */
450   sciSons * pSons = sciGetSons(pFigure);
451   while (pSons != NULL)
452   {
453     sciPointObj * curObj = pSons->pointobj;
454     if (sciGetEntityType(curObj) == SCI_SUBWIN)
455     {
456       zoomSubwin(curObj, posX, posY, width, height);
457     }
458     pSons = pSons->pnext;
459   }
460 }
461 /*------------------------------------------------------------------------------*/
462 /**
463  * Perform a zoom rect (rectangular selection + zoom) on the current figure
464  */
465 void sciZoomRect(void)
466 {
467   int selectionRectangleCorners[4];
468   int x;
469   int y;
470   int w;
471   int h;
472   int button;
473   sciPointObj * curFigure;
474   sciPointObj * curSubWin;
475
476   startGraphicDataWriting();
477   curFigure = sciGetCurrentFigure();
478   curSubWin = sciGetCurrentSubWin();
479   endGraphicDataWriting();
480
481   /* create a ruuber box to select a rectangular area */
482   pixelRubberBox(curFigure, TRUE, NULL, selectionRectangleCorners, &button);
483
484   /* convert found data to [x,y,w,h] */
485   x = Min(selectionRectangleCorners[0], selectionRectangleCorners[2]);
486   y = Min(selectionRectangleCorners[1], selectionRectangleCorners[3]);
487   w = Abs(selectionRectangleCorners[0] - selectionRectangleCorners[2]);
488   h = Abs(selectionRectangleCorners[1] - selectionRectangleCorners[3]); 
489
490   /* Zoom using the found pixels */
491   startFigureDataWriting(curFigure);
492   zoomFigure(curFigure, x, y, w, h);
493   endFigureDataWriting(curFigure);
494
495   /* redraw */
496   sciDrawObj(curFigure);
497 }
498 /*------------------------------------------------------------------------------*/
499 /**
500  * Check if the follawing data bounds can be used as new data bounds for the subwin object
501  * @return TRUE if values can be used, false otherwise
502  */
503 BOOL checkDataBounds(sciPointObj * pObj, double xMin, double xMax,
504                      double yMin, double yMax, double zMin, double zMax)
505 {
506   char logFlags[3];
507   sciGetLogFlags(pObj, logFlags);
508
509   /* check if there is not an inf within the values */
510   /* since this has not any meaning */
511   if (    !finite(xMin) || !finite(xMax)
512        || !finite(yMin) || !finite(yMax)
513        || !finite(zMin) || !finite(zMax) )
514   {
515     sciprint("Error : data bounds values must be finite.");
516     return FALSE ;
517   }
518
519
520   /* check if the bounds are corrects */
521   /* allows equality with bounds since it is working */
522   if ( xMin > xMax || yMin > yMax || zMin > zMax )
523   {
524     sciprint("Error : Min and Max values for one axis do not verify Min <= Max.\n");
525     return FALSE ;
526   }
527
528   /* check for logflags that values are greater than 0 */
529   if (   ( logFlags[0] == 'l' && xMin <= 0.0 )
530       || ( logFlags[1] == 'l' && yMin <= 0.0 )
531       || ( logFlags[2] == 'l' && zMin <= 0.0 ) )
532   {
533     sciprint("Error: bounds on axis must be strictly positive to use logarithmic mode.\n" ) ;
534     return FALSE ;
535   }
536
537   return TRUE;
538 }
539 /*------------------------------------------------------------------------------*/
540 /**
541  * Unzoom a single subwindow
542  */
543 void sciUnzoom(sciPointObj * subwin)
544 {
545   int currentStatus;
546   sciPointObj * parentFig = sciGetParentFigure(subwin);
547   startFigureDataWriting(parentFig);
548   currentStatus = sciSetZooming(subwin, FALSE);
549   endFigureDataWriting(parentFig);
550
551   if (currentStatus == 0)
552   {
553     /* redraw only if needed */
554     forceRedraw(subwin);
555   }
556
557 }
558 /*------------------------------------------------------------------------------*/
559 /**
560  * Un zoom all the subwindow of a figure
561  */
562 void sciUnzoomAll(void)
563 {
564   sciPointObj * pFigure = NULL;
565   sciSons * pSons = NULL;
566
567   startGraphicDataWriting();
568   pFigure = sciGetCurrentFigure();
569   endGraphicDataWriting();
570
571   /* Copy subwins into the array */ 
572   pSons = sciGetSons(pFigure);
573   while (pSons != NULL)
574   {
575     sciPointObj * curObj = pSons->pointobj;
576     if (sciGetEntityType(curObj) == SCI_SUBWIN)
577     {
578       sciUnzoom(curObj);
579     }
580     pSons = pSons->pnext;
581   }
582
583   sciDrawObj(pFigure);
584 }
585 /*------------------------------------------------------------------------------*/
586 /**
587  * Unzoom a set of subwindows given by their handles
588  */
589 void sciUnzoomArray(unsigned long * subwinHandles, int nbSubwin)
590 {
591   int i;
592   /* list of parent figure to redraw */
593   DoublyLinkedList * redrawnFigures = DoublyLinkedList_new();
594   for (i = 0; i < nbSubwin; i++)
595   {
596     sciPointObj * curSubwin = sciGetPointerFromHandle(subwinHandles[i]);
597     sciPointObj * parentFigure = sciGetParentFigure(curSubwin);
598     sciUnzoom(curSubwin);
599     if (List_find(redrawnFigures, parentFigure) == NULL)
600     {
601       /* figure not already added for redraw */
602       redrawnFigures = List_push(redrawnFigures, parentFigure);
603     }
604   }
605
606   /* redraw only needed figures */
607   while (!List_is_empty(redrawnFigures))
608   {
609     sciPointObj * curFigure = NULL;
610     redrawnFigures = List_pop(redrawnFigures, &curFigure);
611     sciDrawObj(curFigure);
612   }
613
614   List_free(redrawnFigures);
615 }
616 /*------------------------------------------------------------------------------*/