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