]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/hud_card.cxx
- fix more cases of scale tick aliasing to get smooth scale movements
[flightgear.git] / src / Cockpit / hud_card.cxx
1
2 #ifdef HAVE_CONFIG_H
3 #  include "config.h"
4 #endif
5
6 #include <plib/sg.h>
7 #include "hud.hxx"
8
9 #ifdef USE_HUD_TextList
10 #define textString(x, y, text, digit)  TextString(text, x , y ,digit)
11 #else
12 #define textString(x, y, text, digit)  puDrawString(guiFnt, text, x, y)
13 #endif
14
15 //========== Top of hud_card class member definitions =============
16 #include <math.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19
20
21 hud_card::hud_card(
22           int       x,
23           int       y,
24           UINT      width,
25           UINT      height,
26           FLTFNPTR  data_source,
27           UINT      options,
28           float     max_value, // 360
29           float     min_value, // 0
30           float     disp_scaling,
31           UINT      major_divs,
32           UINT      minor_divs,
33           UINT      modulus,  // 360
34           int       dp_showing,
35           float     value_span,
36           string    card_type,
37           bool      tick_bottom,
38           bool      tick_top,
39           bool      tick_right,
40           bool      tick_left,
41           bool      cap_bottom,
42           bool      cap_top,
43           bool      cap_right,
44           bool      cap_left,
45           float     mark_offset,
46           bool      pointer_enable,
47           string    type_pointer,
48           string    type_tick,//hud
49           string    length_tick,//hud
50           bool      working,
51           float     rad,
52           int       divs,
53           int       zooms) :
54     instr_scale(x,y,width,height,
55                  data_source, options,
56                  value_span,
57                  max_value, min_value, disp_scaling,
58                  major_divs, minor_divs, modulus,
59                  working),
60     val_span         (value_span),
61     type             (card_type),
62     draw_tick_bottom (tick_bottom),
63     draw_tick_top    (tick_top),
64     draw_tick_right  (tick_right),
65     draw_tick_left   (tick_left),
66     draw_cap_bottom  (cap_bottom),
67     draw_cap_top     (cap_top),
68     draw_cap_right   (cap_right),
69     draw_cap_left    (cap_left),
70     marker_offset    (mark_offset),
71     pointer          (pointer_enable),
72     pointer_type     (type_pointer),
73     tick_type        (type_tick), //hud
74     tick_length      (length_tick), //hud
75     Maj_div          (major_divs),
76     Min_div          (minor_divs)
77
78 {
79     half_width_units = range_to_show() / 2.0;
80     radius = rad;
81     maxValue = max_value;
82     minValue = min_value;
83     divisions = divs;
84     zoom = zooms;
85
86     //  UINT options     = get_options();
87     //  huds_both = (options & HUDS_BOTH) == HUDS_BOTH;
88     //  huds_right = options & HUDS_RIGHT;
89     //  huds_left = options & HUDS_LEFT;
90     //  huds_vert = options & HUDS_VERT;
91     //  huds_notext = options & HUDS_NOTEXT;
92     //  huds_top = options & HUDS_TOP;
93     //  huds_bottom = options & HUDS_BOTTOM;
94 }
95
96
97 hud_card::~hud_card() { }
98
99
100 hud_card::hud_card(const hud_card & image) :
101     instr_scale((const instr_scale &) image),
102     val_span(image.val_span),
103     type(image.type),
104     half_width_units (image.half_width_units),
105     draw_tick_bottom (image.draw_tick_bottom),
106     draw_tick_top (image.draw_tick_top),
107     draw_tick_right (image.draw_tick_right),
108     draw_tick_left (image.draw_tick_left),
109     draw_cap_bottom (image.draw_cap_bottom),
110     draw_cap_top (image.draw_cap_top),
111     draw_cap_right (image.draw_cap_right),
112     draw_cap_left (image.draw_cap_left),
113     marker_offset (image.marker_offset),
114     pointer (image.pointer),
115     pointer_type (image.pointer_type),
116     tick_type(image.tick_type), //hud
117     tick_length(image.tick_length), //hud
118     Maj_div(image.Maj_div),
119     Min_div(image.Min_div)
120
121 {
122     //  UINT options     = get_options();
123     //  huds_both = (options & HUDS_BOTH) == HUDS_BOTH;
124     //  huds_right = options & HUDS_RIGHT;
125     //  huds_left = options & HUDS_LEFT;
126     //  huds_vert = options & HUDS_VERT;
127     //  huds_notext = options & HUDS_NOTEXT;
128     //  huds_top = options & HUDS_TOP;
129     //  huds_bottom = options & HUDS_BOTTOM;
130 }
131
132
133 hud_card & hud_card::operator=(const hud_card & rhs)
134 {
135     if (!(this == &rhs)) {
136         instr_scale::operator = (rhs);
137         val_span = rhs.val_span;
138         half_width_units = rhs.half_width_units;
139         draw_tick_bottom = rhs.draw_tick_bottom;
140         draw_tick_top    = rhs.draw_tick_top;
141         draw_tick_right  = rhs.draw_tick_right;
142         draw_tick_left   = rhs.draw_tick_left;
143         draw_cap_bottom  = rhs.draw_cap_bottom;
144         draw_cap_top     = rhs.draw_cap_top;
145         draw_cap_right   = rhs.draw_cap_right;
146         draw_cap_left    = rhs.draw_cap_left;
147         marker_offset    = rhs.marker_offset;
148         type             = rhs.type;
149         pointer          = rhs.pointer;
150         pointer_type     = rhs.pointer_type;
151         tick_type        = rhs.tick_type;
152         tick_length      = rhs.tick_length;
153         Maj_div          = rhs.Maj_div;
154         Min_div          = rhs.Min_div;
155     }
156
157     return *this;
158 }
159
160
161 void hud_card::draw(void) //  (HUD_scale * pscale)
162 {
163     float vmin = 0.0, vmax = 0.0;
164     float marker_xs;
165     float marker_xe;
166     float marker_ys;
167     float marker_ye;
168     int text_x = 0, text_y = 0;
169     int lenstr;
170     int height, width;
171     int i, last;
172     char TextScale[80];
173     bool condition;
174     int disp_val = 0;
175     int oddtype, k; //odd or even values for ticks
176
177     POINT mid_scr    = get_centroid();
178     float cur_value  = get_value();
179
180     if (!((int)maxValue%2))
181         oddtype = 0; //draw ticks at even values
182     else
183         oddtype = 1; //draw ticks at odd values
184
185     RECT scrn_rect = get_location();
186     UINT options = get_options();
187
188     height = scrn_rect.top + scrn_rect.bottom;
189     width = scrn_rect.left + scrn_rect.right;
190
191     // if type=gauge then display dial
192     if (type == "gauge") {
193         float x,y;
194         float i;
195         y = (float)(scrn_rect.top);
196         x = (float)(scrn_rect.left);
197         glEnable(GL_POINT_SMOOTH);
198         glPointSize(3.0);
199
200         float incr = 360.0 / divisions;
201         for (i = 0.0; i < 360.0; i += incr) {
202             float i1 = i * SGD_DEGREES_TO_RADIANS;
203             float x1 = x + radius*cos(i1);
204             float y1 = y + radius*sin(i1);
205
206             glBegin(GL_POINTS);
207             glVertex2f(x1, y1);
208             glEnd();
209         }
210         glPointSize(1.0);
211         glDisable(GL_POINT_SMOOTH);
212
213
214         if (data_available()) {
215             float offset = 90.0 * SGD_DEGREES_TO_RADIANS;
216             float r1 = 10.0; //size of carrot
217             float theta = get_value();
218
219             float theta1 = -theta*SGD_DEGREES_TO_RADIANS+offset;
220             float x1 = x+radius*cos(theta1);
221             float y1 = y+radius*sin(theta1);
222             float x2 = x1-r1*cos(theta1-30.0*SGD_DEGREES_TO_RADIANS);
223             float y2 = y1-r1*sin(theta1-30.0*SGD_DEGREES_TO_RADIANS);
224             float x3 = x1-r1*cos(theta1+30.0*SGD_DEGREES_TO_RADIANS);
225             float y3 = y1-r1*sin(theta1+30.0*SGD_DEGREES_TO_RADIANS);
226
227             // draw carrot
228             drawOneLine(x1,y1,x2,y2);
229             drawOneLine(x1,y1,x3,y3);
230             sprintf(TextScale,"%3.1f\n",theta);
231
232             // draw value
233             int l = abs((int)theta);
234             if (l) {
235                 if (l < 10)
236                     textString(x, y, TextScale, 0);
237                 else if (l < 100)
238                     textString(x-1.0, y, TextScale, 0);
239                 else if (l<360)
240                     textString(x-2.0, y, TextScale, 0);
241             }
242         } //end type=gauge
243
244     } else {
245         // if its not explicitly a gauge default to tape
246         if (pointer) {
247             if (pointer_type=="moving") {
248                 vmin = minValue;
249                 vmax = maxValue;
250
251             } else {
252                 // default to fixed
253                 vmin   = cur_value - half_width_units; // width units == needle travel
254                 vmax   = cur_value + half_width_units; // or picture unit span.
255                 text_x = mid_scr.x;
256                 text_y = mid_scr.y;
257             }
258
259         } else {
260             vmin   = cur_value - half_width_units; // width units == needle travel
261             vmax   = cur_value + half_width_units; // or picture unit span.
262             text_x = mid_scr.x;
263             text_y = mid_scr.y;
264         }
265
266         // Draw the basic markings for the scale...
267
268         if (huds_vert(options)) { // Vertical scale
269             if (draw_tick_bottom) {
270                 drawOneLine(scrn_rect.left,     // Bottom tick bar
271                             scrn_rect.top,
272                             width,
273                             scrn_rect.top);
274             } // endif draw_tick_bottom
275
276             if (draw_tick_top) {
277                 drawOneLine(scrn_rect.left,    // Top tick bar
278                             height,
279                             width,
280                             height);
281             } // endif draw_tick_top
282
283             marker_xs = scrn_rect.left;  // x start
284             marker_xe = width;           // x extent
285             marker_ye = height;
286
287             //    glBegin(GL_LINES);
288
289             // Bottom tick bar
290             //    glVertex2f(marker_xs, scrn_rect.top);
291             //    glVertex2f(marker_xe, scrn_rect.top);
292
293             // Top tick bar
294             //    glVertex2f(marker_xs, marker_ye);
295             //    glVertex2f(marker_xe, marker_ye);
296             //    glEnd();
297
298
299             // We do not use else in the following so that combining the
300             // two options produces a "caged" display with double
301             // carrots. The same is done for horizontal card indicators.
302
303             // begin vertical/left
304             //First draw capping lines and pointers
305             if (huds_left(options)) {    // Calculate x marker offset
306
307                 if (draw_cap_right) {
308                     drawOneLine(marker_xe, scrn_rect.top,
309                                  marker_xe, marker_ye); // Cap right side
310                 } //endif cap_right
311
312                 marker_xs  = marker_xe - scrn_rect.right / 3;   // Adjust tick xs
313
314                 // drawOneLine(marker_xs, mid_scr.y,
315                 //              marker_xe, mid_scr.y + scrn_rect.right / 6);
316                 // drawOneLine(marker_xs, mid_scr.y,
317                 //              marker_xe, mid_scr.y - scrn_rect.right / 6);
318
319                 // draw pointer
320                 if (pointer) {
321                     if (pointer_type=="moving") {
322                         if (zoom == 0) {
323                             //Code for Moving Type Pointer
324                             float ycentre, ypoint,xpoint;
325                             int range,wth;
326                             if (cur_value > maxValue)
327                                 cur_value = maxValue;
328                             if (cur_value < minValue)
329                                 cur_value = minValue;
330
331                             if (minValue >= 0.0)
332                                 ycentre = scrn_rect.top;
333                             else if (maxValue + minValue == 0.0)
334                                 ycentre = mid_scr.y;
335                             else
336                                 if (oddtype == 1)
337                                     ycentre = scrn_rect.top + (1.0-minValue)*scrn_rect.bottom/(maxValue-minValue);
338                                 else
339                                     ycentre = scrn_rect.top + minValue*scrn_rect.bottom/(maxValue-minValue);
340
341                             range = scrn_rect.bottom;
342                             wth   = scrn_rect.left + scrn_rect.right;
343
344                             if (oddtype == 1)
345                                 ypoint = ycentre + ((cur_value-1.0) * range / val_span);
346                             else
347                                 ypoint = ycentre + (cur_value * range / val_span);
348
349                             xpoint = wth + marker_offset;
350                             drawOneLine(xpoint,ycentre,xpoint,ypoint);
351                             drawOneLine(xpoint,ypoint,xpoint-marker_offset,ypoint);
352                             drawOneLine(xpoint-marker_offset,ypoint,xpoint-5.0,ypoint+5.0);
353                             drawOneLine(xpoint-marker_offset,ypoint,xpoint-5.0,ypoint-5.0);
354                         } //zoom=0
355
356                     } else {
357                         // default to fixed
358                         fixed(marker_offset+marker_xe, text_y + scrn_rect.right / 6,
359                               marker_offset+marker_xs, text_y,marker_offset+marker_xe,
360                               text_y - scrn_rect.right / 6);
361                     }//end pointer type
362                 } //if pointer
363             } //end vertical/left
364
365             // begin vertical/right
366             //First draw capping lines and pointers
367             if (huds_right(options)) {  // We'll default this for now.
368                 if (draw_cap_left) {
369                     drawOneLine(scrn_rect.left, scrn_rect.top,
370                                  scrn_rect.left, marker_ye);  // Cap left side
371                 } //endif cap_left
372
373                 marker_xe = scrn_rect.left + scrn_rect.right / 3;     // Adjust tick xe
374                 // Indicator carrot
375                 // drawOneLine(scrn_rect.left, mid_scr.y +  scrn_rect.right / 6,
376                 //              marker_xe, mid_scr.y);
377                 // drawOneLine(scrn_rect.left, mid_scr.y -  scrn_rect.right / 6,
378                 //              marker_xe, mid_scr.y);
379
380                 // draw pointer
381                 if (pointer) {
382                     if (pointer_type == "moving") {
383                         if (zoom == 0) {
384                             //type-fixed & zoom=1, behaviour to be defined
385                             // Code for Moving Type Pointer
386                             float ycentre, ypoint,xpoint;
387                             int range;
388
389                             if (cur_value > maxValue)
390                                 cur_value = maxValue;
391                             if (cur_value < minValue)
392                                 cur_value = minValue;
393
394                             if (minValue >= 0.0)
395                                 ycentre = scrn_rect.top;
396                             else if (maxValue + minValue == 0.0)
397                                 ycentre = mid_scr.y;
398                             else
399                                 if (oddtype == 1)
400                                     ycentre = scrn_rect.top + (1.0-minValue)*scrn_rect.bottom/(maxValue-minValue);
401                                 else
402                                     ycentre = scrn_rect.top + minValue*scrn_rect.bottom/(maxValue-minValue);
403
404                             range = scrn_rect.bottom;
405
406                             if (oddtype == 1)
407                                 ypoint = ycentre + ((cur_value-1.0) * range / val_span);
408                             else
409                                 ypoint = ycentre + (cur_value * range / val_span);
410
411                             xpoint = scrn_rect.left - marker_offset;
412                             drawOneLine(xpoint,ycentre,xpoint,ypoint);
413                             drawOneLine(xpoint,ypoint,xpoint+marker_offset,ypoint);
414                             drawOneLine(xpoint+marker_offset,ypoint,xpoint+5.0,ypoint+5.0);
415                             drawOneLine(xpoint+marker_offset,ypoint,xpoint+5.0,ypoint-5.0);
416                         }
417
418                     } else {
419                         // default to fixed
420                         fixed(-marker_offset+scrn_rect.left, text_y +  scrn_rect.right / 6,
421                                -marker_offset+marker_xe, text_y,-marker_offset+scrn_rect.left,
422                                text_y -  scrn_rect.right / 6);
423                     }
424                 } //if pointer
425             }  //end vertical/right
426
427             // At this point marker x_start and x_end values are transposed.
428             // To keep this from confusing things they are now interchanged.
429             if (huds_both(options)) {
430                 marker_ye = marker_xs;
431                 marker_xs = marker_xe;
432                 marker_xe = marker_ye;
433             }
434
435             // Work through from bottom to top of scale. Calculating where to put
436             // minor and major ticks.
437
438             // draw scale or tape
439
440 //            last = FloatToInt(vmax)+1;
441 //            i = FloatToInt(vmin);
442             last = (int)vmax + 1; // N
443             i = (int)vmin; // N
444
445             if (zoom == 1) {
446                 zoomed_scale((int)vmin, (int)vmax);
447             } else {
448                 for (; i < last; i++) {
449                     condition = true;
450                     if (!modulo()) {
451                         if (i < min_val()) {
452                             condition = false;
453                         }
454                     }
455
456                     if (condition) {  // Show a tick if necessary
457                         // Calculate the location of this tick
458                         marker_ys = scrn_rect.top + ((i - vmin) * factor()/*+.5f*/);
459                         // marker_ys = scrn_rect.top + (int)((i - vmin) * factor() + .5);
460                         // Block calculation artifact from drawing ticks below min coordinate.
461                         // Calculation here accounts for text height.
462
463                         if ((marker_ys < (scrn_rect.top + 4))
464                                 | (marker_ys > (height - 4))) {
465                             // Magic numbers!!!
466                             continue;
467                         }
468
469                         if (oddtype == 1)
470                             k = i+1; //enable ticks at odd values
471                         else
472                             k = i;
473
474                         // Minor ticks
475                         if (div_min()) {
476                             // if ((i%div_min()) == 0) {
477                             if (!(k%(int)div_min())) {
478                                 if (((marker_ys - 5) > scrn_rect.top)
479                                         && ((marker_ys + 5) < (height))) {
480
481                                     //vertical/left OR vertical/right
482                                     if (huds_both(options)) {
483                                         if (tick_type=="line") {
484                                             if (tick_length=="variable") {
485                                                 drawOneLine(scrn_rect.left, marker_ys,
486                                                             marker_xs,      marker_ys);
487                                                 drawOneLine(marker_xe,      marker_ys,
488                                                             width,  marker_ys);
489                                             } else {
490                                                 drawOneLine(scrn_rect.left, marker_ys,
491                                                             marker_xs,      marker_ys);
492                                                 drawOneLine(marker_xe,      marker_ys,
493                                                             width,  marker_ys);
494                                             }
495                                         } else if (tick_type == "circle")
496                                             circles(scrn_rect.left,(float)marker_ys,3.0);
497
498                                         else {
499                                             // if neither line nor circle draw default as line
500                                             drawOneLine(scrn_rect.left, marker_ys,
501                                                         marker_xs,      marker_ys);
502                                             drawOneLine(marker_xe,      marker_ys,
503                                                         width,  marker_ys);
504                                         }
505                                         // glBegin(GL_LINES);
506                                         // glVertex2f(scrn_rect.left, marker_ys);
507                                         // glVertex2f(marker_xs,      marker_ys);
508                                         // glVertex2f(marker_xe,      marker_ys);
509                                         // glVertex2f(scrn_rect.left + scrn_rect.right,  marker_ys);
510                                         // glEnd();
511                                         // anything other than huds_both
512
513                                     } else {
514                                         if (huds_left(options)) {
515                                             if (tick_type=="line") {
516                                                 if (tick_length=="variable") {
517                                                     drawOneLine(marker_xs + 4, marker_ys,
518                                                                 marker_xe,     marker_ys);
519                                                 } else {
520                                                     drawOneLine(marker_xs , marker_ys,
521                                                                 marker_xe,     marker_ys);
522                                                 }
523                                             } else if (tick_type=="circle")
524                                                 circles((float)marker_xs + 4, (float)marker_ys,3.0);
525
526                                             else {
527                                                 drawOneLine(marker_xs + 4, marker_ys,
528                                                             marker_xe,     marker_ys);
529                                             }
530                                         }  else {
531                                             if (tick_type=="line") {
532                                                 if (tick_length=="variable") {
533                                                     drawOneLine(marker_xs,     marker_ys,
534                                                                 marker_xe - 4, marker_ys);
535                                                 } else {
536                                                     drawOneLine(marker_xs,     marker_ys,
537                                                                 marker_xe , marker_ys);
538                                                 }
539                                             } else if (tick_type=="circle")
540                                                 circles((float)marker_xe - 4, (float)marker_ys,3.0);
541                                             else {
542                                                 drawOneLine(marker_xs,     marker_ys,
543                                                             marker_xe - 4, marker_ys);
544                                             }
545                                         }
546                                     } //end huds both
547                                 }
548                             } //end draw minor ticks
549                         }  //end minor ticks
550
551                         // Major ticks
552                         if (div_max()) {
553                             if (!(k%(int)div_max())) {
554                                 if (modulo()) {
555                                     disp_val = i % (int) modulo(); // ?????????
556                                     if (disp_val < 0) {
557                                         while (disp_val < 0)
558                                             disp_val += modulo();
559                                     }
560                                 } else {
561                                     disp_val = i;
562                                 }
563
564                                 lenstr = sprintf(TextScale, "%d",
565                                                  FloatToInt(disp_val * data_scaling()/*+.5*/));
566                                 // (int)(disp_val  * data_scaling() +.5));
567                                 /* if (((marker_ys - 8) > scrn_rect.top) &&
568                                    ((marker_ys + 8) < (height))){ */
569                                 // huds_both
570                                 if (huds_both(options)) {
571                                     // drawOneLine(scrn_rect.left, marker_ys,
572                                     //              marker_xs,      marker_ys);
573                                     // drawOneLine(marker_xs, marker_ys,
574                                     //              scrn_rect.left + scrn_rect.right,
575                                     //              marker_ys);
576                                     if (tick_type == "line") {
577                                         glBegin(GL_LINE_STRIP);
578                                         glVertex2f(scrn_rect.left, marker_ys);
579                                         glVertex2f(marker_xs, marker_ys);
580                                         glVertex2f(width, marker_ys);
581                                         glEnd();
582                                     } else if (tick_type == "circle") {
583                                         circles(scrn_rect.left, (float)marker_ys,5.0);
584                                     } else {
585                                         glBegin(GL_LINE_STRIP);
586                                         glVertex2f(scrn_rect.left, marker_ys);
587                                         glVertex2f(marker_xs, marker_ys);
588                                         glVertex2f(width, marker_ys);
589                                         glEnd();
590                                     }
591
592                                     if (!huds_notext(options)) {
593                                         textString (marker_xs + 2,  marker_ys,
594                                                     TextScale,0);
595                                     }
596
597                                 } else {
598                                     /* Changes are made to draw a circle when tick_type="circle" */
599                                     // anything other than huds_both
600                                     if (tick_type=="line") {
601                                         drawOneLine(marker_xs, marker_ys, marker_xe, marker_ys);
602                                     } else if (tick_type=="circle") {
603                                         circles((float)marker_xs + 4, (float)marker_ys,5.0);
604                                     } else {
605                                         drawOneLine(marker_xs, marker_ys, marker_xe, marker_ys);
606                                     }
607
608                                     if (!huds_notext(options)) {
609                                         if (huds_left(options)) {
610                                             textString(marker_xs -  8 * lenstr - 2,
611                                                        marker_ys - 4,
612                                                        TextScale, 0);
613                                         } else {
614                                             textString(marker_xe + 3 * lenstr,
615                                                        marker_ys - 4,
616                                                        TextScale, 0);
617                                         } //End if huds_left
618                                     } //End if !huds_notext
619                                 }  //End if huds-both
620                             }  // End if draw major ticks
621                         }   // End if major ticks
622                     }  // End condition
623                 }  // End for
624             }  //end of zoom
625             // End if VERTICAL SCALE TYPE (tape loop yet to be closed)
626
627         } else {
628             // Horizontal scale by default
629             // left tick bar
630             if (draw_tick_left) {
631                 drawOneLine(scrn_rect.left, scrn_rect.top,
632                             scrn_rect.left, height);
633             }  // endif draw_tick_left
634             // right tick bar
635             if (draw_tick_right) {
636                 drawOneLine(width, scrn_rect.top,
637                             width,
638                             height);
639             }  // endif draw_tick_right
640
641             marker_ys = scrn_rect.top;           // Starting point for
642             marker_ye = height;                  // tick y location calcs
643             marker_xe = width;
644             marker_xs = scrn_rect.left + ((cur_value - vmin) * factor() /*+ .5f*/);
645
646             //    glBegin(GL_LINES);
647             // left tick bar
648             //    glVertex2f(scrn_rect.left, scrn_rect.top);
649             //    glVertex2f(scrn_rect.left, marker_ye);
650
651             // right tick bar
652             //    glVertex2f(marker_xe, scrn_rect.top);
653             //    glVertex2f(marker_xe, marker_ye);
654             //    glEnd();
655
656             if (huds_top(options)) {
657                 if (draw_cap_bottom) {
658                     // Bottom box line
659                     drawOneLine(scrn_rect.left,
660                                 scrn_rect.top,
661                                 width,
662                                 scrn_rect.top);
663                 }  //endif cap_bottom
664
665                 // Tick point adjust
666                 marker_ye  = scrn_rect.top + scrn_rect.bottom / 2;
667                 // Bottom arrow
668                 // drawOneLine(mid_scr.x, marker_ye,
669                 //              mid_scr.x - scrn_rect.bottom / 4, scrn_rect.top);
670                 // drawOneLine(mid_scr.x, marker_ye,
671                 //              mid_scr.x + scrn_rect.bottom / 4, scrn_rect.top);
672                 // draw pointer
673                 if (pointer) {
674                     if (pointer_type == "moving") {
675                         if (zoom == 0) {
676                             //Code for Moving Type Pointer
677                             // static float xcentre,xpoint,ypoint;
678                             // static int range;
679                             if (cur_value > maxValue)
680                                 cur_value = maxValue;
681                             if (cur_value < minValue)
682                                 cur_value = minValue;
683
684                             float xcentre = mid_scr.x;
685                             int range = scrn_rect.right;
686                             float xpoint = xcentre + (cur_value * range / val_span);
687                             float ypoint = scrn_rect.top - marker_offset;
688                             drawOneLine(xcentre, ypoint,xpoint,ypoint);
689                             drawOneLine(xpoint,ypoint,xpoint,ypoint+marker_offset);
690                             drawOneLine(xpoint,ypoint+marker_offset,xpoint+5.0,ypoint+5.0);
691                             drawOneLine(xpoint,ypoint+marker_offset,xpoint-5.0,ypoint+5.0);
692                         }
693                     } else {
694                         //default to fixed
695                         fixed(marker_xs - scrn_rect.bottom / 4, scrn_rect.top,
696                                marker_xs, marker_ye, marker_xs + scrn_rect.bottom / 4,scrn_rect.top);
697                     }
698                 }  //if pointer
699             } //End Horizontal scale/top
700
701             if (huds_bottom(options)) {
702                 // Top box line
703                 if (draw_cap_top) {
704                     drawOneLine(scrn_rect.left, height,
705                                  width, height);
706                 }  //endif cap_top
707
708                 // Tick point adjust
709                 marker_ys = height - scrn_rect.bottom / 2;
710                 // Top arrow
711                 //      drawOneLine(mid_scr.x + scrn_rect.bottom / 4,
712                 //                   scrn_rect.top + scrn_rect.bottom,
713                 //                   mid_scr.x, marker_ys);
714                 //      drawOneLine(mid_scr.x - scrn_rect.bottom / 4,
715                 //                   scrn_rect.top + scrn_rect.bottom,
716                 //                   mid_scr.x , marker_ys);
717
718                 // draw pointer
719                 if (pointer) {
720                     if (pointer_type =="moving") {
721                         if (zoom == 0) {
722                             //Code for Moving Type Pointer
723                             // static float xcentre,xpoint,ypoint;
724                             // static int range,hgt;
725                             if (cur_value > maxValue)
726                                 cur_value = maxValue;
727                             if (cur_value < minValue)
728                                 cur_value = minValue;
729
730                             float xcentre = mid_scr.x ;
731                             int range = scrn_rect.right;
732                             int hgt   = scrn_rect.top + scrn_rect.bottom;
733                             float xpoint = xcentre + (cur_value * range / val_span);
734                             float ypoint = hgt + marker_offset;
735                             drawOneLine(xcentre, ypoint,xpoint,ypoint);
736                             drawOneLine(xpoint,ypoint,xpoint,ypoint-marker_offset);
737                             drawOneLine(xpoint,ypoint-marker_offset,xpoint+5.0,ypoint-5.0);
738                             drawOneLine(xpoint,ypoint-marker_offset,xpoint-5.0,ypoint-5.0);
739                         }
740                     } else {
741                         fixed(marker_xs + scrn_rect.bottom / 4, height, marker_xs, marker_ys,
742                               marker_xs - scrn_rect.bottom / 4, height);
743                     }
744                 } //if pointer
745             }  //end horizontal scale bottom
746
747             //    if ((options & HUDS_BOTTOM) == HUDS_BOTTOM) {
748             //      marker_xe = marker_ys;
749             //      marker_ys = marker_ye;
750             //      marker_ye = marker_xe;
751             //      }
752
753             // printf("vmin = %d  vmax = %d\n", (int)vmin, (int)vmax);
754
755             //  last = FloatToInt(vmax)+1;
756             //  i    = FloatToInt(vmin);
757
758             if (zoom == 1) {
759                 zoomed_scale((int)vmin,(int)vmax);
760             } else {
761                 //default to zoom=0
762                 last = (int)vmax + 1;
763                 i = (int)vmin;
764                 for (; i < last; i++) {
765                     // for (i = (int)vmin; i <= (int)vmax; i++)     {
766                     // printf("<*> i = %d\n", i);
767                     condition = true;
768                     if (!modulo()) {
769                         if (i < min_val()) {
770                             condition = false;
771                         }
772                     }
773                     // printf("<**> i = %d\n", i);
774                     if (condition) {
775                         // marker_xs = scrn_rect.left + (int)((i - vmin) * factor() + .5);
776                         marker_xs = scrn_rect.left + (((i - vmin) * factor()/*+ .5f*/));
777
778                         if (oddtype == 1)
779                             k = i+1; //enable ticks at odd values
780                         else
781                             k = i;
782
783                         if (div_min()) {
784                             //          if ((i%(int)div_min()) == 0) {
785                             //draw minor ticks
786                             if (!(k%(int)div_min())) {
787                                 // draw in ticks only if they aren't too close to the edge.
788                                 if (((marker_xs - 5) > scrn_rect.left)
789                                         && ((marker_xs + 5)< (scrn_rect.left + scrn_rect.right))) {
790
791                                     if (huds_both(options)) {
792                                         if (tick_length == "variable") {
793                                             drawOneLine(marker_xs, scrn_rect.top,
794                                                         marker_xs, marker_ys - 4);
795                                             drawOneLine(marker_xs, marker_ye + 4,
796                                                         marker_xs, height);
797                                         } else {
798                                             drawOneLine(marker_xs, scrn_rect.top,
799                                                         marker_xs, marker_ys);
800                                             drawOneLine(marker_xs, marker_ye,
801                                                         marker_xs, height);
802                                         }
803                                         // glBegin(GL_LINES);
804                                         // glVertex2f(marker_xs, scrn_rect.top);
805                                         // glVertex2f(marker_xs, marker_ys - 4);
806                                         // glVertex2f(marker_xs, marker_ye + 4);
807                                         // glVertex2f(marker_xs, scrn_rect.top + scrn_rect.bottom);
808                                         // glEnd();
809
810                                     } else {
811                                         if (huds_top(options)) {
812                                             //draw minor ticks
813                                             if (tick_length=="variable")
814                                                 drawOneLine(marker_xs,marker_ys,marker_xs,marker_ye-4);
815                                             else
816                                                 drawOneLine(marker_xs,marker_ys,marker_xs,marker_ye);
817
818                                         } else
819                                             if (tick_length=="variable")
820                                                 drawOneLine(marker_xs,marker_ys+4,marker_xs,marker_ye);
821                                             else
822                                                 drawOneLine(marker_xs,marker_ys,marker_xs,marker_ye);
823                                         }
824                                     }
825                                 } //end draw minor ticks
826                             } //end minor ticks
827
828                             //major ticks
829                             if (div_max()) {
830                                 // printf("i = %d\n", i);
831                                 // if ((i%(int)div_max())==0) {
832                                 //     draw major ticks
833
834                                 if (!(k%(int)div_max())) {
835                                     if (modulo()) {
836                                         disp_val = i % (int) modulo(); // ?????????
837                                         if (disp_val < 0) {
838                                             while (disp_val<0)
839                                                 disp_val += modulo();
840                                         }
841                                     } else {
842                                         disp_val = i;
843                                     }
844                                     // printf("disp_val = %d\n", disp_val);
845                                     // printf("%d\n", (int)(disp_val  * (double)data_scaling() + 0.5));
846                                     lenstr = sprintf(TextScale, "%d",
847                                             // (int)(disp_val  * data_scaling() +.5));
848                                             FloatToInt(disp_val * data_scaling()/*+.5*/));
849
850                                     // Draw major ticks and text only if far enough from the edge.
851                                     if (((marker_xs - 10)> scrn_rect.left)
852                                             && ((marker_xs + 10) < (scrn_rect.left + scrn_rect.right))) {
853                                         if (huds_both(options)) {
854                                             // drawOneLine(marker_xs, scrn_rect.top,
855                                             //              marker_xs, marker_ys);
856                                             // drawOneLine(marker_xs, marker_ye,
857                                             //              marker_xs, scrn_rect.top + scrn_rect.bottom);
858                                             glBegin(GL_LINE_STRIP);
859                                             glVertex2f(marker_xs, scrn_rect.top);
860                                             glVertex2f(marker_xs, marker_ye);
861                                             glVertex2f(marker_xs, height);
862                                             glEnd();
863
864                                             if (!huds_notext(options)) {
865                                                 textString(marker_xs - 4 * lenstr,
866                                                            marker_ys + 4, TextScale, 0);
867                                             }
868                                         } else {
869                                             drawOneLine(marker_xs, marker_ys, marker_xs, marker_ye);
870
871                                         if (!huds_notext(options)) {
872                                             if (huds_top(options)) {
873                                                 textString(marker_xs - 4 * lenstr,
874                                                            height - 10, TextScale, 0);
875
876                                             }  else  {
877                                                 textString(marker_xs - 4 * lenstr,
878                                                            scrn_rect.top, TextScale, 0);
879                                             }
880                                         }
881                                     }
882                                 }
883                             }  //end draw major ticks
884                         } //endif major ticks
885                     }   //end condition
886                 } //end for
887             }  //end zoom
888         } //end horizontal/vertical scale
889     } // end of type tape
890 } //draw
891
892
893
894 void hud_card::circles(float x,float y,float size)
895 {
896     glEnable(GL_POINT_SMOOTH);
897     glPointSize(size);
898
899     glBegin(GL_POINTS);
900     glVertex2f(x,y);
901     glEnd();
902
903     glPointSize(1.0);
904     glDisable(GL_POINT_SMOOTH);
905 }
906
907
908 void hud_card::fixed(float x1, float y1, float x2, float y2, float x3, float y3)
909 {
910     glBegin(GL_LINE_STRIP);
911     glVertex2f(x1, y1);
912     glVertex2f(x2, y2);
913     glVertex2f(x3, y3);
914     glEnd();
915 }
916
917
918 void hud_card::zoomed_scale(int first, int last)
919 {
920     POINT mid_scr    = get_centroid();
921     RECT   scrn_rect = get_location();
922     UINT options     = get_options();
923     char TextScale[80];
924     // int disp_val = 0;
925     int data[80];
926
927     float x,y,w,h,bottom;
928     float cur_value=get_value();
929     if (cur_value > maxValue)
930         cur_value = maxValue;
931     if (cur_value < minValue)
932         cur_value = minValue;
933
934     int a=0;
935
936     while (first <= last) {
937         if ((first % (int)Maj_div) == 0) {
938             data[a] = first;
939             a++ ;
940         }
941         first++;
942     }
943     int centre =a/2;
944
945     if (huds_vert(options)) {
946         x=scrn_rect.left;
947         y=scrn_rect.top;
948         w=scrn_rect.left+scrn_rect.right;
949         h=scrn_rect.top+scrn_rect.bottom;
950         bottom=scrn_rect.bottom;
951
952         float xstart, yfirst, ycentre, ysecond;
953
954         float hgt = bottom * 20.0 /100.0;  // 60% of height should be zoomed
955         yfirst = mid_scr.y - hgt;
956         ycentre = mid_scr.y;
957         ysecond = mid_scr.y + hgt;
958         float range = hgt * 2;
959
960         int i;
961         float factor = range /10.0;
962
963         float hgt1 = bottom * 30.0 /100.0;
964         int  incrs = ((int)val_span - (Maj_div * 2)) / Maj_div ;
965         int  incr = incrs / 2;
966         float factors = hgt1 / incr;
967
968         // begin
969         //this is for moving type pointer
970         static float ycent, ypoint,xpoint;
971         static int wth;
972
973         ycent = mid_scr.y;
974         wth=scrn_rect.left+scrn_rect.right;
975
976         if (cur_value <= data[centre+1])
977             if (cur_value > data[centre]) {
978                 ypoint = ycent + ((cur_value - data[centre]) * hgt/Maj_div);
979             }
980
981         if (cur_value >= data[centre-1])
982             if (cur_value <= data[centre]) {
983                 ypoint = ycent - ((data[centre]-cur_value) * hgt/Maj_div);
984             }
985
986         if (cur_value < data[centre-1])
987             if (cur_value >= minValue) {
988                 float diff  = minValue  - data[centre-1];
989                 float diff1 = cur_value - data[centre-1];
990                 float val = (diff1 * hgt1) / diff;
991
992                 ypoint = ycent - hgt -  val;
993             }
994
995         if (cur_value > data[centre+1])
996             if (cur_value <= maxValue) {
997                 float diff  = maxValue  - data[centre+1];
998                 float diff1 = cur_value - data[centre+1];
999                 float val = (diff1 * hgt1) / diff;
1000
1001                 ypoint = ycent + hgt +  val;
1002             }
1003
1004         if (huds_left(options)) {
1005             xstart = w;
1006
1007             drawOneLine(xstart, ycentre, xstart - 5.0, ycentre); //centre tick
1008
1009             sprintf(TextScale,"%3.0f\n",(float)(data[centre] * data_scaling()));
1010
1011             if (!huds_notext(options)) {
1012                 textString (x, ycentre, TextScale, 0);
1013             }
1014
1015             for (i = 1; i < 5; i++) {
1016                 yfirst  += factor;
1017                 ycentre += factor;
1018                 circles(xstart-2.5,yfirst, 3.0);
1019                 circles(xstart-2.5,ycentre,3.0);
1020             }
1021
1022             yfirst = mid_scr.y - hgt;
1023
1024             for (i = 0; i <= incr; i++) {
1025                 drawOneLine(xstart, yfirst, xstart - 5.0, yfirst);
1026                 drawOneLine(xstart,ysecond, xstart - 5.0,ysecond);
1027
1028                 sprintf(TextScale,"%3.0f\n",(float)(data[centre-i-1] * data_scaling()));
1029
1030                 if (!huds_notext(options))
1031                     textString (x, yfirst, TextScale, 0);
1032
1033                 sprintf(TextScale,"%3.0f\n",(float)(data[centre+i+1] * data_scaling()));
1034
1035                 if (!huds_notext(options))
1036                     textString (x, ysecond, TextScale, 0);
1037
1038                 yfirst    -= factors;
1039                 ysecond   += factors;
1040
1041             }
1042
1043             //to draw moving type pointer for left option
1044             //begin
1045             xpoint = wth + 10.0;
1046
1047             if (pointer_type == "moving") {
1048                 drawOneLine(xpoint,ycent,xpoint,ypoint);
1049                 drawOneLine(xpoint,ypoint,xpoint-10.0,ypoint);
1050                 drawOneLine(xpoint-10.0,ypoint,xpoint-5.0,ypoint+5.0);
1051                 drawOneLine(xpoint-10.0,ypoint,xpoint-5.0,ypoint-5.0);
1052             }
1053             //end
1054
1055         } else {
1056             //huds_right
1057             xstart = (x+w)/2;
1058
1059             drawOneLine(xstart, ycentre, xstart + 5.0, ycentre); //centre tick
1060
1061             sprintf(TextScale,"%3.0f\n",(float)(data[centre] * data_scaling()));
1062
1063             if (!huds_notext(options)) {
1064                 textString (w, ycentre, TextScale, 0);
1065             }
1066
1067             for (i = 1; i < 5; i++) {
1068                 yfirst  += factor;
1069                 ycentre += factor;
1070                 circles(xstart+2.5,yfirst, 3.0);
1071                 circles(xstart+2.5,ycentre,3.0);
1072             }
1073
1074             yfirst = mid_scr.y - hgt;
1075
1076             for (i = 0; i <= incr; i++) {
1077                 drawOneLine(xstart, yfirst, xstart + 5.0, yfirst);
1078                 drawOneLine(xstart,ysecond, xstart + 5.0,ysecond);
1079
1080                 sprintf(TextScale,"%3.0f\n",(float)(data[centre-i-1] * data_scaling()));
1081
1082                 if (!huds_notext(options))
1083                     textString(w, yfirst, TextScale, 0);
1084
1085                 sprintf(TextScale,"%3.0f\n",(float)(data[centre+i+1] * data_scaling()));
1086
1087                 if (!huds_notext(options))
1088                     textString(w, ysecond, TextScale, 0);
1089
1090                 yfirst -= factors;
1091                 ysecond += factors;
1092
1093             }
1094
1095             // to draw moving type pointer for right option
1096             //begin
1097             xpoint = scrn_rect.left;
1098
1099             if (pointer_type == "moving") {
1100                 drawOneLine(xpoint,ycent,xpoint,ypoint);
1101                 drawOneLine(xpoint,ypoint,xpoint+10.0,ypoint);
1102                 drawOneLine(xpoint+10.0,ypoint,xpoint+5.0,ypoint+5.0);
1103                 drawOneLine(xpoint+10.0,ypoint,xpoint+5.0,ypoint-5.0);
1104             }
1105             //end
1106         }//end huds_right /left
1107         //end of vertical scale
1108
1109     } else {
1110         //horizontal scale
1111         x=scrn_rect.left;
1112         y=scrn_rect.top;
1113         w=scrn_rect.left+scrn_rect.right;
1114         h=scrn_rect.top+scrn_rect.bottom;
1115         bottom=scrn_rect.right;
1116
1117         float ystart, xfirst, xcentre, xsecond;
1118
1119         float hgt = bottom * 20.0 /100.0;  // 60% of height should be zoomed
1120         xfirst = mid_scr.x - hgt;
1121         xcentre = mid_scr.x;
1122         xsecond = mid_scr.x + hgt;
1123         float range = hgt * 2;
1124
1125         int i;
1126         float factor = range /10.0;
1127
1128         float hgt1 = bottom * 30.0 /100.0;
1129         int  incrs = ((int)val_span - (Maj_div * 2)) / Maj_div ;
1130         int  incr = incrs / 2;
1131         float factors = hgt1 / incr;
1132
1133
1134         //Code for Moving Type Pointer
1135         //begin
1136         static float xcent,xpoint,ypoint;
1137
1138         xcent = mid_scr.x;
1139
1140         if (cur_value <= data[centre+1])
1141             if (cur_value > data[centre]) {
1142                 xpoint = xcent + ((cur_value - data[centre]) * hgt/Maj_div);
1143             }
1144
1145         if (cur_value >= data[centre-1])
1146             if (cur_value <= data[centre]) {
1147                 xpoint = xcent - ((data[centre]-cur_value) * hgt/Maj_div);
1148             }
1149
1150         if (cur_value < data[centre-1])
1151             if (cur_value >= minValue) {
1152                 float diff  = minValue  - data[centre-1];
1153                 float diff1 = cur_value - data[centre-1];
1154                 float val = (diff1 * hgt1) / diff;
1155
1156                 xpoint = xcent - hgt -  val;
1157             }
1158
1159
1160         if (cur_value > data[centre+1])
1161             if (cur_value <= maxValue) {
1162                 float diff  = maxValue  - data[centre+1];
1163                 float diff1 = cur_value - data[centre+1];
1164                 float val = (diff1 * hgt1) / diff;
1165
1166                 xpoint = xcent + hgt +  val;
1167             }
1168
1169         //end
1170         if (huds_top(options)) {
1171
1172             ystart =h;
1173
1174             drawOneLine(xcentre, ystart, xcentre, ystart - 5.0); //centre tick
1175
1176             sprintf(TextScale,"%3.0f\n",(float)(data[centre] * data_scaling()));
1177
1178             if (!huds_notext(options)) {
1179                 textString (xcentre-10.0, y, TextScale, 0);
1180             }
1181
1182             for (i = 1; i < 5; i++) {
1183                 xfirst  += factor;
1184                 xcentre += factor;
1185                 circles(xfirst,  ystart-2.5, 3.0);
1186                 circles(xcentre, ystart-2.5, 3.0);
1187             }
1188
1189             xfirst = mid_scr.x - hgt;
1190
1191             for (i = 0; i <= incr; i++) {
1192                 drawOneLine(xfirst,  ystart, xfirst,  ystart - 5.0);
1193                 drawOneLine(xsecond, ystart, xsecond, ystart - 5.0);
1194
1195                 sprintf(TextScale,"%3.0f\n",(float)(data[centre-i-1] * data_scaling()));
1196
1197                 if (!huds_notext(options))
1198                     textString (xfirst-10.0, y, TextScale, 0);
1199
1200                 sprintf(TextScale,"%3.0f\n",(float)(data[centre+i+1] * data_scaling()));
1201
1202                 if (!huds_notext(options))
1203                     textString (xsecond-10.0, y, TextScale, 0);
1204
1205
1206                 xfirst -= factors;
1207                 xsecond += factors;
1208             }
1209             //this is for moving pointer for top option
1210             //begin
1211
1212             ypoint = scrn_rect.top + scrn_rect.bottom + 10.0;
1213
1214             if (pointer_type == "moving") {
1215                 drawOneLine(xcent, ypoint,xpoint,ypoint);
1216                 drawOneLine(xpoint,ypoint,xpoint,ypoint-10.0);
1217                 drawOneLine(xpoint,ypoint-10.0,xpoint+5.0,ypoint-5.0);
1218                 drawOneLine(xpoint,ypoint-10.0,xpoint-5.0,ypoint-5.0);
1219             }
1220             //end of top option
1221
1222         } else {
1223             //else huds_bottom
1224             ystart = (y + h) / 2;
1225
1226             //drawOneLine(xstart, yfirst,  xstart - 5.0, yfirst);
1227             drawOneLine(xcentre, ystart, xcentre, ystart + 5.0); //centre tick
1228
1229             sprintf(TextScale,"%3.0f\n",(float)(data[centre] * data_scaling()));
1230
1231             if (!huds_notext(options)) {
1232                 textString (xcentre-10.0, h, TextScale, 0);
1233             }
1234
1235             for (i = 1; i < 5; i++) {
1236                 xfirst  += factor;
1237                 xcentre += factor;
1238                 circles(xfirst,  ystart+2.5, 3.0);
1239                 circles(xcentre, ystart+2.5,3.0);
1240             }
1241
1242             xfirst = mid_scr.x - hgt;
1243
1244             for (i = 0; i <= incr; i++) {
1245                 drawOneLine(xfirst, ystart, xfirst, ystart + 5.0);
1246                 drawOneLine(xsecond,ystart, xsecond,ystart + 5.0);
1247
1248                 sprintf(TextScale,"%3.0f\n",(float)(data[centre-i-1] * data_scaling()));
1249
1250                 if (!huds_notext(options))
1251                     textString (xfirst-10.0,h, TextScale, 0);
1252
1253                 sprintf(TextScale,"%3.0f\n",(float)(data[centre+i+1] * data_scaling()));
1254
1255                 if (!huds_notext(options))
1256                     textString (xsecond-10.0,h, TextScale, 0);
1257
1258
1259                 xfirst -= factors;
1260                 xsecond   += factors;
1261
1262             }
1263             //this is for movimg pointer for bottom option
1264             //begin
1265
1266             ypoint = scrn_rect.top - 10.0;
1267             if (pointer_type == "moving") {
1268                 drawOneLine(xcent, ypoint,xpoint,ypoint);
1269                 drawOneLine(xpoint,ypoint,xpoint,ypoint+10.0);
1270                 drawOneLine(xpoint,ypoint+10.0,xpoint+5.0,ypoint+5.0);
1271                 drawOneLine(xpoint,ypoint+10.0,xpoint-5.0,ypoint+5.0);
1272             }
1273         }//end hud_top or hud_bottom
1274     }  //end of horizontal/vertical scales
1275 }//end draw
1276
1277