1 /* SCCS-info %W% %E% */
2
3 /*--------------------------------------------------------------------*/
4 /* */
5 /* VCG : Visualization of Compiler Graphs */
6 /* -------------------------------------- */
7 /* */
8 /* file: fisheye.c */
9 /* version: 1.00.00 */
10 /* creation: 14.4.1993 */
11 /* author: I. Lemke (...-Version 0.99.99) */
12 /* G. Sander (Version 1.00.00-...) */
13 /* Universitaet des Saarlandes, 66041 Saarbruecken */
14 /* ESPRIT Project #5399 Compare */
15 /* description: Fisheye co-ordinate transformations */
16 /* status: in work */
17 /* */
18 /*--------------------------------------------------------------------*/
19
20 #ifndef lint
21 static char *id_string="$Id: fisheye.c,v 1.3 1995/02/08 16:29:00 sander Exp $";
22 #endif
23
24 /*
25 * Copyright (C) 1993-2005 Saarland University
26 *
27 * This program and documentation is free software; you can redistribute
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation; either version 2 of the License, or
30 * (at your option) any later version.
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40 *
41 * The software is available per anonymous ftp at ftp.cs.uni-sb.de.
42 * Contact sander@cs.uni-sb.de for additional information.
43 */
44
45
46 /*
47 * $Log: fisheye.c,v $
48 * Revision 1.3 1995/02/08 16:29:00 sander
49 * Small bug with K&R C solved.
50 *
51 * Revision 1.2 1995/02/08 11:11:14 sander
52 * Distribution version 1.3.
53 *
54 * Revision 1.1 1994/12/23 18:12:45 sander
55 * Initial revision
56 *
57 */
58
59
60 /****************************************************************************
61 * This file contains the different co-ordinate transformations used
62 * to implement the different fisheye views, which are:
63 * 1) a carthesian self adaptable continuous fisheye
64 * 2) a polar self adaptable continuous fisheye
65 * 3) a carthesian fixed size continuous fisheye
66 * 4) a polar fixed size continuous fisheye
67 *
68 * Fisheye views are used to see a small region with a high scaling
69 * while inspecting the remaining region with a low scaling.
70 *
71 * Note: the continuous fisheyes preserves bendings but do not
72 * preserve crossings, i.e. the fisheye view may show more or less
73 * crossings than the normal view, due to speed requirements.
74 * The noncontinous fisheyes preserve crossings but do not preserve
75 * bendings, i.e. some originally straight edges may be shown with bendings.
76 * The carthesian fisheyes do not preserve angles, while the polar
77 * fisheyes preserves at least the angle between rays starting at the
78 * focus point.
79 ***************************************************************************/
80
81
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <math.h>
85 #include "globals.h"
86 #include "grammar.h"
87 #include "main.h"
88 #include "options.h"
89 #include "alloc.h"
90 #include "steps.h"
91 #include "fisheye.h"
92
93 #undef DEBUG
94 #undef debugmessage
95 #ifdef DEBUG
96 #define debugmessage(a,b) {FPRINTF(stderr,"Debug: %s %s\n",a,b);}
97 #else
98 #define debugmessage(a,b) /**/
99 #endif
100
101
102 /* Prototypes
103 * ----------
104 */
105
106 static int change_cscf_sfocus _PP((void));
107 static int change_cscf_gfocus _PP((long gfx, long gfy));
108 static long cscf_sx_to_gx _PP((int x));
109 static long cscf_sy_to_gy _PP((int y));
110 static int change_fcscf_gfocus _PP((long gfx, long gfy));
111 static void normalize_scaling _PP((void));
112 static void normalize_fe_parameters _PP((void));
113 static int change_pscf_sfocus _PP((void));
114 static int change_pscf_gfocus _PP((long gfx, long gfy));
115 static void pscf_g_to_s _PP((long x, long y, int *resx, int *resy));
116
117
118 /* Global Variables
119 * ----------------
120 */
121
122 /* The fisheye view flag:
123 * 0 = normal flat view, no fisheye
124 * 1 = CSNF = carthesian self adaptable noncontinuous (trapeze) fisheye
125 * 2 = CSCF = carthesian self adaptable continuous fisheye
126 * 3 = PSCF = polar self adaptable continuous fisheye
127 * 4 = FCSCF= carthesian fixed continuous fisheye
128 * 5 = FPSCF= polar fixed continuous fisheye
129 */
130
131 int fisheye_view = 0;
132
133
134 /* The coordinate hash tables. They have a fixed size.
135 * For the carthesian fisheye, they map the graph position to a screen
136 * position.
137 */
138
139 #define COORD_HASHSIZE 20000L
140
141 static short int *xcoord_hash = NULL;
142 static short int *ycoord_hash = NULL;
143
144 static long xhashmin, xhashmax;
145 static long yhashmin, yhashmax;
146
147
148 /* The minimal and maximal coordinates of the screen
149 */
150
151 static int screen_xmin;
152 static int screen_xmax;
153 static int screen_ymin;
154 static int screen_ymax;
155
156 /* The coordinates of the focus point on the screen
157 */
158
159 static int sfocus_x;
160 static int sfocus_y;
161
162 /* For the self adaptable fisheyes:
163 * The minimal and maximal coordinates of the graph
164 */
165
166 static long graph_xmin;
167 static long graph_xmax;
168 static long graph_ymin;
169 static long graph_ymax;
170
171 /* For the fisheye with fixed width:
172 * the fisheye distance from the graph focus.
173 */
174
175 long gfishdist = 500L;
176
177
178
179 /* The coordinates of the focus point in the graph
180 */
181
182 long gfocus_x;
183 long gfocus_y;
184
185 /* The scaling factors in percent. fe_scaling = 100 means normal size.
186 */
187
188 long fe_scaling;
189
190
191 /* Parameter that help a faster calculation of the coordinate
192 * transformation.
193 */
194
195 static double par_p;
196 static long par_xlp1;
197 static long par_xlp2;
198 static long par_xrp1;
199 static long par_xrp2;
200 static long par_yup1;
201 static long par_yup2;
202 static long par_ylp1;
203 static long par_ylp2;
204
205
206 /*--------------------------------------------------------------------*/
207 /* Carthesian self adaptable continuous fisheye */
208 /*--------------------------------------------------------------------*/
209
210 /* A cartesian self adaptable continuos fisheye transforms the
211 * coordinates according to the following formula:
212 *
213 * k * d where d ist the distance to the focus in the
214 * f(d) = ----------- graph, k is the magnification, A is the
215 * A * d + 1 alignment and f(d) the resulting distance
216 * to the focus on the screen.
217 * Note:
218 * k
219 * f'(d) = -------------
220 * (A * d + 1)^2
221 *
222 * Hence:
223 * f(0) = 0 i.e. the graph focus is transformed into the sceen focus
224 * f'(0) = k i.e. the magnification at the focus is k
225 *
226 * The alignment A is selected such that the whole graph is visible, i.e.
227 *
228 * k 1
229 * f(d_max) = sd_max i.e. A = ------ - -----
230 * sd_max d_max
231 *
232 * where d_max is the maximal distance to the focus in the graph
233 * and sd_max is the maximal distance to the focus on the sceen.
234 * The cartesion fisheye allows to have different sd_max, if we go from
235 * the focus to the left, right, bottom, up.
236 *
237 * To avoid rounding errors, we use
238 *
239 * k 1 par2 with par2 = k * d_max - sd_max
240 * A = ------ - ----- = ----
241 * sd_max d_max par1 and par1 = d_max * sd_max
242 *
243 *
244 * sd_max^2
245 * Note that f'(d_max) = ----------- is less than k, if k * d_max > sd_max
246 * k * d_max^2
247 *
248 * which means that in this case, the graph is shrinked at the borders of the
249 * fisheye. The focus is visible at normal size, but the borders are
250 * distort such that the whole graph is visible.
251 *
252 * The screen focus is self adaptable such that the relation of the position
253 * in the graph and the position of the screen are preserved,
254 * i.e.
255 * x - x_min
256 * sxf - s_min = ------------- * (s_max - s_min)
257 * x_max - x_min
258 *
259 * Implementation detail: we do not transfer straight lines into curves,
260 * because this would need to much time. As result, the following properties
261 * hold:
262 *
263 * 1) the fisheye preserve bendings
264 * 2) the fisheye does not preserve crossings
265 * 3) the fisheye does not preserve angles, since it is a carthesian
266 * transformation.
267 */
268
269
270
271 /* Calculation of the auxiliary parameters
272 * ---------------------------------------
273 * A new calculation of the auxiliary parameters is necessary if
274 * a) the scaling changes.
275 * b) the position of the focus in the graph changes.
276 * c) the position of the focus in the window chnages.
277 * d) the size of the window changes.
278 */
279
280 #ifdef ANSI_C
calc_cscf_parameters(void)281 static void calc_cscf_parameters(void)
282 #else
283 static void calc_cscf_parameters()
284 #endif
285 {
286 long s, t;
287 register int i;
288 short int k;
289
290 debugmessage("calc_cscf_parameters","");
291
292 par_xrp1 = (long)(screen_xmax-sfocus_x)*(graph_xmax-gfocus_x);
293 par_xrp2 = fe_scaling*(graph_xmax-gfocus_x)
294 - 100L*(long)(screen_xmax-sfocus_x);
295 par_xlp1 = (long)(sfocus_x-screen_xmin)*(gfocus_x-graph_xmin);
296 par_xlp2 = fe_scaling*(gfocus_x-graph_xmin)
297 - 100L*(long)(sfocus_x-screen_xmin);
298 par_ylp1 = (long)(screen_ymax-sfocus_y)*(graph_ymax-gfocus_y);
299 par_ylp2 = fe_scaling*(graph_ymax-gfocus_y)
300 - 100L*(long)(screen_ymax-sfocus_y);
301 par_yup1 = (long)(sfocus_y-screen_ymin)*(gfocus_y-graph_ymin);
302 par_yup2 = fe_scaling*(gfocus_y-graph_ymin)
303 - 100L*(sfocus_y-screen_ymin);
304
305 if (par_xrp1==0L) par_xrp1 = 1L;
306 if (par_xlp1==0L) par_xlp1 = 1L;
307 if (par_ylp1==0L) par_ylp1 = 1L;
308 if (par_yup1==0L) par_yup1 = 1L;
309 if (par_xrp2==0L) par_xrp2 = 1L;
310 if (par_xlp2==0L) par_xlp2 = 1L;
311 if (par_ylp2==0L) par_ylp2 = 1L;
312 if (par_yup2==0L) par_yup2 = 1L;
313
314 normalize_fe_parameters();
315
316 if (xcoord_hash) {
317 t = graph_xmax+1L;
318 if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
319 for (i=0; i<(int)t; i++) xcoord_hash[i]=(short)0;
320 if (screen_xmin < screen_xmax)
321 for (i=screen_xmin; i<=screen_xmax; i++) {
322 s = cscf_sx_to_gx(i);
323 if (s>=0 && s<COORD_HASHSIZE)
324 xcoord_hash[s] = (short)i;
325 }
326 k = xcoord_hash[0];
327 for (i=0; i<(int)t; i++) {
328 if (xcoord_hash[i]==(short)0) xcoord_hash[i] = k;
329 else k = xcoord_hash[i];
330 }
331 }
332 if (ycoord_hash) {
333 t = graph_ymax+1;
334 if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
335 for (i=0; i<(int)t; i++) ycoord_hash[i]=(short)0;
336 if (screen_ymin < screen_ymax)
337 for (i=screen_ymin; i<=screen_ymax; i++) {
338 s = cscf_sy_to_gy(i);
339 if (s>=0 && s<COORD_HASHSIZE)
340 ycoord_hash[s] = (short)i;
341 }
342 k = ycoord_hash[0];
343 for (i=0; i<t; i++) {
344 if (ycoord_hash[i]==(short)0) ycoord_hash[i] = k;
345 else k = ycoord_hash[i];
346 }
347 }
348 xhashmin = 0L;
349 xhashmax = COORD_HASHSIZE-1L;
350 yhashmin = 0L;
351 yhashmax = COORD_HASHSIZE-1L;
352 }
353
354
355
356 /* Initialization of the cscf_fisheye
357 * ----------------------------------
358 */
359
360
361 #ifdef ANSI_C
init_cscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)362 static void init_cscf(int sxmin, int sxmax, int symin, int symax,
363 long gfx, long gfy)
364 #else
365 static void init_cscf(sxmin, sxmax, symin, symax, gfx, gfy)
366 int sxmin;
367 int sxmax;
368 int symin;
369 int symax;
370 long gfx;
371 long gfy;
372 #endif
373 {
374 debugmessage("init_cscf","");
375
376 if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
377 screen_xmin = sxmin;
378 screen_xmax = sxmax;
379 screen_ymin = symin;
380 screen_ymax = symax;
381 }
382 graph_xmin = 0L;
383 graph_xmax = maximal_xpos + (long)G_xbase;
384 graph_ymin = 0L;
385 graph_ymax = maximal_ypos + (long)G_ybase;
386 gfocus_x = gfx;
387 gfocus_y = gfy;
388 sfocus_x = (int)((long)(screen_xmax-screen_xmin)
389 * (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
390 sfocus_y = (int)((long)(screen_ymax-screen_ymin)
391 * (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
392 if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
393 if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
394 if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
395 if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
396 if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
397 if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
398 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
399 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
400 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
401 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
402 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
403 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
404 V_xmin = 0L;
405 V_xmax = MAXLONG;
406 V_ymin = 0L;
407 V_ymax = MAXLONG;
408 calc_cscf_parameters();
409 }
410
411
412 /* Change scaling
413 * --------------
414 */
415
416 #ifdef ANSI_C
change_cscf_scaling(void)417 static void change_cscf_scaling(void)
418 #else
419 static void change_cscf_scaling()
420 #endif
421 {
422 debugmessage("change_cscf_scaling","");
423
424 calc_cscf_parameters();
425 }
426
427
428 /* Change windowsize
429 * -----------------
430 * Returns 1, if a redraw is necessary.
431 */
432
433 #ifdef ANSI_C
change_cscf_winsize(int sxmin,int sxmax,int symin,int symax)434 static int change_cscf_winsize(int sxmin, int sxmax, int symin, int symax)
435 #else
436 static int change_cscf_winsize(sxmin, sxmax, symin, symax)
437 int sxmin;
438 int sxmax;
439 int symin;
440 int symax;
441 #endif
442 {
443 int oldsxmin, oldsxmax, oldsymin, oldsymax;
444 int ret;
445
446 debugmessage("change_cscf_winsize","");
447
448 ret = 0;
449 oldsxmin = screen_xmin;
450 oldsxmax = screen_xmax;
451 oldsymin = screen_ymin;
452 oldsymax = screen_ymax;
453 screen_xmin = sxmin;
454 screen_xmax = sxmax;
455 screen_ymin = symin;
456 screen_ymax = symax;
457 ret += change_cscf_sfocus();
458 if (oldsxmin != screen_xmin) return(1);
459 if (oldsxmax != screen_xmax) return(1);
460 if (oldsymin != screen_ymin) return(1);
461 if (oldsymax != screen_ymax) return(1);
462 return(ret);
463 }
464
465
466 /* Change screen focus
467 * -------------------
468 * Returns 1, if a redraw is necessary.
469 */
470
471 #ifdef ANSI_C
change_cscf_sfocus(void)472 static int change_cscf_sfocus(void)
473 #else
474 static int change_cscf_sfocus()
475 #endif
476 {
477 int oldsfx, oldsfy;
478
479 debugmessage("change_cscf_sfocus","");
480
481 oldsfx = sfocus_x;
482 oldsfy = sfocus_y;
483 sfocus_x = (int)((long)(screen_xmax-screen_xmin)
484 * (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
485 sfocus_y = (int)((long)(screen_ymax-screen_ymin)
486 * (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
487 if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
488 if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
489 if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
490 if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
491 if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
492 if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
493 calc_cscf_parameters();
494 if (oldsfx != sfocus_x) return(1);
495 if (oldsfy != sfocus_y) return(1);
496 return(0);
497 }
498
499
500 /* Change graph focus
501 * ------------------
502 * Returns 1, if a redraw is necessary.
503 */
504
505 #ifdef ANSI_C
change_cscf_gfocus(long gfx,long gfy)506 static int change_cscf_gfocus(long gfx, long gfy)
507 #else
508 static int change_cscf_gfocus(gfx, gfy)
509 long gfx;
510 long gfy;
511 #endif
512 {
513 int ret;
514 long oldgfx, oldgfy;
515
516 debugmessage("change_cscf_gfocus","");
517
518 ret = 0;
519 oldgfx = gfocus_x;
520 oldgfy = gfocus_y;
521 gfocus_x = gfx;
522 gfocus_y = gfy;
523 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
524 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
525 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
526 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
527 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
528 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
529 ret += change_cscf_sfocus();
530 if (oldgfx != gfocus_x) return(1);
531 if (oldgfy != gfocus_y) return(1);
532 return(ret);
533 }
534
535
536 /* Increment graph focus
537 * ---------------------
538 * Returns 1, if a redraw is necessary.
539 */
540
541 #ifdef ANSI_C
incr_cscf_gfocus(long dfx,long dfy)542 static int incr_cscf_gfocus(long dfx, long dfy)
543 #else
544 static int incr_cscf_gfocus(dfx, dfy)
545 long dfx;
546 long dfy;
547 #endif
548 {
549 debugmessage("incr_cscf_sfocus","");
550
551 if ((dfx==0L) && (dfy==0L)) return(0);
552 gfocus_x += dfx;
553 gfocus_y += dfy;
554 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
555 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
556 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
557 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
558 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
559 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
560 (void)change_cscf_sfocus();
561 return(1);
562 }
563
564
565 /* Translate a x,y-coord. of the graph into a x,y-coord. of the screen
566 * -------------------------------------------------------------------
567 */
568
569 #ifdef ANSI_C
cscf_g_to_s(long x,long y,int * resx,int * resy)570 static void cscf_g_to_s(long x, long y, int *resx, int *resy)
571 #else
572 static void cscf_g_to_s(x, y, resx, resy)
573 long x, y;
574 int *resx, *resy;
575 #endif
576 {
577 long dist, help;
578
579 if ((xcoord_hash) && (x>=xhashmin) && (x<=xhashmax)) {
580 /* NOTHING: this is handled in the entry point */;
581 }
582 else if (x > gfocus_x) {
583 dist = x - gfocus_x;
584 help = (par_xrp2 * dist * 10L) / par_xrp1 + 1000L;
585 if (help<=0L) help = MAXLONG;
586 *resx = sfocus_x +
587 (int)((fe_scaling * dist * 10L) / help);
588 }
589 else {
590 dist = gfocus_x - x;
591 help = (par_xlp2 * dist * 10L) / par_xlp1 + 1000L;
592 if (help<=0L) help = MAXLONG;
593 *resx = sfocus_x -
594 (int)((fe_scaling * dist * 10) / help);
595 }
596
597 if ((ycoord_hash) && (y>=yhashmin) && (y<=yhashmax)) {
598 /* NOTHING: this is handled in the entry point */;
599 }
600 else if (y > gfocus_y) {
601 dist = y - gfocus_y;
602 help = (par_ylp2 * dist * 10L) / par_ylp1 + 1000L;
603 if (help<=0L) help = MAXLONG;
604 *resy = sfocus_y +
605 (int)((fe_scaling * dist * 10) / help);
606 }
607 else {
608 dist = gfocus_y - y;
609 help = (par_yup2 * dist * 10L) / par_yup1 + 1000L;
610 if (help<=0L) help = MAXLONG;
611 *resy = sfocus_y -
612 (int)((fe_scaling * dist * 10) / help);
613 }
614 }
615
616
617
618 /* Translate a x,y-coord. of the screen into a x,y-coord. of the graph
619 * -------------------------------------------------------------------
620 */
621
622 #ifdef ANSI_C
cscf_s_to_g(int x,int y,long * resx,long * resy)623 static void cscf_s_to_g(int x, int y, long *resx, long *resy)
624 #else
625 static void cscf_s_to_g(x, y, resx, resy)
626 int x, y;
627 long *resx, *resy;
628 #endif
629 {
630 long dist, help;
631
632 if (x > sfocus_x) {
633 dist = (long)(x - sfocus_x);
634 help = - par_xrp2 * dist + par_xrp1 * fe_scaling;
635 if (help!=0L)
636 *resx = gfocus_x + (100L * dist * par_xrp1) / help;
637 else *resx = COORD_HASHSIZE;
638 }
639 else {
640 dist = (long)(sfocus_x - x);
641 help = - par_xlp2 * dist + par_xlp1 * fe_scaling;
642 if (help!=0L)
643 *resx = gfocus_x - (100L * dist * par_xlp1) / help;
644 else *resx = COORD_HASHSIZE;
645 }
646
647 if (y > sfocus_y) {
648 dist = (long)(y - sfocus_y);
649 help = - par_ylp2 * dist + par_ylp1 * fe_scaling;
650 if (help!=0L)
651 *resy = gfocus_y + (100L * dist * par_ylp1) / help;
652 else *resy = COORD_HASHSIZE;
653 }
654 else {
655 dist = (long)(sfocus_y - y);
656 help = - par_yup2 * dist + par_yup1 * fe_scaling;
657 if (help!=0L)
658 *resy = gfocus_y - (100L * dist * par_yup1) / help;
659 else *resy = COORD_HASHSIZE;
660 }
661 }
662
663
664 /* Translate a x-coordinate of the screen into a x-coordinate of the graph
665 * -----------------------------------------------------------------------
666 * This is exactly as above, however only for the x component.
667 */
668
669 #ifdef ANSI_C
cscf_sx_to_gx(int x)670 static long cscf_sx_to_gx(int x)
671 #else
672 static long cscf_sx_to_gx(x)
673 int x;
674 #endif
675 {
676 long dist, help;
677
678 if (x > sfocus_x) {
679 dist = (long)(x - sfocus_x);
680 help = - par_xrp2 * dist + par_xrp1 * fe_scaling;
681 if (help!=0L)
682 return( gfocus_x + (100L * dist * par_xrp1) / help );
683 return( COORD_HASHSIZE );
684 }
685 else {
686 dist = (long)(sfocus_x - x);
687 help = - par_xlp2 * dist + par_xlp1 * fe_scaling;
688 if (help!=0L)
689 return( gfocus_x - (100L * dist * par_xlp1) / help );
690 return( COORD_HASHSIZE );
691 }
692 }
693
694
695 /* Translate a y-coordinate of the screen into a y-coordinate of the graph
696 * -----------------------------------------------------------------------
697 * This is exactly as above, however only for the y component.
698 */
699
700 #ifdef ANSI_C
cscf_sy_to_gy(int y)701 static long cscf_sy_to_gy(int y)
702 #else
703 static long cscf_sy_to_gy(y)
704 int y;
705 #endif
706 {
707 long dist, help;
708
709 if (y > sfocus_y) {
710 dist = (long)(y - sfocus_y);
711 help = - par_ylp2 * dist + par_ylp1 * fe_scaling;
712 if (help!=0L)
713 return( gfocus_y + (100L * dist * par_ylp1) / help );
714 return( COORD_HASHSIZE );
715 }
716 else {
717 dist = (long)(sfocus_y - y);
718 help = - par_yup2 * dist + par_yup1 * fe_scaling;
719 if (help!=0L)
720 return( gfocus_y - (100L * dist * par_yup1) / help );
721 return( COORD_HASHSIZE );
722 }
723 }
724
725
726 /*--------------------------------------------------------------------*/
727 /* Carthesian fixed width continuous fisheye */
728 /*--------------------------------------------------------------------*/
729
730 /* A carthesian continuos fisheye with a fixed radius of visible range.
731 * For the formula, see the self adaptable continuous fisheye.
732 * Now, we fisheye focus is always at the middle of the screen
733 * and the maximal distance to the focus in the graph is gfishdist.
734 * In the formula, d_max is now gfishdist.
735 *
736 * with par2 = k * gfishdist - sd_max
737 * and par1 = gfishdist * sd_max
738 *
739 *
740 * Implementation detail: we do not transfer straight lines into curves,
741 * because this would need to much time. As result, the following properties
742 * hold:
743 *
744 * 1) the fisheye preserve bendings
745 * 2) the fisheye does not preserve crossings
746 * 3) the fisheye does not preserve angles, since it is a carthesian
747 * transformation.
748 */
749
750
751
752 /* Calculation of the auxiliary parameters
753 * ---------------------------------------
754 * A new calculation of the auxiliary parameters is necessary if
755 * a) the scaling changes.
756 * b) the position of the focus in the graph changes.
757 * c) the position of the focus in the window chnages.
758 * d) the size of the window changes.
759 */
760
761
762 #ifdef ANSI_C
calc_fcscf_parameters(void)763 static void calc_fcscf_parameters(void)
764 #else
765 static void calc_fcscf_parameters()
766 #endif
767 {
768 long s, t;
769 register int i;
770 short int k;
771
772 debugmessage("calc_fcscf_parameters","");
773
774 par_xrp1 = (long)(screen_xmax-sfocus_x) * gfishdist;
775 par_xrp2 = fe_scaling * gfishdist
776 - 100L*(long)(screen_xmax-sfocus_x);
777 par_xlp1 = (long)(sfocus_x-screen_xmin) * gfishdist;
778 par_xlp2 = fe_scaling * gfishdist
779 - 100L*(long)(sfocus_x-screen_xmin);
780 par_ylp1 = (long)(screen_ymax-sfocus_y) * gfishdist;
781 par_ylp2 = fe_scaling * gfishdist
782 - 100L*(long)(screen_ymax-sfocus_y);
783 par_yup1 = (long)(sfocus_y-screen_ymin) * gfishdist;
784 par_yup2 = fe_scaling * gfishdist
785 - 100L*(sfocus_y-screen_ymin);
786
787 if (par_xrp1==0L) par_xrp1 = 1L;
788 if (par_xlp1==0L) par_xlp1 = 1L;
789 if (par_ylp1==0L) par_ylp1 = 1L;
790 if (par_yup1==0L) par_yup1 = 1L;
791 if (par_xrp2<=0L) par_xrp2 = 1L;
792 if (par_xlp2<=0L) par_xlp2 = 1L;
793 if (par_ylp2<=0L) par_ylp2 = 1L;
794 if (par_yup2<=0L) par_yup2 = 1L;
795
796 normalize_fe_parameters();
797
798 if (xcoord_hash) {
799 t = graph_xmax+1L;
800 if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
801 for (i=0; i<(int)t; i++) xcoord_hash[i]=(short)0;
802 for (i=0; i<=G_xmax; i++) {
803 s = cscf_sx_to_gx(i);
804 if (s>=0 && s<COORD_HASHSIZE)
805 xcoord_hash[s] = (short)i;
806 }
807 k = xcoord_hash[0];
808 for (i=0; i<(int)t; i++) {
809 if (xcoord_hash[i]==(short)0) xcoord_hash[i] = k;
810 else k = xcoord_hash[i];
811 }
812 xhashmin = cscf_sx_to_gx(i);
813 if (xhashmin < 0) xhashmin = 0;
814 xhashmax = cscf_sx_to_gx(G_xmax);
815 if (xhashmax>COORD_HASHSIZE-1)
816 xhashmax = COORD_HASHSIZE-1;
817 }
818 if (ycoord_hash) {
819 t = graph_ymax+1;
820 if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
821 for (i=0; i<(int)t; i++) ycoord_hash[i]=(short)0;
822 i = 0;
823 s = 0L;
824 while ((s<COORD_HASHSIZE)&&(i<G_ymax)) {
825 s = cscf_sy_to_gy(i);
826 if (s>=0 && s<COORD_HASHSIZE)
827 ycoord_hash[s] = (short)i;
828 i++;
829 }
830 k = ycoord_hash[0];
831 for (i=0; i<t; i++) {
832 if (ycoord_hash[i]==(short)0) ycoord_hash[i] = k;
833 else k = ycoord_hash[i];
834 }
835 yhashmin = cscf_sy_to_gy(i);
836 if (yhashmin < 0) yhashmin = 0;
837 yhashmax = cscf_sy_to_gy(G_ymax);
838 if (yhashmax>COORD_HASHSIZE-1)
839 yhashmax = COORD_HASHSIZE-1;
840 }
841 }
842
843
844
845 /* Initialization of the fcscf_fisheye
846 * -----------------------------------
847 */
848
849
850 #ifdef ANSI_C
init_fcscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)851 static void init_fcscf(int sxmin, int sxmax, int symin, int symax,
852 long gfx, long gfy)
853 #else
854 static void init_fcscf(sxmin, sxmax, symin, symax, gfx, gfy)
855 int sxmin;
856 int sxmax;
857 int symin;
858 int symax;
859 long gfx;
860 long gfy;
861 #endif
862 {
863 debugmessage("init_fcscf","");
864
865 if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
866 screen_xmin = sxmin;
867 screen_xmax = sxmax;
868 screen_ymin = symin;
869 screen_ymax = symax;
870 }
871 graph_xmin = 0L;
872 graph_xmax = maximal_xpos + (long)G_xbase;
873 graph_ymin = 0L;
874 graph_ymax = maximal_ypos + (long)G_ybase;
875
876 gfishdist = 2L * (long)(screen_xmax-screen_xmin);
877 if (gfishdist<30L) gfishdist = 30;
878
879 sfocus_x = (screen_xmax+screen_xmin)/2;
880 sfocus_y = (screen_ymax+screen_ymin)/2;
881 gfocus_x = gfx;
882 gfocus_y = gfy;
883
884 if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
885 if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
886 if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
887 if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
888 if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
889 if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
890 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
891 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
892 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
893 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
894 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
895 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
896 V_xmin = 0L;
897 V_xmax = MAXLONG;
898 V_ymin = 0L;
899 V_ymax = MAXLONG;
900 calc_fcscf_parameters();
901 }
902
903
904 /* Change scaling
905 * --------------
906 */
907
908 #ifdef ANSI_C
change_fcscf_scaling(void)909 static void change_fcscf_scaling(void)
910 #else
911 static void change_fcscf_scaling()
912 #endif
913 {
914 debugmessage("change_fcscf_scaling","");
915
916 calc_fcscf_parameters();
917 }
918
919
920 /* Change windowsize
921 * -----------------
922 * Returns 1, if a redraw is necessary.
923 */
924
925 #ifdef ANSI_C
change_fcscf_winsize(int sxmin,int sxmax,int symin,int symax)926 static int change_fcscf_winsize(int sxmin, int sxmax, int symin, int symax)
927 #else
928 static int change_fcscf_winsize(sxmin, sxmax, symin, symax)
929 int sxmin;
930 int sxmax;
931 int symin;
932 int symax;
933 #endif
934 {
935 int oldsxmin, oldsxmax, oldsymin, oldsymax;
936
937 debugmessage("change_fcscf_winsize","");
938
939 oldsxmin = screen_xmin;
940 oldsxmax = screen_xmax;
941 oldsymin = screen_ymin;
942 oldsymax = screen_ymax;
943 screen_xmin = sxmin;
944 screen_xmax = sxmax;
945 screen_ymin = symin;
946 screen_ymax = symax;
947 sfocus_x = (screen_xmax+screen_xmin)/2;
948 sfocus_y = (screen_ymax+screen_ymin)/2;
949 calc_fcscf_parameters();
950 if (oldsxmin != screen_xmin) return(1);
951 if (oldsxmax != screen_xmax) return(1);
952 if (oldsymin != screen_ymin) return(1);
953 if (oldsymax != screen_ymax) return(1);
954 return(0);
955 }
956
957
958
959
960 /* Change graph focus
961 * ------------------
962 * Returns 1, if a redraw is necessary.
963 */
964
965 #ifdef ANSI_C
change_fcscf_gfocus(long gfx,long gfy)966 static int change_fcscf_gfocus(long gfx, long gfy)
967 #else
968 static int change_fcscf_gfocus(gfx, gfy)
969 long gfx;
970 long gfy;
971 #endif
972 {
973 long oldgfx, oldgfy;
974
975 debugmessage("change_fcscf_gfocus","");
976
977 oldgfx = gfocus_x;
978 oldgfy = gfocus_y;
979 gfocus_x = gfx;
980 gfocus_y = gfy;
981 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
982 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
983 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
984 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
985 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
986 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
987
988 /* The parameters don't change, but the hash tables may change */
989 calc_fcscf_parameters();
990
991 if (oldgfx != gfocus_x) return(1);
992 if (oldgfy != gfocus_y) return(1);
993 return(0);
994 }
995
996
997 /* Increment graph focus
998 * ---------------------
999 * Returns 1, if a redraw is necessary.
1000 */
1001
1002 #ifdef ANSI_C
incr_fcscf_gfocus(long dfx,long dfy)1003 static int incr_fcscf_gfocus(long dfx, long dfy)
1004 #else
1005 static int incr_fcscf_gfocus(dfx, dfy)
1006 long dfx;
1007 long dfy;
1008 #endif
1009 {
1010 debugmessage("incr_fcscf_sfocus","");
1011
1012 if ((dfx==0L) && (dfy==0L)) return(0);
1013 gfocus_x += dfx;
1014 gfocus_y += dfy;
1015 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1016 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1017 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1018 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1019 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1020 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1021
1022 /* The parameters don't change, but the hash tables may change */
1023 calc_fcscf_parameters();
1024
1025 return(1);
1026 }
1027
1028
1029 /* Change the fisheye width
1030 * ------------------------
1031 * Returns 1, if a redraw is necessary.
1032 */
1033
1034 #ifdef ANSI_C
set_fcscf_gfishdist(long gd)1035 static int set_fcscf_gfishdist(long gd)
1036 #else
1037 static int set_fcscf_gfishdist(gd)
1038 long gd;
1039 #endif
1040 {
1041 int ret;
1042
1043 debugmessage("set_fcscf_gfishdist","");
1044
1045 if (gd<30L) return(0);
1046
1047 ret = (gfishdist != gd);
1048 gfishdist = gd;
1049 calc_fcscf_parameters();
1050 return(ret);
1051 }
1052
1053
1054
1055 /*--------------------------------------------------------------------*/
1056 /* Polar self adaptable continuous fisheye */
1057 /*--------------------------------------------------------------------*/
1058
1059 /* A polar self adaptable continuos fisheye preserves the angles of the
1060 * vectors starting at the focus point. It transforms the distance from
1061 * the focus point according to the following formula:
1062 *
1063 * k * d where d ist the distance to the focus in the
1064 * f(d) = ----------- graph, k is the magnification, A is the
1065 * A * d + 1 alignment and f(d) the resulting distance
1066 * to the focus on the screen.
1067 * Note:
1068 * k
1069 * f'(d) = -------------
1070 * (A * d + 1)^2
1071 *
1072 * Hence:
1073 * f(0) = 0 i.e. the graph focus is transformed into the sceen focus
1074 * f'(0) = k i.e. the magnification at the focus is k
1075 *
1076 * The alignment A is selected such that the whole graph is visible, i.e.
1077 *
1078 * k 1
1079 * f(d_max) = sd_max i.e. A = ------ - -----
1080 * sd_max d_max
1081 *
1082 * where d_max is the maximal distance to the focus in the graph
1083 * and sd_max is the maximal distance to the focus on the sceen.
1084 * The polar fisheye has only one d_max and sd_max.
1085 * d_max is the minimal radius around the graph focus which encloses
1086 * the whole graph.
1087 * sdmax is the maximal radius around the screen focus such that this
1088 * circle is inside the screen.
1089 *
1090 * To avoid rounding errors, we use
1091 *
1092 * k 1 par2 with par2 = k * d_max - sd_max
1093 * A = ------ - ----- = ----
1094 * sd_max d_max par1 and par1 = d_max * sd_max
1095 *
1096 *
1097 * sd_max^2
1098 * Note that f'(d_max) = ----------- is less than k, if k * d_max > sd_max
1099 * k * d_max^2
1100 *
1101 * which means that in this case, the graph is shrinked at the borders of the
1102 * fisheye. The focus is visible at normal size, but the borders are
1103 * distort such that the whole graph is visible.
1104 *
1105 * The screen focus is self adaptable such that whole graph is visible.
1106 * We cannot give a good formula for the problem of finding the screen
1107 * focus. The reason is: if we have a screen focus, we can calculate
1108 * par1 and par2 such that the left part is completely visible, or such
1109 * that the right part is completely visible. But if the right part is
1110 * completely visible, the left part may be clipped, i.e. not completely
1111 * visible, or the left part may have to much free space.
1112 * To avoid this, we simply try out the screen focus and select the
1113 * position where the graph fits as best into the window.
1114 *
1115 * Implementation detail: we do not transfer straight lines into curves,
1116 * because this would need to much time. As result, the following properties
1117 * hold:
1118 *
1119 * 1) the fisheye preserve bendings
1120 * 2) the fisheye does not preserve crossings
1121 * 3) the fisheye does not preserve angles. However, it preserves
1122 * angles of rays starting at the focus point, since it is a polar
1123 * transformation.
1124 */
1125
1126
1127
1128 /* Calculation of the auxiliary parameters
1129 * ---------------------------------------
1130 * A new calculation of the auxiliary parameters is necessary if
1131 * a) the scaling changes.
1132 * b) the position of the focus in the graph changes.
1133 * c) the position of the focus in the window chnages.
1134 * d) the size of the window changes.
1135 */
1136
1137 #ifdef ANSI_C
calc_pscf_parameters(void)1138 static void calc_pscf_parameters(void)
1139 #else
1140 static void calc_pscf_parameters()
1141 #endif
1142 {
1143 long s, t;
1144 int x1, y1, diff, bestdiff, bestsf;
1145 double bestpar1, bestpar2;
1146
1147 debugmessage("calc_pscf_parameters","");
1148
1149 xhashmin = 0L;
1150 xhashmax = -1L;
1151 yhashmin = 0L;
1152 yhashmax = -1L;
1153
1154
1155 bestdiff = MAXINT;
1156 for (sfocus_x = screen_xmin+5; sfocus_x<screen_xmax-5; sfocus_x += 5) {
1157 diff = 0;
1158 s = (long)(screen_xmax-sfocus_x);
1159 t = graph_xmax - gfocus_x;
1160
1161 par_xrp1 = s*t;
1162 par_xrp2 = fe_scaling*t - 100L*s;
1163
1164 if (par_xrp1==0L) par_xrp1 = 1L;
1165 if (par_xrp2==0L) par_xrp2 = 1L;
1166 par_p = (double)par_xrp2 / (double)par_xrp1;
1167 pscf_g_to_s(graph_xmin, gfocus_y, &x1, &y1);
1168 if (x1<screen_xmin) diff += (screen_xmin-x1);
1169 else diff += (x1-screen_xmin);
1170 if (diff < bestdiff) {
1171 bestdiff = diff;
1172 bestpar1 = par_p;
1173 bestsf = sfocus_x;
1174 }
1175 }
1176 sfocus_x = bestsf;
1177
1178 bestdiff = MAXINT;
1179 for (sfocus_y = screen_ymin+5; sfocus_y<screen_ymax-5; sfocus_y += 5) {
1180 diff = 0;
1181 s = (long)(screen_ymax-sfocus_y);
1182 t = graph_ymax - gfocus_y;
1183
1184 par_xrp1 = s*t;
1185 par_xrp2 = fe_scaling*t - 100L*s;
1186
1187 if (par_xrp1==0L) par_xrp1 = 1L;
1188 if (par_xrp2==0L) par_xrp2 = 1L;
1189 par_p = (double)par_xrp2 / (double)par_xrp1;
1190 pscf_g_to_s(gfocus_x, graph_ymin, &x1, &y1);
1191 if (y1<screen_ymin) diff += (screen_ymin-y1);
1192 else diff += (y1-screen_ymin);
1193 if (diff < bestdiff) {
1194 bestdiff = diff;
1195 bestpar2 = par_p;
1196 bestsf = sfocus_y;
1197 }
1198 }
1199 sfocus_y = bestsf;
1200
1201 if (bestpar2>bestpar1) par_p = bestpar2;
1202 else par_p = bestpar1;
1203 }
1204
1205
1206
1207 /* Initialization of the pscf_fisheye
1208 * ----------------------------------
1209 */
1210
1211
1212 #ifdef ANSI_C
init_pscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)1213 static void init_pscf(int sxmin, int sxmax, int symin, int symax,
1214 long gfx, long gfy)
1215 #else
1216 static void init_pscf(sxmin, sxmax, symin, symax, gfx, gfy)
1217 int sxmin;
1218 int sxmax;
1219 int symin;
1220 int symax;
1221 long gfx;
1222 long gfy;
1223 #endif
1224 {
1225 debugmessage("init_pscf","");
1226
1227 if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
1228 screen_xmin = sxmin;
1229 screen_xmax = sxmax;
1230 screen_ymin = symin;
1231 screen_ymax = symax;
1232 }
1233 graph_xmin = 0L;
1234 graph_xmax = maximal_xpos + (long)G_xbase;
1235 graph_ymin = 0L;
1236 graph_ymax = maximal_ypos + (long)G_ybase;
1237 gfocus_x = gfx;
1238 gfocus_y = gfy;
1239 sfocus_x = (int)((long)(screen_xmax-screen_xmin)
1240 * (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
1241 sfocus_y = (int)((long)(screen_ymax-screen_ymin)
1242 * (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
1243 if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
1244 if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
1245 if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
1246 if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
1247 if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
1248 if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
1249 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1250 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1251 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1252 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1253 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1254 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1255 V_xmin = 0L;
1256 V_xmax = MAXLONG;
1257 V_ymin = 0L;
1258 V_ymax = MAXLONG;
1259 calc_pscf_parameters();
1260 }
1261
1262
1263 /* Change scaling
1264 * --------------
1265 */
1266
1267 #ifdef ANSI_C
change_pscf_scaling(void)1268 static void change_pscf_scaling(void)
1269 #else
1270 static void change_pscf_scaling()
1271 #endif
1272 {
1273 debugmessage("change_pscf_scaling","");
1274
1275 calc_pscf_parameters();
1276 }
1277
1278
1279 /* Change windowsize
1280 * -----------------
1281 * Returns 1, if a redraw is necessary.
1282 */
1283
1284 #ifdef ANSI_C
change_pscf_winsize(int sxmin,int sxmax,int symin,int symax)1285 static int change_pscf_winsize(int sxmin, int sxmax, int symin, int symax)
1286 #else
1287 static int change_pscf_winsize(sxmin, sxmax, symin, symax)
1288 int sxmin;
1289 int sxmax;
1290 int symin;
1291 int symax;
1292 #endif
1293 {
1294 int oldsxmin, oldsxmax, oldsymin, oldsymax;
1295 int ret;
1296
1297 debugmessage("change_pscf_winsize","");
1298
1299 ret = 0;
1300 oldsxmin = screen_xmin;
1301 oldsxmax = screen_xmax;
1302 oldsymin = screen_ymin;
1303 oldsymax = screen_ymax;
1304 screen_xmin = sxmin;
1305 screen_xmax = sxmax;
1306 screen_ymin = symin;
1307 screen_ymax = symax;
1308 ret += change_pscf_sfocus();
1309 if (oldsxmin != screen_xmin) return(1);
1310 if (oldsxmax != screen_xmax) return(1);
1311 if (oldsymin != screen_ymin) return(1);
1312 if (oldsymax != screen_ymax) return(1);
1313 return(ret);
1314 }
1315
1316
1317 /* Change screen focus
1318 * -------------------
1319 * Returns 1, if a redraw is necessary.
1320 */
1321
1322 #ifdef ANSI_C
change_pscf_sfocus(void)1323 static int change_pscf_sfocus(void)
1324 #else
1325 static int change_pscf_sfocus()
1326 #endif
1327 {
1328 int oldsfx, oldsfy;
1329
1330 debugmessage("change_pscf_sfocus","");
1331
1332 oldsfx = sfocus_x;
1333 oldsfy = sfocus_y;
1334 sfocus_x = (int)((long)(screen_xmax-screen_xmin)
1335 * (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
1336 sfocus_y = (int)((long)(screen_ymax-screen_ymin)
1337 * (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
1338 if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
1339 if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
1340 if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
1341 if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
1342 if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
1343 if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
1344 calc_pscf_parameters();
1345 if (oldsfx != sfocus_x) return(1);
1346 if (oldsfy != sfocus_y) return(1);
1347 return(0);
1348 }
1349
1350
1351 /* Change graph focus
1352 * ------------------
1353 * Returns 1, if a redraw is necessary.
1354 */
1355
1356 #ifdef ANSI_C
change_pscf_gfocus(long gfx,long gfy)1357 static int change_pscf_gfocus(long gfx, long gfy)
1358 #else
1359 static int change_pscf_gfocus(gfx, gfy)
1360 long gfx;
1361 long gfy;
1362 #endif
1363 {
1364 int ret;
1365 long oldgfx, oldgfy;
1366
1367 debugmessage("change_pscf_gfocus","");
1368
1369 ret = 0;
1370 oldgfx = gfocus_x;
1371 oldgfy = gfocus_y;
1372 gfocus_x = gfx;
1373 gfocus_y = gfy;
1374 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1375 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1376 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1377 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1378 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1379 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1380 ret += change_pscf_sfocus();
1381 if (oldgfx != gfocus_x) return(1);
1382 if (oldgfy != gfocus_y) return(1);
1383 return(ret);
1384 }
1385
1386
1387 /* Increment graph focus
1388 * ---------------------
1389 * Returns 1, if a redraw is necessary.
1390 */
1391
1392 #ifdef ANSI_C
incr_pscf_gfocus(long dfx,long dfy)1393 static int incr_pscf_gfocus(long dfx, long dfy)
1394 #else
1395 static int incr_pscf_gfocus(dfx, dfy)
1396 long dfx;
1397 long dfy;
1398 #endif
1399 {
1400 debugmessage("incr_pscf_sfocus","");
1401
1402 if ((dfx==0L) && (dfy==0L)) return(0);
1403 gfocus_x += dfx;
1404 gfocus_y += dfy;
1405 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1406 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1407 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1408 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1409 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1410 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1411 (void)change_pscf_sfocus();
1412 return(1);
1413 }
1414
1415
1416 /* Translate a x,y-coordinate of the graph into a x,y-coordinate of the screen
1417 * ---------------------------------------------------------------------------
1418 */
1419
1420 #ifdef ANSI_C
pscf_g_to_s(long x,long y,int * resx,int * resy)1421 static void pscf_g_to_s(long x, long y, int *resx, int *resy)
1422 #else
1423 static void pscf_g_to_s(x, y, resx, resy)
1424 long x, y;
1425 int *resx, *resy;
1426 #endif
1427 {
1428 float xdiff, ydiff, dist1, dist2, help;
1429
1430 xdiff = (float)(x - gfocus_x);
1431 ydiff = (float)(y - gfocus_y);
1432 dist1 = sqrt(xdiff*xdiff + ydiff*ydiff);
1433
1434 help = par_p * dist1 + 100.0;
1435 if (help<=0.0) help = 0.1;
1436 dist2 = (double)fe_scaling * dist1 / help;
1437
1438 *resx = sfocus_x + (int)(xdiff*dist2/dist1);
1439 *resy = sfocus_y + (int)(ydiff*dist2/dist1);
1440 }
1441
1442
1443
1444 /* Translate a x,y-coordinate of the screen into a x,y-coordinate of the graph
1445 * ---------------------------------------------------------------------------
1446 */
1447
1448 #ifdef ANSI_C
pscf_s_to_g(int x,int y,long * resx,long * resy)1449 static void pscf_s_to_g(int x, int y, long *resx, long *resy)
1450 #else
1451 static void pscf_s_to_g(x, y, resx, resy)
1452 int x, y;
1453 long *resx, *resy;
1454 #endif
1455 {
1456 float xdiff, ydiff, dist1, dist2, help;
1457
1458 xdiff = (float)(x - sfocus_x);
1459 ydiff = (float)(y - sfocus_y);
1460 dist2 = sqrt(xdiff*xdiff + ydiff*ydiff);
1461
1462 help = - par_p * dist2 + fe_scaling;
1463 if (help<=0.0) help = 0.1;
1464 dist1 = 100.0 * dist2 / help;
1465
1466 *resx = gfocus_x + (long)(xdiff*dist1/dist2);
1467 *resy = gfocus_y + (long)(ydiff*dist1/dist2);
1468 }
1469
1470
1471
1472 /*--------------------------------------------------------------------*/
1473 /* Polar fixed width continuous fisheye */
1474 /*--------------------------------------------------------------------*/
1475
1476 /* A polar continuos fisheye with a fixed radius of visible range.
1477 * For the formula, see the self adaptable continuous fisheye.
1478 * Now, we fisheye focus is always at the middle of the screen
1479 * and the maximal distance to the focus in the graph is gfishdist.
1480 * In the formula, d_max is now gfishdist.
1481 *
1482 * with par2 = k * gfishdist - sd_max
1483 * and par1 = gfishdist * sd_max
1484 *
1485 * Implementation detail: we do not transfer straight lines into curves,
1486 * because this would need to much time. As result, the following properties
1487 * hold:
1488 *
1489 * 1) the fisheye preserve bendings
1490 * 2) the fisheye does not preserve crossings
1491 * 3) the fisheye does not preserve angles. However, it preserves
1492 * angles of rays starting at the focus point, since it is a polar
1493 * transformation.
1494 */
1495
1496
1497
1498 /* Calculation of the auxiliary parameters
1499 * ---------------------------------------
1500 * A new calculation of the auxiliary parameters is necessary if
1501 * a) the scaling changes.
1502 * b) the position of the focus in the graph changes.
1503 * c) the position of the focus in the window chnages.
1504 * d) the size of the window changes.
1505 */
1506
1507 #ifdef ANSI_C
calc_fpscf_parameters(void)1508 static void calc_fpscf_parameters(void)
1509 #else
1510 static void calc_fpscf_parameters()
1511 #endif
1512 {
1513 long s, t;
1514
1515 debugmessage("calc_fpscf_parameters","");
1516
1517 xhashmin = 0L;
1518 xhashmax = -1L;
1519 yhashmin = 0L;
1520 yhashmax = -1L;
1521
1522 s = (long)(screen_xmax-sfocus_x);
1523 t = gfishdist;
1524
1525 par_xrp1 = s*t;
1526 par_xrp2 = fe_scaling*t - 100L*s;
1527
1528 if (par_xrp1==0L) par_xrp1 = 1L;
1529 if (par_xrp2<=0L) par_xrp2 = 1L;
1530 par_p = (double)par_xrp2 / (double)par_xrp1;
1531
1532 }
1533
1534
1535
1536 /* Initialization of the fpscf_fisheye
1537 * -----------------------------------
1538 */
1539
1540
1541 #ifdef ANSI_C
init_fpscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)1542 static void init_fpscf(int sxmin, int sxmax, int symin, int symax,
1543 long gfx, long gfy)
1544 #else
1545 static void init_fpscf(sxmin, sxmax, symin, symax, gfx, gfy)
1546 int sxmin;
1547 int sxmax;
1548 int symin;
1549 int symax;
1550 long gfx;
1551 long gfy;
1552 #endif
1553 {
1554 debugmessage("init_fpscf","");
1555
1556 if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
1557 screen_xmin = sxmin;
1558 screen_xmax = sxmax;
1559 screen_ymin = symin;
1560 screen_ymax = symax;
1561 }
1562 graph_xmin = 0L;
1563 graph_xmax = maximal_xpos + (long)G_xbase;
1564 graph_ymin = 0L;
1565 graph_ymax = maximal_ypos + (long)G_ybase;
1566
1567 gfishdist = 2L * (long)(screen_xmax-screen_xmin);
1568 if (gfishdist<30L) gfishdist = 30;
1569
1570 sfocus_x = (screen_xmax+screen_xmin)/2;
1571 sfocus_y = (screen_ymax+screen_ymin)/2;
1572 gfocus_x = gfx;
1573 gfocus_y = gfy;
1574 if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
1575 if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
1576 if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
1577 if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
1578 if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
1579 if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
1580 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1581 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1582 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1583 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1584 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1585 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1586 V_xmin = 0L;
1587 V_xmax = MAXLONG;
1588 V_ymin = 0L;
1589 V_ymax = MAXLONG;
1590 calc_fpscf_parameters();
1591 }
1592
1593
1594 /* Change scaling
1595 * --------------
1596 */
1597
1598 #ifdef ANSI_C
change_fpscf_scaling(void)1599 static void change_fpscf_scaling(void)
1600 #else
1601 static void change_fpscf_scaling()
1602 #endif
1603 {
1604 debugmessage("change_fpscf_scaling","");
1605
1606 calc_fpscf_parameters();
1607 }
1608
1609
1610 /* Change windowsize
1611 * -----------------
1612 * Returns 1, if a redraw is necessary.
1613 */
1614
1615 #ifdef ANSI_C
change_fpscf_winsize(int sxmin,int sxmax,int symin,int symax)1616 static int change_fpscf_winsize(int sxmin, int sxmax, int symin, int symax)
1617 #else
1618 static int change_fpscf_winsize(sxmin, sxmax, symin, symax)
1619 int sxmin;
1620 int sxmax;
1621 int symin;
1622 int symax;
1623 #endif
1624 {
1625 int oldsxmin, oldsxmax, oldsymin, oldsymax;
1626
1627 debugmessage("change_fpscf_winsize","");
1628
1629 oldsxmin = screen_xmin;
1630 oldsxmax = screen_xmax;
1631 oldsymin = screen_ymin;
1632 oldsymax = screen_ymax;
1633 screen_xmin = sxmin;
1634 screen_xmax = sxmax;
1635 screen_ymin = symin;
1636 screen_ymax = symax;
1637 calc_fpscf_parameters();
1638 if (oldsxmin != screen_xmin) return(1);
1639 if (oldsxmax != screen_xmax) return(1);
1640 if (oldsymin != screen_ymin) return(1);
1641 if (oldsymax != screen_ymax) return(1);
1642 return(0);
1643 }
1644
1645
1646 /* Change graph focus
1647 * ------------------
1648 * Returns 1, if a redraw is necessary.
1649 */
1650
1651 #ifdef ANSI_C
change_fpscf_gfocus(long gfx,long gfy)1652 static int change_fpscf_gfocus(long gfx, long gfy)
1653 #else
1654 static int change_fpscf_gfocus(gfx, gfy)
1655 long gfx;
1656 long gfy;
1657 #endif
1658 {
1659 long oldgfx, oldgfy;
1660
1661 debugmessage("change_fpscf_gfocus","");
1662
1663 oldgfx = gfocus_x;
1664 oldgfy = gfocus_y;
1665 gfocus_x = gfx;
1666 gfocus_y = gfy;
1667 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1668 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1669 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1670 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1671 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1672 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1673 calc_fpscf_parameters();
1674 if (oldgfx != gfocus_x) return(1);
1675 if (oldgfy != gfocus_y) return(1);
1676 return(0);
1677 }
1678
1679
1680 /* Increment graph focus
1681 * ---------------------
1682 * Returns 1, if a redraw is necessary.
1683 */
1684
1685 #ifdef ANSI_C
incr_fpscf_gfocus(long dfx,long dfy)1686 static int incr_fpscf_gfocus(long dfx, long dfy)
1687 #else
1688 static int incr_fpscf_gfocus(dfx, dfy)
1689 long dfx;
1690 long dfy;
1691 #endif
1692 {
1693 debugmessage("incr_fpscf_sfocus","");
1694
1695 if ((dfx==0L) && (dfy==0L)) return(0);
1696 gfocus_x += dfx;
1697 gfocus_y += dfy;
1698 if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1699 if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1700 if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1701 if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1702 if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1703 if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1704 calc_fpscf_parameters(); /* not necessary ? */
1705 return(1);
1706 }
1707
1708
1709 /* Change the fisheye width
1710 * ------------------------
1711 * Returns 1, if a redraw is necessary.
1712 */
1713
1714 #ifdef ANSI_C
set_fpscf_gfishdist(long gd)1715 static int set_fpscf_gfishdist(long gd)
1716 #else
1717 static int set_fpscf_gfishdist(gd)
1718 long gd;
1719 #endif
1720 {
1721 int ret;
1722
1723 debugmessage("set_fpscf_gfishdist","");
1724
1725 if (gd<30L) return(0);
1726
1727 ret = (gfishdist != gd);
1728 gfishdist = gd;
1729 calc_fpscf_parameters();
1730 return(ret);
1731 }
1732
1733 /*--------------------------------------------------------------------*/
1734 /* Entry-Points for the different fisheyes */
1735 /*--------------------------------------------------------------------*/
1736
1737 /* Initialization of the fisheye
1738 * -----------------------------
1739 */
1740
1741
1742 #ifdef ANSI_C
init_fe(int sxmin,int sxmax,int symin,int symax,int sfx,int sfy)1743 void init_fe(int sxmin, int sxmax, int symin, int symax,
1744 int sfx, int sfy)
1745 #else
1746 void init_fe(sxmin, sxmax, symin, symax, sfx, sfy)
1747 int sxmin;
1748 int sxmax;
1749 int symin;
1750 int symax;
1751 int sfx;
1752 int sfy;
1753 #endif
1754 {
1755 long gfx, gfy;
1756
1757 debugmessage("init_fe","");
1758
1759 fe_scaling = (long)(G_stretch * 100 / G_shrink);
1760 if (fe_scaling<=0L) fe_scaling = 1L;
1761 if (fe_scaling>=5000L) fe_scaling = 5000L;
1762 gfx = V_xmin + (long)(sxmax-sxmin)/2L;
1763 gfy = V_ymin + (long)(symax-symin)/2L;
1764
1765 if (!xcoord_hash)
1766 xcoord_hash = (short *)malloc(COORD_HASHSIZE*sizeof(short));
1767 if (!ycoord_hash)
1768 ycoord_hash = (short *)malloc(COORD_HASHSIZE*sizeof(short));
1769
1770 switch (fisheye_view) {
1771 case CSCF_VIEW:
1772 init_cscf(sxmin,sxmax,symin,symax,gfx,gfy);
1773 G_stretch = G_shrink = 1;
1774 V_xmin = 0L;
1775 V_xmax = MAXLONG;
1776 return;
1777 case FCSCF_VIEW:
1778 init_fcscf(sxmin,sxmax,symin,symax,gfx,gfy);
1779 G_stretch = G_shrink = 1;
1780 V_xmin = 0L;
1781 V_xmax = MAXLONG;
1782 return;
1783 case PSCF_VIEW:
1784 init_pscf(sxmin,sxmax,symin,symax,gfx,gfy);
1785 G_stretch = G_shrink = 1;
1786 V_xmin = 0L;
1787 V_xmax = MAXLONG;
1788 return;
1789 case FPSCF_VIEW:
1790 init_fpscf(sxmin,sxmax,symin,symax,gfx,gfy);
1791 G_stretch = G_shrink = 1;
1792 V_xmin = 0L;
1793 V_xmax = MAXLONG;
1794 return;
1795 }
1796 fisheye_view = 0;
1797
1798 }
1799
1800 /* Exit a fisheye view
1801 * -------------------
1802 */
1803
1804 #ifdef ANSI_C
exit_fe(void)1805 void exit_fe(void)
1806 #else
1807 void exit_fe()
1808 #endif
1809 {
1810 debugmessage("exit_fe","");
1811
1812 if (fisheye_view==0) return;
1813 G_shrink = 100;
1814 G_stretch = fe_scaling;
1815 V_xmin = gfocus_x - (long)(screen_xmax-screen_xmin)/2;
1816 V_ymin = gfocus_y - (long)(screen_ymax-screen_ymin)/2;
1817 V_xmax = V_xmin + (long)G_xmax;
1818 V_ymax = V_ymin + (long)(G_ymax + COFFSET);
1819 fisheye_view = 0;
1820 }
1821
1822
1823
1824 /* Translate a x,y-coord. of the graph into a x,y-coord. of the screen
1825 * -------------------------------------------------------------------
1826 */
1827
1828
1829 #ifdef ANSI_C
fe_g_to_s(long x,long y,int * resx,int * resy)1830 void fe_g_to_s(long x, long y, int *resx, int *resy)
1831 #else
1832 void fe_g_to_s(x, y, resx, resy)
1833 long x, y;
1834 int *resx, *resy;
1835 #endif
1836 {
1837 int have_x = 0;
1838
1839 if ((xcoord_hash) && (x>=xhashmin) && (x<=xhashmax)) {
1840 *resx = (int)xcoord_hash[x];
1841 have_x = 1;
1842 }
1843 if ((ycoord_hash) && (y>=yhashmin) && (y<=yhashmax)) {
1844 *resy = (int)ycoord_hash[y];
1845 if (have_x) return;
1846 }
1847
1848 switch (fisheye_view) {
1849 case FCSCF_VIEW:
1850 case CSCF_VIEW: cscf_g_to_s(x,y,resx,resy); return;
1851 case FPSCF_VIEW:
1852 case PSCF_VIEW: pscf_g_to_s(x,y,resx,resy); return;
1853 }
1854 *resx = (int)x;
1855 *resy = (int)y;
1856 }
1857
1858
1859 /* Translate a x,y-coord. of the screen into a x,y-coord. of the graph
1860 * -------------------------------------------------------------------
1861 */
1862
1863 #ifdef ANSI_C
fe_s_to_g(int x,int y,long * resx,long * resy)1864 void fe_s_to_g(int x, int y, long *resx, long *resy)
1865 #else
1866 void fe_s_to_g(x, y, resx, resy)
1867 int x, y;
1868 long *resx, *resy;
1869 #endif
1870 {
1871 switch (fisheye_view) {
1872 case FCSCF_VIEW:
1873 case CSCF_VIEW: cscf_s_to_g(x,y,resx,resy); return;
1874 case FPSCF_VIEW:
1875 case PSCF_VIEW: pscf_s_to_g(x,y,resx,resy); return;
1876 }
1877 *resx = (long)x;
1878 *resy = (long)y;
1879 }
1880
1881
1882 /* Set scaling
1883 * -----------
1884 */
1885
1886 #ifdef ANSI_C
set_fe_scaling(int stretch,int shrink)1887 void set_fe_scaling(int stretch, int shrink)
1888 #else
1889 void set_fe_scaling(stretch, shrink)
1890 int stretch, shrink;
1891 #endif
1892 {
1893 long xx, yy;
1894
1895 debugmessage("set_fe_scaling","");
1896
1897 if (shrink==0) fe_scaling = 100L;
1898 else fe_scaling = (long)(stretch * 100 / shrink);
1899 if (fe_scaling<=0L) fe_scaling = 1L;
1900 if (fe_scaling>=5000L) fe_scaling = 5000L;
1901
1902 switch (fisheye_view) {
1903 case CSCF_VIEW: change_cscf_scaling(); return;
1904 case FCSCF_VIEW: change_fcscf_scaling(); return;
1905 case PSCF_VIEW: change_pscf_scaling(); return;
1906 case FPSCF_VIEW: change_fpscf_scaling(); return;
1907 }
1908 xx = V_xmin * (long)G_shrink/(long)G_stretch;
1909 yy = V_ymin * (long)G_shrink/(long)G_stretch;
1910 G_stretch = stretch;
1911 G_shrink = shrink;
1912 normalize_scaling();
1913 V_xmin = xx * (long)G_stretch/(long)G_shrink;
1914 V_ymin = yy * (long)G_stretch/(long)G_shrink;
1915 V_xmax = V_xmin+(long)G_xmax;
1916 V_ymax = V_ymin+(long)(G_ymax+COFFSET);
1917 }
1918
1919
1920 /* Change scaling relatively
1921 * -------------------------
1922 */
1923
1924 #ifdef ANSI_C
change_fe_scaling(int stretch,int shrink)1925 void change_fe_scaling(int stretch, int shrink)
1926 #else
1927 void change_fe_scaling(stretch, shrink)
1928 int stretch, shrink;
1929 #endif
1930 {
1931 long xx, yy;
1932
1933 debugmessage("change_fe_scaling","");
1934
1935 if (shrink==0) fe_scaling = 100L;
1936 else fe_scaling = fe_scaling * (long)stretch / (long)shrink;
1937 if (fe_scaling<=0L) fe_scaling = 1L;
1938 if (fe_scaling>=5000L) fe_scaling = 5000L;
1939 switch (fisheye_view) {
1940 case CSCF_VIEW: change_cscf_scaling(); return;
1941 case FCSCF_VIEW: change_fcscf_scaling(); return;
1942 case PSCF_VIEW: change_pscf_scaling(); return;
1943 case FPSCF_VIEW: change_fpscf_scaling(); return;
1944 }
1945
1946 xx = V_xmin * (long)G_shrink/(long)G_stretch;
1947 yy = V_ymin * (long)G_shrink/(long)G_stretch;
1948 G_stretch = G_stretch * stretch;
1949 G_shrink = G_shrink * shrink;
1950 normalize_scaling();
1951 V_xmin = xx * (long)G_stretch/(long)G_shrink;
1952 V_ymin = yy * (long)G_stretch/(long)G_shrink;
1953 V_xmax = V_xmin+(long)G_xmax;
1954 V_ymax = V_ymin+(long)(G_ymax+COFFSET);
1955 }
1956
1957
1958
1959 /* Set graph focus to the normal position
1960 * --------------------------------------
1961 * Returns 1, if a redraw is necessary.
1962 */
1963
1964 #ifdef ANSI_C
normal_fe_focus(void)1965 int normal_fe_focus(void)
1966 #else
1967 int normal_fe_focus()
1968 #endif
1969 {
1970 int ret;
1971 long dfx, dfy;
1972
1973 debugmessage("normal_fe_focus","");
1974
1975 dfx = (graph_xmin + graph_xmax)/2L;
1976 dfy = (graph_ymin + graph_ymax)/2L;
1977 switch (fisheye_view) {
1978 case CSCF_VIEW: return(change_cscf_gfocus(dfx, dfy));
1979 case FCSCF_VIEW: return(change_fcscf_gfocus(dfx, dfy));
1980 case PSCF_VIEW: return(change_pscf_gfocus(dfx, dfy));
1981 case FPSCF_VIEW: return(change_fpscf_gfocus(dfx, dfy));
1982 }
1983 ret = 0;
1984 if (V_xmin!=0L) ret = 1;
1985 if (V_ymin!=0L) ret = 1;
1986 V_xmin = 0L;
1987 V_ymin = 0L;
1988 V_xmax = V_xmin+(long)G_xmax;
1989 V_ymax = V_ymin+(long)(G_ymax+COFFSET);
1990 return(ret);
1991 }
1992
1993
1994 /* Set graph focus x-coordinate
1995 * ----------------------------
1996 * Returns 1, if a redraw is necessary.
1997 */
1998
1999 #ifdef ANSI_C
set_fe_xfocus(long fx)2000 int set_fe_xfocus(long fx)
2001 #else
2002 int set_fe_xfocus(fx)
2003 long fx;
2004 #endif
2005 {
2006 int ret;
2007
2008 debugmessage("set_fe_xfocus","");
2009
2010 switch (fisheye_view) {
2011 case CSCF_VIEW: return(change_cscf_gfocus(fx, gfocus_y));
2012 case FCSCF_VIEW: return(change_fcscf_gfocus(fx, gfocus_y));
2013 case PSCF_VIEW: return(change_pscf_gfocus(fx, gfocus_y));
2014 case FPSCF_VIEW: return(change_fpscf_gfocus(fx, gfocus_y));
2015 }
2016 ret = 0;
2017 if (V_xmin!=fx) ret = 1;
2018 V_xmin = fx;
2019 V_xmax = V_xmin+(long)G_xmax;
2020 return(ret);
2021 }
2022
2023
2024 /* Set graph focus y-coordinate
2025 * ----------------------------
2026 * Returns 1, if a redraw is necessary.
2027 */
2028
2029 #ifdef ANSI_C
set_fe_yfocus(long fy)2030 int set_fe_yfocus(long fy)
2031 #else
2032 int set_fe_yfocus(fy)
2033 long fy;
2034 #endif
2035 {
2036 int ret;
2037
2038 debugmessage("set_fe_yfocus","");
2039
2040 switch (fisheye_view) {
2041 case CSCF_VIEW: return(change_cscf_gfocus(gfocus_x,fy));
2042 case FCSCF_VIEW: return(change_fcscf_gfocus(gfocus_x,fy));
2043 case PSCF_VIEW: return(change_pscf_gfocus(gfocus_x,fy));
2044 case FPSCF_VIEW: return(change_fpscf_gfocus(gfocus_x,fy));
2045 }
2046 ret = 0;
2047 if (V_ymin!=fy) ret = 1;
2048 V_ymin = fy;
2049 V_ymax = V_ymin+(long)(G_ymax+COFFSET);
2050 return(ret);
2051 }
2052
2053
2054
2055 /* Increment graph focus
2056 * ---------------------
2057 * Returns 1, if a redraw is necessary.
2058 */
2059
2060 #ifdef ANSI_C
incr_fe_focus(long dfx,long dfy)2061 int incr_fe_focus(long dfx, long dfy)
2062 #else
2063 int incr_fe_focus(dfx, dfy)
2064 long dfx, dfy;
2065 #endif
2066 {
2067 debugmessage("incr_fe_focus","");
2068
2069 switch (fisheye_view) {
2070 case CSCF_VIEW: return(incr_cscf_gfocus(dfx, dfy));
2071 case FCSCF_VIEW: return(incr_fcscf_gfocus(dfx, dfy));
2072 case PSCF_VIEW: return(incr_pscf_gfocus(dfx, dfy));
2073 case FPSCF_VIEW: return(incr_fpscf_gfocus(dfx, dfy));
2074 }
2075 V_xmin += dfx;
2076 V_ymin += dfy;
2077 V_xmax = V_xmin+(long)G_xmax;
2078 V_ymax = V_ymin+(long)(G_ymax+COFFSET);
2079 if ((dfx==0L) && (dfy==0L)) return(0);
2080 return(1);
2081 }
2082
2083
2084
2085 /* Change windowsize
2086 * -----------------
2087 * Returns 1, if a redraw is necessary.
2088 */
2089
2090 #ifdef ANSI_C
change_fe_winsize(int sxmin,int sxmax,int symin,int symax)2091 int change_fe_winsize(int sxmin, int sxmax, int symin, int symax)
2092 #else
2093 int change_fe_winsize(sxmin, sxmax, symin, symax)
2094 int sxmin;
2095 int sxmax;
2096 int symin;
2097 int symax;
2098 #endif
2099 {
2100 switch (fisheye_view) {
2101 case CSCF_VIEW: return(change_cscf_winsize(sxmin,sxmax,symin,symax));
2102 case FCSCF_VIEW: return(change_fcscf_winsize(sxmin,sxmax,symin,symax));
2103 case PSCF_VIEW: return(change_pscf_winsize(sxmin,sxmax,symin,symax));
2104 case FPSCF_VIEW: return(change_fpscf_winsize(sxmin,sxmax,symin,symax));
2105 }
2106 return(0);
2107 }
2108
2109
2110 /* Change the fisheye width
2111 * ------------------------
2112 * Returns 1, if a redraw is necessary.
2113 */
2114
2115 #ifdef ANSI_C
set_gfishdist(long gd)2116 int set_gfishdist(long gd)
2117 #else
2118 int set_gfishdist(gd)
2119 long gd;
2120 #endif
2121 {
2122 switch (fisheye_view) {
2123 case FCSCF_VIEW: return(set_fcscf_gfishdist(gd));
2124 case FPSCF_VIEW: return(set_fpscf_gfishdist(gd));
2125 }
2126 return(0);
2127 }
2128
2129
2130 /*--------------------------------------------------------------------*/
2131 /* Normalize G_shrink and G_stretch */
2132 /*--------------------------------------------------------------------*/
2133
2134 /* This is done to minimize rounding errors if to often
2135 * the scaling is changed.
2136 */
2137
2138 #ifdef ANSI_C
normalize_scaling(void)2139 static void normalize_scaling(void)
2140 #else
2141 static void normalize_scaling()
2142 #endif
2143 {
2144 if (G_shrink<0) G_shrink *= -1;
2145 if (G_stretch<0) G_stretch *= -1;
2146 if (G_shrink==G_stretch) G_shrink = G_stretch = 1;
2147 if (G_shrink ==0) G_shrink=1;
2148 if (G_stretch==0) G_stretch=1;
2149 if (G_stretch > G_shrink) {
2150 if (G_shrink * 5000 < G_stretch) {
2151 G_shrink = 1;
2152 G_stretch = 5000;
2153 }
2154 G_stretch = G_stretch * 60 / G_shrink;
2155 G_shrink = 60;
2156 }
2157 if (G_stretch < G_shrink) {
2158 if (G_shrink > G_stretch * 5000) {
2159 G_shrink = 5000;
2160 G_stretch = 1;
2161 }
2162 G_shrink = G_shrink * 60 / G_stretch;
2163 G_stretch = 60;
2164 }
2165 while ((G_shrink%2==0) && (G_stretch%2==0)) {
2166 G_shrink = G_shrink/2;
2167 G_stretch = G_stretch/2;
2168 }
2169 while ((G_shrink%3==0) && (G_stretch%3==0)) {
2170 G_shrink = G_shrink/3;
2171 G_stretch = G_stretch/3;
2172 }
2173 while ((G_shrink%5==0) && (G_stretch%5==0)) {
2174 G_shrink = G_shrink/5;
2175 G_stretch = G_stretch/5;
2176 }
2177 while ((G_shrink%7==0) && (G_stretch%7==0)) {
2178 G_shrink = G_shrink/7;
2179 G_stretch = G_stretch/7;
2180 }
2181 if (G_shrink ==0) G_shrink=1;
2182 if (G_stretch==0) G_stretch=1;
2183 }
2184
2185
2186 /*--------------------------------------------------------------------*/
2187 /* Normalize par_xrp1, ... par_yup2 */
2188 /*--------------------------------------------------------------------*/
2189
2190 /* This is done to minimize rounding errors if the fisheye comes
2191 * too extreme or to near to the normal view.
2192 */
2193
2194 #ifdef ANSI_C
normalize_fe_parameters(void)2195 static void normalize_fe_parameters(void)
2196 #else
2197 static void normalize_fe_parameters()
2198 #endif
2199 {
2200 double h;
2201 long s;
2202
2203 assert((par_xrp1>0L));
2204 if (par_xrp2 < 0L) s = -1L; else s = 1L;
2205 par_xrp2 = par_xrp2 * s;
2206 if (par_xrp1 > par_xrp2) {
2207 h = (double)par_xrp1/(double)par_xrp2;
2208 if (h<10.0) {
2209 par_xrp1 = (long)(h*100+0.5);
2210 par_xrp2 = s * 100L;
2211 }
2212 else if (h<100.0) {
2213 par_xrp1 = (long)(h*10+0.5);
2214 par_xrp2 = s * 10L;
2215 }
2216 else if (h>1000.0) {
2217 par_xrp1 = 1000L;
2218 par_xrp2 = s;
2219 }
2220 else { par_xrp1 = (long)(h+0.5);
2221 par_xrp2 = s;
2222 }
2223 }
2224 else {
2225 h = (double)par_xrp2/(double)par_xrp1;
2226 if (h<10.0) {
2227 par_xrp2 = s * (long)(h*100+0.5);
2228 par_xrp1 = 100L;
2229 }
2230 else if (h<100.0) {
2231 par_xrp2 = s * (long)(h*10+0.5);
2232 par_xrp1 = 10L;
2233 }
2234 else if (h>1000.0) {
2235 par_xrp2 = s*1000;
2236 par_xrp1 = 1L;
2237 }
2238 else { par_xrp2 = s * (long)(h+0.5);
2239 par_xrp1 = 1L;
2240 }
2241 }
2242 assert((par_xlp1>0L));
2243 if (par_xlp2 < 0L) s = -1L; else s = 1L;
2244 par_xlp2 = par_xlp2 * s;
2245 if (par_xlp1 > par_xlp2) {
2246 h = (double)par_xlp1/(double)par_xlp2;
2247 if (h<10.0) {
2248 par_xlp1 = (long)(h*100+0.5);
2249 par_xlp2 = s * 100L;
2250 }
2251 else if (h<100.0) {
2252 par_xlp1 = (long)(h*10+0.5);
2253 par_xlp2 = s * 10L;
2254 }
2255 else if (h>1000.0) {
2256 par_xlp1 = 1000;
2257 par_xlp2 = s;
2258 }
2259 else { par_xlp1 = (long)(h+0.5);
2260 par_xlp2 = s;
2261 }
2262 }
2263 else {
2264 h = (double)par_xlp2/(double)par_xlp1;
2265 if (h<10.0) {
2266 par_xlp2 = s * (long)(h*100+0.5);
2267 par_xlp1 = 100L;
2268 }
2269 else if (h<100.0) {
2270 par_xlp2 = s * (long)(h*10+0.5);
2271 par_xlp1 = 10L;
2272 }
2273 else if (h>1000.0) {
2274 par_xlp2 = s * 1000;
2275 par_xlp1 = 1L;
2276 }
2277 else { par_xlp2 = s * (long)(h+0.5);
2278 par_xlp1 = 1L;
2279 }
2280 }
2281 assert((par_ylp1>0L));
2282 if (par_ylp2 < 0L) s = -1L; else s = 1L;
2283 par_ylp2 = par_ylp2 * s;
2284 if (par_ylp1 > par_ylp2) {
2285 h = (double)par_ylp1/(double)par_ylp2;
2286 if (h<10.0) {
2287 par_ylp1 = (long)(h*100+0.5);
2288 par_ylp2 = s * 100L;
2289 }
2290 else if (h<100.0) {
2291 par_ylp1 = (long)(h*10+0.5);
2292 par_ylp2 = s * 10L;
2293 }
2294 else if (h>1000.0) {
2295 par_ylp1 = 1000;
2296 par_ylp2 = s;
2297 }
2298 else { par_ylp1 = (long)(h+0.5);
2299 par_ylp2 = s;
2300 }
2301 }
2302 else {
2303 h = (double)par_ylp2/(double)par_ylp1;
2304 if (h<10.0) {
2305 par_ylp2 = s * (long)(h*100+0.5);
2306 par_ylp1 = 100L;
2307 }
2308 else if (h<100.0) {
2309 par_ylp2 = s * (long)(h*10+0.5);
2310 par_ylp1 = 10L;
2311 }
2312 else if (h>1000.0) {
2313 par_ylp2 = s * 1000;
2314 par_ylp1 = 1L;
2315 }
2316 else { par_ylp2 = s * (long)(h+0.5);
2317 par_ylp1 = 1L;
2318 }
2319 }
2320 assert((par_yup1>0L));
2321 if (par_yup2 < 0L) s = -1L; else s = 1L;
2322 par_yup2 = par_yup2 * s;
2323 if (par_yup1 > par_yup2) {
2324 h = (double)par_yup1/(double)par_yup2;
2325 if (h<10.0) {
2326 par_yup1 = (long)(h*100+0.5);
2327 par_yup2 = s * 100L;
2328 }
2329 else if (h<100.0) {
2330 par_yup1 = (long)(h*10+0.5);
2331 par_yup2 = s * 10L;
2332 }
2333 else if (h>1000.0) {
2334 par_yup1 = 1000;
2335 par_yup2 = s;
2336 }
2337 else { par_yup1 = (long)(h+0.5);
2338 par_yup2 = s;
2339 }
2340 }
2341 else {
2342 h = (double)par_yup2/(double)par_yup1;
2343 if (h<10.0) {
2344 par_yup2 = s * (long)(h*100+0.5);
2345 par_yup1 = 100L;
2346 }
2347 else if (h<100.0) {
2348 par_yup2 = s * (long)(h*10+0.5);
2349 par_yup1 = 10L;
2350 }
2351 else if (h>1000.0) {
2352 par_yup2 = s * 1000;
2353 par_yup1 = 1L;
2354 }
2355 else { par_yup2 = s * (long)(h+0.5);
2356 par_yup1 = 1L;
2357 }
2358 }
2359 }
2360
2361