GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gsd_objs.c
Go to the documentation of this file.
1 
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <grass/gis.h>
23 #include <grass/ogsf_proto.h>
24 #include <grass/gstypes.h>
25 
26 #include "gsget.h"
27 #include "math.h"
28 #include "rowcol.h"
29 
30 static void init_stuff(void);
31 
35 float Octo[6][3] = {
36  {1.0, 0.0, 0.0},
37  {0.0, 1.0, 0.0},
38  {0.0, 0.0, 1.0},
39  {-1.0, 0.0, 0.0},
40  {0.0, -1.0, 0.0},
41  {0.0, 0.0, -1.0}
42 };
43 
44 #define ONORM .57445626
45 
49 float OctoN[8][3] = {
50  {ONORM, ONORM, ONORM},
51  {-ONORM, ONORM, ONORM},
52  {ONORM, -ONORM, ONORM},
53  {-ONORM, -ONORM, ONORM},
54  {ONORM, ONORM, -ONORM},
55  {-ONORM, ONORM, -ONORM},
56  {ONORM, -ONORM, -ONORM},
57  {-ONORM, -ONORM, -ONORM},
58 };
59 
72 float CubeNormals[3][3] = {
73  {0, -ONORM, 0},
74  {0, 0, ONORM},
75  {ONORM, 0, 0}
76 };
77 
78 float CubeVertices[8][3] = {
79  {-1.0, -1.0, -1.0},
80  {1.0, -1.0, -1.0},
81  {1.0, 1.0, -1.0},
82  {-1.0, 1.0, -1.0},
83  {-1.0, -1.0, 1.0},
84  {1.0, -1.0, 1.0},
85  {1.0, 1.0, 1.0},
86  {-1.0, 1.0, 1.0}
87 };
88 
89 float origin[3] = { 0.0, 0.0, 0.0 };
90 
91 #define UP_NORM Octo[2]
92 #define DOWN_NORM Octo[5]
93 #define ORIGIN origin
94 
98 float ogverts[8][3];
99 
103 float ogvertsplus[8][3];
104 
105 float Pi;
106 
107 static void init_stuff(void)
108 {
109  float cos45;
110  int i;
111  static int first = 1;
112 
113  if (first) {
114  first = 0;
115 
116  cos45 = cos(atan(1.0));
117 
118  for (i = 0; i < 8; i++) {
119  ogverts[i][Z] = 0.0;
120  ogvertsplus[i][Z] = 1.0;
121  }
122 
123  ogverts[0][X] = ogvertsplus[0][X] = 1.0;
124  ogverts[0][Y] = ogvertsplus[0][Y] = 0.0;
125  ogverts[1][X] = ogvertsplus[1][X] = cos45;
126  ogverts[1][Y] = ogvertsplus[1][Y] = cos45;
127  ogverts[2][X] = ogvertsplus[2][X] = 0.0;
128  ogverts[2][Y] = ogvertsplus[2][Y] = 1.0;
129  ogverts[3][X] = ogvertsplus[3][X] = -cos45;
130  ogverts[3][Y] = ogvertsplus[3][Y] = cos45;
131  ogverts[4][X] = ogvertsplus[4][X] = -1.0;
132  ogverts[4][Y] = ogvertsplus[4][Y] = 0.0;
133  ogverts[5][X] = ogvertsplus[5][X] = -cos45;
134  ogverts[5][Y] = ogvertsplus[5][Y] = -cos45;
135  ogverts[6][X] = ogvertsplus[6][X] = 0.0;
136  ogverts[6][Y] = ogvertsplus[6][Y] = -1.0;
137  ogverts[7][X] = ogvertsplus[7][X] = cos45;
138  ogverts[7][Y] = ogvertsplus[7][Y] = -cos45;
139 
140  Pi = 4.0 * atan(1.0);
141  }
142 
143  return;
144 }
145 
153 void gsd_plus(float *center, int colr, float siz)
154 {
155  float v1[3], v2[3];
156 
157  gsd_color_func(colr);
158  siz *= .5;
159 
160  v1[Z] = v2[Z] = center[Z];
161 
162  v1[X] = v2[X] = center[X];
163  v1[Y] = center[Y] - siz;
164  v2[Y] = center[Y] + siz;
165  gsd_bgnline();
166  gsd_vert_func(v1);
167  gsd_vert_func(v2);
168  gsd_endline();
169 
170  v1[Y] = v2[Y] = center[Y];
171  v1[X] = center[X] - siz;
172  v2[X] = center[X] + siz;
173  gsd_bgnline();
174  gsd_vert_func(v1);
175  gsd_vert_func(v2);
176  gsd_endline();
177 
178  return;
179 }
180 
190 void gsd_line_onsurf(geosurf * gs, float *v1, float *v2)
191 {
192  int i, np;
193  Point3 *pts;
194  float fudge;
195 
196  pts = gsdrape_get_segments(gs, v1, v2, &np);
197  if (pts) {
198  fudge = FUDGE(gs);
199  gsd_bgnline();
200 
201  for (i = 0; i < np; i++) {
202  /* ACS */
203  /* reverting back, as it broke displaying X symbol and query line */
204  pts[i][Z] += fudge;
205  /*pts[i][Z] *= fudge;*/
206  gsd_vert_func(pts[i]);
207  }
208 
209  gsd_endline();
210 
211  /* fix Z values? */
212  v1[Z] = pts[0][Z];
213  v2[Z] = pts[np - 1][Z];
214  }
215 
216  return;
217 }
218 
236 int gsd_nline_onsurf(geosurf * gs, float *v1, float *v2, float *pt, int n)
237 {
238  int i, np, pdraw;
239  Point3 *pts;
240  float fudge;
241 
242  pts = gsdrape_get_segments(gs, v1, v2, &np);
243 
244  if (pts) {
245  pdraw = n < np ? n : np;
246  fudge = FUDGE(gs);
247  gsd_bgnline();
248 
249  for (i = 0; i < pdraw; i++) {
250  pts[i][Z] += fudge;
251  gsd_vert_func(pts[i]);
252  }
253 
254  gsd_endline();
255 
256  pt[X] = pts[i - 1][X];
257  pt[Y] = pts[i - 1][Y];
258 
259  /* fix Z values? */
260  v1[Z] = pts[0][Z];
261  v2[Z] = pts[np - 1][Z];
262 
263  return (i);
264  }
265 
266  return (0);
267 }
268 
279 void gsd_x(geosurf * gs, float *center, int colr, float siz)
280 {
281  float v1[3], v2[3];
282 
283  gsd_color_func(colr);
284  siz *= .5;
285 
286  v1[Z] = v2[Z] = center[Z];
287 
288  v1[X] = center[X] - siz;
289  v2[X] = center[X] + siz;
290  v1[Y] = center[Y] - siz;
291  v2[Y] = center[Y] + siz;
292 
293  if (gs) {
294  gsd_line_onsurf(gs, v1, v2);
295  }
296  else {
297  gsd_bgnline();
298  gsd_vert_func(v1);
299  gsd_vert_func(v2);
300  gsd_endline();
301  }
302 
303  v1[X] = center[X] - siz;
304  v2[X] = center[X] + siz;
305  v1[Y] = center[Y] + siz;
306  v2[Y] = center[Y] - siz;
307 
308  if (gs) {
309  gsd_line_onsurf(gs, v1, v2);
310  }
311  else {
312  gsd_bgnline();
313  gsd_vert_func(v1);
314  gsd_vert_func(v2);
315  gsd_endline();
316  }
317 
318  return;
319 }
320 
328 void gsd_diamond(float *center, unsigned long colr, float siz)
329 {
330  int preshade;
331 
332  /* seems right, but isn't
333  siz *= .5;
334  */
335 
336  gsd_pushmatrix();
337  gsd_translate(center[X], center[Y], center[Z]);
338  gsd_scale(siz, siz, siz);
339  preshade = gsd_getshademodel();
340  gsd_shademodel(0); /* want flat shading */
341 
342  gsd_bgnpolygon();
343  gsd_litvert_func(OctoN[0], colr, Octo[0]);
344  gsd_litvert_func(OctoN[0], colr, Octo[1]);
345  gsd_litvert_func(OctoN[0], colr, Octo[2]);
346  gsd_endpolygon();
347 
348  gsd_bgnpolygon();
349  gsd_litvert_func(OctoN[1], colr, Octo[2]);
350  gsd_litvert_func(OctoN[1], colr, Octo[1]);
351  gsd_litvert_func(OctoN[1], colr, Octo[3]);
352  gsd_endpolygon();
353 
354  gsd_bgnpolygon();
355  gsd_litvert_func(OctoN[2], colr, Octo[2]);
356  gsd_litvert_func(OctoN[2], colr, Octo[4]);
357  gsd_litvert_func(OctoN[2], colr, Octo[0]);
358  gsd_endpolygon();
359 
360  gsd_bgnpolygon();
361  gsd_litvert_func(OctoN[3], colr, Octo[2]);
362  gsd_litvert_func(OctoN[3], colr, Octo[3]);
363  gsd_litvert_func(OctoN[3], colr, Octo[4]);
364  gsd_endpolygon();
365 
366  gsd_bgnpolygon();
367  gsd_litvert_func(OctoN[4], colr, Octo[0]);
368  gsd_litvert_func(OctoN[4], colr, Octo[5]);
369  gsd_litvert_func(OctoN[4], colr, Octo[1]);
370  gsd_endpolygon();
371 
372  gsd_bgnpolygon();
373  gsd_litvert_func(OctoN[5], colr, Octo[1]);
374  gsd_litvert_func(OctoN[5], colr, Octo[5]);
375  gsd_litvert_func(OctoN[5], colr, Octo[3]);
376  gsd_endpolygon();
377 
378  gsd_bgnpolygon();
379  gsd_litvert_func(OctoN[6], colr, Octo[5]);
380  gsd_litvert_func(OctoN[6], colr, Octo[0]);
381  gsd_litvert_func(OctoN[6], colr, Octo[4]);
382  gsd_endpolygon();
383 
384  gsd_bgnpolygon();
385  gsd_litvert_func(OctoN[7], colr, Octo[5]);
386  gsd_litvert_func(OctoN[7], colr, Octo[4]);
387  gsd_litvert_func(OctoN[7], colr, Octo[3]);
388  gsd_endpolygon();
389 
390 #ifdef OCT_SHADED
391  {
392  gsd_bgntmesh();
393  gsd_litvert_func(Octo[0], colr, Octo[0]);
394  gsd_litvert_func(Octo[1], colr, Octo[1]);
395  gsd_swaptmesh();
396  gsd_litvert_func(Octo[2], colr, Octo[2]);
397  gsd_swaptmesh();
398  gsd_litvert_func(Octo[4], colr, Octo[4]);
399  gsd_swaptmesh();
400  gsd_litvert_func(Octo[5], colr, Octo[5]);
401  gsd_swaptmesh();
402  gsd_litvert_func(Octo[1], colr, Octo[1]);
403  gsd_litvert_func(Octo[3], colr, Octo[3]);
404  gsd_litvert_func(Octo[2], colr, Octo[2]);
405  gsd_swaptmesh();
406  gsd_litvert_func(Octo[4], colr, Octo[4]);
407  gsd_swaptmesh();
408  gsd_litvert_func(Octo[5], colr, Octo[5]);
409  gsd_swaptmesh();
410  gsd_litvert_func(Octo[1], colr, Octo[1]);
411  gsd_endtmesh();
412  }
413 #endif
414 
415  gsd_popmatrix();
416  gsd_shademodel(preshade);
417 
418  return;
419 }
420 
430 void gsd_cube(float *center, unsigned long colr, float siz)
431 {
432  int preshade;
433 
434  /* see gsd_diamond() "seems right, but isn't" */
435  siz *= .5;
436 
437  gsd_pushmatrix();
438  gsd_translate(center[X], center[Y], center[Z]);
439  gsd_scale(siz, siz, siz);
440  preshade = gsd_getshademodel();
441  gsd_shademodel(0); /* want flat shading */
442 
443 
444  /* N wall: */
445  gsd_bgnpolygon();
450  gsd_endpolygon();
451 
452  /* S wall: */
453  gsd_bgnpolygon();
458  gsd_endpolygon();
459 
460  /* E wall: */
461  gsd_bgnpolygon();
466  gsd_endpolygon();
467 
468  /* W wall: */
469  gsd_bgnpolygon();
474  gsd_endpolygon();
475 
476  /* lower wall: */
477  gsd_bgnpolygon();
482  gsd_endpolygon();
483 
484  /* top wall: */
485  gsd_bgnpolygon();
490  gsd_endpolygon();
491 
492  gsd_popmatrix();
493  gsd_shademodel(preshade);
494 
495  return;
496 }
497 
507 void gsd_draw_box(float *center, unsigned long colr, float siz)
508 {
509 
510  /* see gsd_diamond() "seems right, but isn't" */
511  siz *= .5;
512 
513  gsd_pushmatrix();
514  gsd_translate(center[X], center[Y], center[Z]);
515  gsd_scale(siz, siz, siz);
516  gsd_color_func(colr);
517 
518  gsd_bgnline(); /* N wall */
524  gsd_endline();
525 
526  gsd_bgnline(); /* S wall */
532  gsd_endline();
533 
534  gsd_bgnline();
537  gsd_endline();
538 
539  gsd_bgnline();
542  gsd_endline();
543 
544  gsd_bgnline();
547  gsd_endline();
548 
549  gsd_bgnline();
552  gsd_endline();
553 
554  gsd_popmatrix();
555 
556  return;
557 }
558 
566 void gsd_drawsphere(float *center, unsigned long colr, float siz)
567 {
568  siz *= .5; /* siz is diameter, gsd_sphere uses radius */
569  gsd_color_func(colr);
570  gsd_sphere(center, siz);
571 
572  return;
573 }
574 
579 {
580  gsd_bgnline();
581  gsd_vert_func(Octo[0]);
582  gsd_vert_func(Octo[3]);
583  gsd_endline();
584 
585  gsd_bgnline();
586  gsd_vert_func(Octo[1]);
587  gsd_vert_func(Octo[4]);
588  gsd_endline();
589 
590  gsd_bgnline();
591  gsd_vert_func(Octo[2]);
592  gsd_vert_func(Octo[5]);
593  gsd_endline();
594 
595  return;
596 }
597 
605 void gsd_draw_asterisk(float *center, unsigned long colr, float siz)
606 {
607  float angle;
608 
609  angle = 45.; /* degrees */
610 
611  gsd_pushmatrix();
612  gsd_translate(center[X], center[Y], center[Z]);
613  gsd_scale(siz, siz, siz);
614  gsd_color_func(colr);
615 
617 
618  gsd_pushmatrix();
619  gsd_rot(angle, 'x');
621  gsd_popmatrix();
622 
623  gsd_pushmatrix();
624  gsd_rot(-angle, 'x');
626  gsd_popmatrix();
627 
628  gsd_pushmatrix();
629  gsd_rot(angle, 'y');
631  gsd_popmatrix();
632 
633  gsd_pushmatrix();
634  gsd_rot(-angle, 'y');
636  gsd_popmatrix();
637 
638  gsd_pushmatrix();
639  gsd_rot(angle, 'z');
641  gsd_popmatrix();
642 
643  gsd_pushmatrix();
644  gsd_rot(-angle, 'z');
646  gsd_popmatrix();
647 
648  gsd_popmatrix();
649 
650  return;
651 }
652 
660 void gsd_draw_gyro(float *center, unsigned long colr, float siz)
661 {
662  int i;
663 
664  gsd_pushmatrix();
665  gsd_translate(center[X], center[Y], center[Z]);
666  gsd_scale(siz, siz, siz);
667  gsd_color_func(colr);
668 
669  /* vert axis */
670  gsd_bgnline();
671  gsd_vert_func(Octo[2]);
672  gsd_vert_func(Octo[5]);
673  gsd_endline();
674 
675  /* spokes */
676  gsd_pushmatrix();
677 
678  for (i = 0; i < 6; i++) {
679  gsd_rot(30., 'z');
680  gsd_bgnline();
681  gsd_vert_func(Octo[0]);
682  gsd_vert_func(Octo[3]);
683  gsd_endline();
684  }
685 
686  gsd_popmatrix();
687 
688  gsd_color_func(colr);
689 
690  gsd_circ(0., 0., 1.);
691 
692  gsd_pushmatrix();
693  gsd_rot(90., 'x');
694  gsd_circ(0., 0., 1.);
695  gsd_popmatrix();
696 
697  gsd_pushmatrix();
698  gsd_rot(90., 'y');
699  gsd_circ(0., 0., 1.);
700  gsd_popmatrix();
701 
702  gsd_popmatrix();
703 
704  return;
705 }
706 
712 void gsd_3dcursor(float *pt)
713 {
714  float big, vert[3];
715 
716  big = 10000.;
717 
718  gsd_bgnline();
719  vert[X] = pt[X];
720  vert[Y] = pt[Y];
721  vert[Z] = big;
722  gsd_vert_func(vert);
723  vert[Z] = -big;
724  gsd_vert_func(vert);
725  gsd_endline();
726 
727  gsd_bgnline();
728  vert[X] = pt[X];
729  vert[Z] = pt[Z];
730  vert[Y] = big;
731  gsd_vert_func(vert);
732  vert[Y] = -big;
733  gsd_vert_func(vert);
734  gsd_endline();
735 
736  gsd_bgnline();
737  vert[Y] = pt[Y];
738  vert[Z] = pt[Z];
739  vert[X] = big;
740  gsd_vert_func(vert);
741  vert[X] = -big;
742  gsd_vert_func(vert);
743  gsd_endline();
744 
745  return;
746 }
747 
756 void dir_to_slope_aspect(float *dir, float *slope, float *aspect, int degrees)
757 {
758  float dx, dy, dz;
759  float costheta, theta, adjacent;
760 
761  dx = dir[X];
762  dy = dir[Y];
763  dz = dir[Z];
764 
765  /* project vector <dx,dy,dz> onto plane of constant z containing
766  * final value should be 0.0 to 3600.0 */
767  if (dx == 0 && dy == 0) {
768  *aspect = 0.;
769  }
770  else {
771  if (dx == 0) {
772  theta = 90.0;
773  }
774  else {
775  costheta = dx / sqrt(dx * dx + dy * dy);
776  theta = acos(costheta);
777  }
778 
779  if (dy < 0) {
780  theta = (2 * Pi) - theta;
781  }
782 
783  *aspect = theta;
784  }
785 
786  /* project vector <dx,dy,dz> onto plane of constant y containing
787  * final value should be -900.0 (looking up) to 900.0 (looking down) */
788  if (dz == 0) {
789  theta = 0.0;
790  }
791  else if (dx == 0 && dy == 0) {
792  theta = Pi / 2.;
793  }
794  else {
795  adjacent = sqrt(dx * dx + dy * dy);
796  costheta = adjacent / sqrt(adjacent * adjacent + dz * dz);
797  theta = acos(costheta);
798  }
799 
800  if (dz > 0) {
801  theta = -theta;
802  }
803 
804  *slope = theta;
805 
806  if (degrees) {
807  *aspect = *aspect * (180. / Pi);
808  *slope = *slope * (180. / Pi);
809  }
810 
811  return;
812 }
813 
814 
826 int gsd_north_arrow(float *pos2, float len, GLuint fontbase,
827  unsigned long arw_clr, unsigned long text_clr)
828 {
829  const char *txt;
830  float v[4][3];
831  float base[3][3];
832  float Ntop[] = { 0.0, 0.0, 1.0 };
833 
834  base[0][Z] = base[1][Z] = base[2][Z] = pos2[Z];
835  v[0][Z] = v[1][Z] = v[2][Z] = v[3][Z] = pos2[Z];
836 
837  base[0][X] = pos2[X] - len / 16.;
838  base[1][X] = pos2[X] + len / 16.;
839  base[0][Y] = base[1][Y] = pos2[Y] - len / 2.;
840  base[2][X] = pos2[X];
841  base[2][Y] = pos2[Y] + .45 * len;
842 
843  v[0][X] = v[2][X] = pos2[X];
844  v[1][X] = pos2[X] + len / 8.;
845  v[3][X] = pos2[X] - len / 8.;
846  v[0][Y] = pos2[Y] + .2 * len;
847  v[1][Y] = v[3][Y] = pos2[Y] + .1 * len;
848  v[2][Y] = pos2[Y] + .5 * len;
849 
850  /* make sure we are drawing in front buffer */
851  GS_set_draw(GSD_FRONT);
852 
853  gsd_pushmatrix();
854  gsd_do_scale(1);
855 
856  glNormal3fv(Ntop);
857  gsd_color_func(arw_clr);
858 
859  gsd_bgnpolygon();
860  glVertex3fv(base[0]);
861  glVertex3fv(base[1]);
862  glVertex3fv(base[2]);
863  gsd_endpolygon();
864 
865  gsd_bgnpolygon();
866  glVertex3fv(v[0]);
867  glVertex3fv(v[1]);
868  glVertex3fv(v[2]);
869  glVertex3fv(v[0]);
870  gsd_endpolygon();
871 
872  gsd_bgnpolygon();
873  glVertex3fv(v[0]);
874  glVertex3fv(v[2]);
875  glVertex3fv(v[3]);
876  glVertex3fv(v[0]);
877  gsd_endpolygon();
878 
879  /* draw N for North */
880  /* Need to pick a nice generic font */
881  /* TODO -- project text position off arrow
882  * bottom along azimuth
883  */
884 
885  gsd_color_func(text_clr);
886  txt = "North";
887  /* adjust position of N text */
888  base[0][X] -= gsd_get_txtwidth(txt, 18) - 20.;
889  base[0][Y] -= gsd_get_txtheight(18) - 20.;
890 
891  glRasterPos3fv(base[0]);
892  glListBase(fontbase);
893  glCallLists(strlen(txt), GL_UNSIGNED_BYTE, (const GLvoid *)txt);
894  GS_done_draw();
895 
896  gsd_popmatrix();
897  gsd_flush();
898 
899  return (1);
900 
901 }
902 
922 int gsd_arrow(float *center, unsigned long colr, float siz, float *dir,
923  float sz, geosurf * onsurf)
924 {
925  float slope, aspect;
926  float tmp[3];
927  static int first = 1;
928 
929  if (first) {
930  init_stuff();
931  first = 0;
932  }
933 
934  dir[Z] /= sz;
935 
936  GS_v3norm(dir);
937 
938  if (NULL != onsurf) {
939  float base[3], tip[3], len;
940 
941  base[X] = center[X];
942  base[Y] = center[Y];
943 
944  /* project dir to surface, after zexag */
945  len = GS_P2distance(ORIGIN, dir); /* in case dir isn't normalized */
946  tip[X] = center[X] + dir[X] * len * siz;
947  tip[Y] = center[Y] + dir[Y] * len * siz;
948 
949  return gsd_arrow_onsurf(base, tip, colr, 2, onsurf);
950  }
951 
952  dir_to_slope_aspect(dir, &slope, &aspect, 1);
953 
954  gsd_pushmatrix();
955  gsd_translate(center[X], center[Y], center[Z]);
956  gsd_scale(1.0, 1.0, 1.0 / sz);
957  gsd_rot(aspect + 90, 'z');
958  gsd_rot(slope + 90., 'x');
959  gsd_scale(siz, siz, siz);
960  gsd_color_func(colr);
961 
962  tmp[X] = 0.2;
963  tmp[Y] = 0.0;
964  tmp[Z] = 0.65;
965 
966  gsd_bgnline();
969  gsd_endline();
970 
971  gsd_bgnline();
972  gsd_vert_func(tmp);
974  tmp[X] = -0.2;
975  gsd_vert_func(tmp);
976  gsd_endline();
977 
978  gsd_popmatrix();
979 
980  return (1);
981 }
982 
994 int gsd_arrow_onsurf(float *base, float *tip, unsigned long colr, int wid,
995  geosurf * gs)
996 {
997  static int first = 1;
998 
999  if (first) {
1000  init_stuff();
1001  first = 0;
1002  }
1003 
1004  gsd_linewidth(wid);
1005  gsd_color_func(colr);
1006 
1007  G_debug(3, "gsd_arrow_onsurf");
1008  G_debug(3, " %f %f -> %f %f", base[X], base[Y], tip[X], tip[Y]);
1009 
1010  gsd_line_onsurf(gs, base, tip);
1011 
1012 #ifdef DO_SPHERE_BASE
1013  {
1014  GS_v3dir(tip, base, dir0);
1015  GS_v3mag(dir0, &len);
1016  gsd_disc(base[X], base[Y], len / 10.);
1017  }
1018 #endif
1019 
1020 #ifdef ARROW_READY
1021  {
1022  base[Z] = tip[Z] = 0.0;
1023  GS_v3dir(tip, base, dir0);
1024 
1025  G_debug(3, " dir0: %f %f %f", dir0[X], dir0[Y], dir0[Z]);
1026 
1027  /* rotate this direction 90 degrees */
1028  GS_v3cross(dir0, UP_NORM, dir2);
1029  GS_v3mag(dir0, &len);
1030  GS_v3eq(dir1, dir0);
1031 
1032  G_debug(3, " len: %f", len);
1033  G_debug(3, " a-dir1: %f %f %f", dir1[X], dir1[Y], dir1[Z]);
1034  G_debug(3, " a-dir2: %f %f %f", dir2[X], dir2[Y], dir2[Z]);
1035 
1036  dim1 = len * .7;
1037  dim2 = len * .2;
1038  GS_v3mult(dir1, dim1);
1039  GS_v3mult(dir2, dim2);
1040 
1041  G_debug(3, " b-dir1: %f %f %f", dir1[X], dir1[Y], dir1[Z]);
1042  G_debug(3, " b-dir2: %f %f %f", dir2[X], dir2[Y], dir2[Z]);
1043 
1044  GS_v3eq(tmp, base);
1045  GS_v3add(tmp, dir1);
1046  GS_v3add(tmp, dir2);
1047 
1048  G_debug(3, " %f %f -> ", tmp[X], tmp[Y]);
1049 
1050  gsd_line_onsurf(gs, tmp, tip);
1051 
1052  GS_v3cross(dir0, DOWN_NORM, dir2);
1053  GS_v3mult(dir2, dim2);
1054  GS_v3eq(tmp, base);
1055 
1056  G_debug(3, " dir1: %f %f %f", dir1[X], dir1[Y], dir1[Z]);
1057  G_debug(3, " dir2: %f %f %f", dir2[X], dir2[Y], dir2[Z]);
1058 
1059  GS_v3add(tmp, dir1);
1060  GS_v3add(tmp, dir2);
1061 
1062  G_debug(3, " %f %f", tmp[X], tmp[Y]);
1063 
1064  gsd_line_onsurf(gs, tip, tmp);
1065  }
1066 #endif
1067 
1068  return (0);
1069 }
1070 
1081 void gsd_3darrow(float *center, unsigned long colr, float siz1, float siz2,
1082  float *dir, float sz)
1083 {
1084  float slope, aspect;
1085  int preshade;
1086  static int first = 1;
1087  static int list;
1088  static int debugint = 1;
1089 
1090  dir[Z] /= sz;
1091 
1092  GS_v3norm(dir);
1093  dir_to_slope_aspect(dir, &slope, &aspect, 1);
1094 
1095  if (debugint > 100) {
1096  G_debug(3, "gsd_3darrow()");
1097  G_debug(3, " pt: %f,%f,%f dir: %f,%f,%f slope: %f aspect: %f",
1098  center[X], center[Y], center[Z], dir[X], dir[Y], dir[Z],
1099  slope, aspect);
1100  debugint = 1;
1101  }
1102  debugint++;
1103 
1104  preshade = gsd_getshademodel();
1105 
1106  /*
1107  gsd_shademodel(0);
1108  want flat shading? */
1109  gsd_pushmatrix();
1110  gsd_translate(center[X], center[Y], center[Z]);
1111  gsd_scale(1.0, 1.0, 1.0 / sz);
1112  gsd_rot(aspect + 90, 'z');
1113  gsd_rot(slope + 90., 'x');
1114  gsd_scale(siz2, siz2, siz1);
1115  gsd_color_func(colr);
1116 
1117  if (first) {
1118  /* combine these into an object */
1119  first = 0;
1120  list = gsd_makelist();
1121  gsd_bgnlist(list, 1);
1122  gsd_backface(1);
1123 
1124  gsd_pushmatrix();
1125  gsd_scale(.10, .10, .75); /* narrow cyl */
1126  primitive_cylinder(colr, 0);
1127  gsd_popmatrix();
1128 
1129  gsd_pushmatrix();
1130  gsd_translate(0.0, 0.0, .60);
1131  gsd_scale(0.3, 0.3, 0.4); /* cone */
1132  primitive_cone(colr);
1133  gsd_popmatrix();
1134 
1135  gsd_backface(0);
1136  gsd_endlist();
1137  }
1138  else {
1139  gsd_calllist(list);
1140  }
1141 
1142  gsd_popmatrix();
1143  gsd_shademodel(preshade);
1144 
1145  return;
1146 }
1147 
1160 int gsd_scalebar(float *pos2, float len, GLuint fontbase,
1161  unsigned long bar_clr, unsigned long text_clr)
1162 {
1163  char txt[100];
1164  float base[4][3];
1165  float Ntop[] = { 0.0, 0.0, 1.0 };
1166 
1167 
1168  base[0][Z] = base[1][Z] = base[2][Z] = base[3][Z] = pos2[Z];
1169 
1170  /* simple 1:8 rectangle *//* bump to X/20. for a 1:10 narrower bar? */
1171  base[0][X] = base[1][X] = pos2[X] - len / 2.;
1172  base[2][X] = base[3][X] = pos2[X] + len / 2.;
1173 
1174  base[0][Y] = base[3][Y] = pos2[Y] - len / 16.;
1175  base[1][Y] = base[2][Y] = pos2[Y] + len / 16.;
1176 
1177  /* make sure we are drawing in front buffer */
1178  GS_set_draw(GSD_FRONT);
1179 
1180  gsd_pushmatrix();
1181  gsd_do_scale(1); /* get map scale factor */
1182 
1183  glNormal3fv(Ntop);
1184 
1185  gsd_color_func(bar_clr);
1186 
1187  gsd_bgnpolygon();
1188  glVertex3fv(base[0]);
1189  glVertex3fv(base[1]);
1190  glVertex3fv(base[2]);
1191  glVertex3fv(base[3]);
1192  glVertex3fv(base[0]);
1193  gsd_endpolygon();
1194 
1195  /* draw units */
1196  /* Need to pick a nice generic font */
1197  /* TODO -- project text position off bar bottom along azimuth */
1198 
1199  gsd_color_func(text_clr);
1200 
1201  /* format text in a nice way */
1202  if (strcmp("meters", G_database_unit_name(TRUE)) == 0) {
1203  if (len > 2500)
1204  sprintf(txt, "%g km", len / 1000);
1205  else
1206  sprintf(txt, "%g meters", len);
1207  }
1208  else if (strcmp("feet", G_database_unit_name(TRUE)) == 0) {
1209  if (len > 5280)
1210  sprintf(txt, "%g miles", len / 5280);
1211  else if (len == 5280)
1212  sprintf(txt, "1 mile");
1213  else
1214  sprintf(txt, "%g feet", len);
1215  }
1216  else {
1217  sprintf(txt, "%g %s", len, G_database_unit_name(TRUE));
1218  }
1219 
1220  /* adjust position of text (In map units?!) */
1221  base[0][X] -= gsd_get_txtwidth(txt, 18) - 20.;
1222  base[0][Y] -= gsd_get_txtheight(18) - 20.;
1223 
1224 
1225  glRasterPos3fv(base[0]);
1226  glListBase(fontbase);
1227  glCallLists(strlen(txt), GL_BYTE, (GLubyte *) txt);
1228  GS_done_draw();
1229 
1230  gsd_popmatrix();
1231  gsd_flush();
1232 
1233  return (1);
1234 }
1235 
1243 void primitive_cone(unsigned long col)
1244 {
1245  float tip[3];
1246  static int first = 1;
1247 
1248  if (first) {
1249  init_stuff();
1250  first = 0;
1251  }
1252 
1253  tip[X] = tip[Y] = 0.0;
1254  tip[Z] = 1.0;
1255 
1256  gsd_bgntfan();
1257  gsd_litvert_func2(UP_NORM, col, tip);
1258  gsd_litvert_func2(ogverts[0], col, ogverts[0]);
1259  gsd_litvert_func2(ogverts[1], col, ogverts[1]);
1260  gsd_litvert_func2(ogverts[2], col, ogverts[2]);
1261  gsd_litvert_func2(ogverts[3], col, ogverts[3]);
1262  gsd_litvert_func2(ogverts[4], col, ogverts[4]);
1263  gsd_litvert_func2(ogverts[5], col, ogverts[5]);
1264  gsd_litvert_func2(ogverts[6], col, ogverts[6]);
1265  gsd_litvert_func2(ogverts[7], col, ogverts[7]);
1266  gsd_litvert_func2(ogverts[0], col, ogverts[0]);
1267  gsd_endtfan();
1268 
1269  return;
1270 }
1271 
1280 void primitive_cylinder(unsigned long col, int caps)
1281 {
1282  static int first = 1;
1283 
1284  if (first) {
1285  init_stuff();
1286  first = 0;
1287  }
1288 
1289  gsd_bgnqstrip();
1290  gsd_litvert_func2(ogverts[0], col, ogvertsplus[0]);
1291  gsd_litvert_func2(ogverts[0], col, ogverts[0]);
1292  gsd_litvert_func2(ogverts[1], col, ogvertsplus[1]);
1293  gsd_litvert_func2(ogverts[1], col, ogverts[1]);
1294  gsd_litvert_func2(ogverts[2], col, ogvertsplus[2]);
1295  gsd_litvert_func2(ogverts[2], col, ogverts[2]);
1296  gsd_litvert_func2(ogverts[3], col, ogvertsplus[3]);
1297  gsd_litvert_func2(ogverts[3], col, ogverts[3]);
1298  gsd_litvert_func2(ogverts[4], col, ogvertsplus[4]);
1299  gsd_litvert_func2(ogverts[4], col, ogverts[4]);
1300  gsd_litvert_func2(ogverts[5], col, ogvertsplus[5]);
1301  gsd_litvert_func2(ogverts[5], col, ogverts[5]);
1302  gsd_litvert_func2(ogverts[6], col, ogvertsplus[6]);
1303  gsd_litvert_func2(ogverts[6], col, ogverts[6]);
1304  gsd_litvert_func2(ogverts[7], col, ogvertsplus[7]);
1305  gsd_litvert_func2(ogverts[7], col, ogverts[7]);
1306  gsd_litvert_func2(ogverts[0], col, ogvertsplus[0]);
1307  gsd_litvert_func2(ogverts[0], col, ogverts[0]);
1308  gsd_endqstrip();
1309 
1310  if (caps) {
1311  /* draw top */
1312  gsd_bgntfan();
1323  gsd_endtfan();
1324 
1325  /* draw bottom */
1326  gsd_bgntfan();
1337  gsd_endtfan();
1338  }
1339 
1340  return;
1341 }
1342 
1343 /*** ACS_MODIFY_BEGIN - sites_attribute management ********************************/
1344 /*
1345  Draws boxes that are used for histograms by gpd_obj function in gpd.c
1346  for site_attribute management
1347  */
1348 
1352 float Box[8][3] =
1353  { {1.0, 1.0, -1.0}, {-1.0, 1.0, -1.0}, {-1.0, 1.0, 1.0}, {1.0, 1.0, 1.0},
1354 {1.0, -1.0, -1.0}, {-1.0, -1.0, -1.0}, {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}
1355 };
1356 
1357 float BoxN[6][3] =
1358  { {0, 0, -ONORM}, {0, 0, ONORM}, {0, ONORM, 0}, {0, -ONORM, 0}, {ONORM, 0,
1359  0},
1360 {-ONORM, 0, 0}
1361 };
1362 
1372 void gsd_box(float *center, int colr, float *siz)
1373 {
1374  int preshade;
1375 
1376  gsd_pushmatrix();
1377  gsd_translate(center[X], center[Y], center[Z] + siz[2]);
1378  gsd_scale(siz[0], siz[1], siz[2]);
1379  preshade = gsd_getshademodel();
1380  gsd_shademodel(0); /* want flat shading */
1381 
1382  /* Top */
1383  gsd_bgnpolygon();
1384  gsd_litvert_func(BoxN[2], colr, Box[0]);
1385  gsd_litvert_func(BoxN[2], colr, Box[1]);
1386  gsd_litvert_func(BoxN[2], colr, Box[2]);
1387  gsd_litvert_func(BoxN[2], colr, Box[3]);
1388  gsd_endpolygon();
1389 
1390  /* Bottom */
1391  gsd_bgnpolygon();
1392  gsd_litvert_func(BoxN[3], colr, Box[7]);
1393  gsd_litvert_func(BoxN[3], colr, Box[6]);
1394  gsd_litvert_func(BoxN[3], colr, Box[5]);
1395  gsd_litvert_func(BoxN[3], colr, Box[4]);
1396  gsd_endpolygon();
1397 
1398  /* Right */
1399  gsd_bgnpolygon();
1400  gsd_litvert_func(BoxN[4], colr, Box[0]);
1401  gsd_litvert_func(BoxN[4], colr, Box[3]);
1402  gsd_litvert_func(BoxN[4], colr, Box[7]);
1403  gsd_litvert_func(BoxN[4], colr, Box[4]);
1404  gsd_endpolygon();
1405 
1406  /* Left */
1407  gsd_bgnpolygon();
1408  gsd_litvert_func(BoxN[5], colr, Box[1]);
1409  gsd_litvert_func(BoxN[5], colr, Box[5]);
1410  gsd_litvert_func(BoxN[5], colr, Box[6]);
1411  gsd_litvert_func(BoxN[5], colr, Box[2]);
1412  gsd_endpolygon();
1413 
1414  /* Front */
1415  gsd_bgnpolygon();
1416  gsd_litvert_func(BoxN[0], colr, Box[0]);
1417  gsd_litvert_func(BoxN[0], colr, Box[4]);
1418  gsd_litvert_func(BoxN[0], colr, Box[5]);
1419  gsd_litvert_func(BoxN[0], colr, Box[1]);
1420  gsd_endpolygon();
1421 
1422  /* Back */
1423  gsd_bgnpolygon();
1424  gsd_litvert_func(BoxN[1], colr, Box[3]);
1425  gsd_litvert_func(BoxN[1], colr, Box[2]);
1426  gsd_litvert_func(BoxN[1], colr, Box[6]);
1427  gsd_litvert_func(BoxN[1], colr, Box[7]);
1428  gsd_endpolygon();
1429 
1430  gsd_popmatrix();
1431  gsd_shademodel(preshade);
1432  return;
1433 }
1434 
1435 /*** ACS_MODIFY_END - sites_attribute management ********************************/