BRL-CAD
plot3.h
Go to the documentation of this file.
1 /* P L O T 3 . H
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2024 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup plot3
21  *
22  * @brief A public-domain UNIX plot library, for 2-D and 3-D plotting
23  * in 16-bit VAX signed integer spaces, or 64-bit IEEE floating point.
24  *
25  * These routines generate "UNIX plot" output (with the addition of
26  * 3-D commands). They behave almost exactly like the regular libplot
27  * routines, except:
28  *
29  * -# These all take a stdio file pointer, and can thus be used to
30  * create multiple plot files simultaneously.
31  * -# There are 3-D versions of most commands.
32  * -# There are IEEE floating point versions of the commands.
33  * -# The names have been changed.
34  *
35  * The 3-D extensions are those of Doug Gwyn, from his System V
36  * extensions.
37  *
38  * These are the ascii command letters allocated to various actions.
39  * Care has been taken to consistently match lowercase and uppercase
40  * letters.
41  *
42  * @code
43  2d 3d 2df 3df
44  space s S w W
45  move m M o O
46  cont n N q Q
47  point p P x X
48  line l L v V
49  circle c i
50  arc a r
51  linmod f
52  label t
53  erase e
54  color C
55  flush F
56 
57  bd gh jk uyz
58  ABDEGHIJKRTUYZ
59 
60  @endcode
61  *
62  * The calling sequence is the same as the original Bell Labs routines, with
63  * the exception of the pl_ prefix on the name.
64  *
65  * NOTE: from libbv's perspective, plot3.h is a stand-alone header that does
66  * not use any other library functionality. To use this header without libbv,
67  * define PLOT3_IMPLEMENTATION before including the plot3.h header.
68  *
69  * Of interest: the Plan 9 sources (recently MIT licensed) appear to be
70  * related to the original code that would have formed the conceptual basis for
71  * these routines:
72  *
73  * https://plan9.io/sources/plan9/sys/src/cmd/plot/libplot/
74  *
75  * Don't know if there would be any improvements that could be retrofitted onto
76  * this version, but might be worth looking. In particular, curious if the
77  * spline routine might be useful...
78  */
79 /** @{ */
80 /** @file plot3.h */
81 
82 #ifndef PLOT3_H
83 #define PLOT3_H
84 
85 #include "common.h"
86 
87 #include "vmath.h"
88 #include "bu/color.h"
89 #include "bu/file.h"
90 
91 #ifndef PLOT3_EXPORT
92 # if defined(PLOT3_DLL_EXPORTS) && defined(PLOT3_DLL_IMPORTS)
93 # error "Only PLOT3_DLL_EXPORTS or PLOT3_DLL_IMPORTS can be defined, not both."
94 # elif defined(PLOT3_DLL_EXPORTS)
95 # define PLOT3_EXPORT COMPILER_DLLEXPORT
96 # elif defined(PLOT3_DLL_IMPORTS)
97 # define PLOT3_EXPORT COMPILER_DLLIMPORT
98 # else
99 # define PLOT3_EXPORT
100 # endif
101 #endif
102 
103 __BEGIN_DECLS
104 #define PL_OUTPUT_MODE_BINARY 0
105 #define PL_OUTPUT_MODE_TEXT 1
106 
107 #if !defined(PLOT_PREFIX_STR)
108 # define PLOT_PREFIX_STR plot3_
109 #endif
110 #define PL_CONCAT2(a, b) a ## b
111 #define PL_CONCAT(a, b) PL_CONCAT2(a,b)
112 #define PL_ADD_PREFIX(b) PL_CONCAT(PLOT_PREFIX_STR,b)
113 
114 /* All linked symbols */
115 #define pd_3box PL_ADD_PREFIX(pd_3box)
116 #define pd_3cont PL_ADD_PREFIX(pd_3cont)
117 #define pd_3line PL_ADD_PREFIX(pd_3line)
118 #define pd_3move PL_ADD_PREFIX(pd_3move)
119 #define pd_3point PL_ADD_PREFIX(pd_3point)
120 #define pd_3space PL_ADD_PREFIX(pd_3space)
121 #define pd_arc PL_ADD_PREFIX(pd_arc)
122 #define pd_box PL_ADD_PREFIX(pd_box)
123 #define pd_circle PL_ADD_PREFIX(pd_circle)
124 #define pd_cont PL_ADD_PREFIX(pd_cont)
125 #define pd_line PL_ADD_PREFIX(pd_line)
126 #define pd_move PL_ADD_PREFIX(pd_move)
127 #define pd_point PL_ADD_PREFIX(pd_point)
128 #define pd_space PL_ADD_PREFIX(pd_space)
129 #define pdv_3box PL_ADD_PREFIX(pdv_3box)
130 #define pdv_3cont PL_ADD_PREFIX(pdv_3cont)
131 #define pdv_3line PL_ADD_PREFIX(pdv_3line)
132 #define pdv_3move PL_ADD_PREFIX(pdv_3move)
133 #define pdv_3point PL_ADD_PREFIX(pdv_3point)
134 #define pdv_3ray PL_ADD_PREFIX(pdv_3ray)
135 #define pdv_3space PL_ADD_PREFIX(pdv_3space)
136 #define pl_3box PL_ADD_PREFIX(pl_3box)
137 #define pl_3cont PL_ADD_PREFIX(pl_3cont)
138 #define pl_3line PL_ADD_PREFIX(pl_3line)
139 #define pl_3move PL_ADD_PREFIX(pl_3move)
140 #define pl_3point PL_ADD_PREFIX(pl_3point)
141 #define pl_3space PL_ADD_PREFIX(pl_3space)
142 #define pl_arc PL_ADD_PREFIX(pl_arc)
143 #define pl_box PL_ADD_PREFIX(pl_box)
144 #define pl_circle PL_ADD_PREFIX(pl_circle)
145 #define pl_color PL_ADD_PREFIX(pl_color)
146 #define pl_color_buc PL_ADD_PREFIX(pl_color_buc)
147 #define pl_cont PL_ADD_PREFIX(pl_cont)
148 #define pl_erase PL_ADD_PREFIX(pl_erase)
149 #define pl_flush PL_ADD_PREFIX(pl_flush)
150 #define pl_getOutputMode PL_ADD_PREFIX(pl_getOutputMode)
151 #define pl_label PL_ADD_PREFIX(pl_label)
152 #define pl_line PL_ADD_PREFIX(pl_line)
153 #define pl_linmod PL_ADD_PREFIX(pl_linmod)
154 #define pl_move PL_ADD_PREFIX(pl_move)
155 #define pl_point PL_ADD_PREFIX(pl_point)
156 #define pl_setOutputMode PL_ADD_PREFIX(pl_setOutputMode)
157 #define pl_space PL_ADD_PREFIX(pl_space)
158 #define plot3_invalid PL_ADD_PREFIX(plot3_invalid)
159 
160 
161 PLOT3_EXPORT extern int pl_getOutputMode(void);
163 PLOT3_EXPORT extern void pl_point(FILE *plotfp,
164  int x,
165  int y);
166 PLOT3_EXPORT extern void pl_line(FILE *plotfp,
167  int fx,
168  int fy,
169  int tx,
170  int ty);
171 PLOT3_EXPORT extern void pl_linmod(FILE *plotfp,
172  const char *s);
173 PLOT3_EXPORT extern void pl_move(FILE *plotfp,
174  int x,
175  int y);
176 PLOT3_EXPORT extern void pl_cont(FILE *plotfp,
177  int x,
178  int y);
179 PLOT3_EXPORT extern void pl_label(FILE *plotfp,
180  const char *s);
181 PLOT3_EXPORT extern void pl_space(FILE *plotfp,
182  int x_1,
183  int y_1,
184  int x_2,
185  int y_2);
186 PLOT3_EXPORT extern void pl_erase(FILE *plotfp);
187 PLOT3_EXPORT extern void pl_circle(FILE *plotfp,
188  int x,
189  int y,
190  int r);
191 PLOT3_EXPORT extern void pl_arc(FILE *plotfp,
192  int xc,
193  int yc,
194  int x_1,
195  int y_1,
196  int x_2,
197  int y_2);
198 PLOT3_EXPORT extern void pl_box(FILE *plotfp,
199  int x_1,
200  int y_1,
201  int x_2,
202  int y_2);
203 
204 /*
205  * BRL extensions to the UNIX-plot file format.
206  */
207 PLOT3_EXPORT extern void pl_color(FILE *plotfp,
208  int r,
209  int g,
210  int b);
211 PLOT3_EXPORT extern void pl_color_buc(FILE *plotfp,
212  struct bu_color *c);
213 PLOT3_EXPORT extern void pl_flush(FILE *plotfp);
214 PLOT3_EXPORT extern void pl_3space(FILE *plotfp,
215  int x_1,
216  int y_1,
217  int z_1,
218  int x_2,
219  int y_2,
220  int z_2);
221 PLOT3_EXPORT extern void pl_3point(FILE *plotfp,
222  int x,
223  int y,
224  int z);
225 PLOT3_EXPORT extern void pl_3move(FILE *plotfp,
226  int x,
227  int y,
228  int z);
229 PLOT3_EXPORT extern void pl_3cont(FILE *plotfp,
230  int x,
231  int y,
232  int z);
233 PLOT3_EXPORT extern void pl_3line(FILE *plotfp,
234  int x_1,
235  int y_1,
236  int z_1,
237  int x_2,
238  int y_2,
239  int z_2);
240 PLOT3_EXPORT extern void pl_3box(FILE *plotfp,
241  int x_1,
242  int y_1,
243  int z_1,
244  int x_2,
245  int y_2,
246  int z_2);
247 
248 /* Double floating point versions */
249 PLOT3_EXPORT extern void pd_point(FILE *plotfp,
250  double x,
251  double y);
252 PLOT3_EXPORT extern void pd_line(FILE *plotfp,
253  double fx,
254  double fy,
255  double tx,
256  double ty);
257 PLOT3_EXPORT extern void pd_move(FILE *plotfp,
258  double x,
259  double y);
260 PLOT3_EXPORT extern void pd_cont(FILE *plotfp,
261  double x,
262  double y);
263 PLOT3_EXPORT extern void pd_space(FILE *plotfp,
264  double x_1,
265  double y_1,
266  double x_2,
267  double y_2);
268 PLOT3_EXPORT extern void pd_circle(FILE *plotfp,
269  double x,
270  double y,
271  double r);
272 PLOT3_EXPORT extern void pd_arc(FILE *plotfp,
273  double xc,
274  double yc,
275  double x_1,
276  double y_1,
277  double x_2,
278  double y_2);
279 PLOT3_EXPORT extern void pd_box(FILE *plotfp,
280  double x_1,
281  double y_1,
282  double x_2,
283  double y_2);
284 
285 /* Double 3-D both in vector and enumerated versions */
286 #ifdef VMATH_H
287 PLOT3_EXPORT extern void pdv_3space(FILE *plotfp,
288  const vect_t min,
289  const vect_t max);
290 PLOT3_EXPORT extern void pdv_3point(FILE *plotfp,
291  const vect_t pt);
292 PLOT3_EXPORT extern void pdv_3move(FILE *plotfp,
293  const vect_t pt);
294 PLOT3_EXPORT extern void pdv_3cont(FILE *plotfp,
295  const vect_t pt);
296 PLOT3_EXPORT extern void pdv_3line(FILE *plotfp,
297  const vect_t a,
298  const vect_t b);
299 PLOT3_EXPORT extern void pdv_3box(FILE *plotfp,
300  const vect_t a,
301  const vect_t b);
302 #endif /* VMATH_H */
303 PLOT3_EXPORT extern void pd_3space(FILE *plotfp,
304  double x_1,
305  double y_1,
306  double z_1,
307  double x_2,
308  double y_2,
309  double z_2);
310 PLOT3_EXPORT extern void pd_3point(FILE *plotfp,
311  double x,
312  double y,
313  double z);
314 PLOT3_EXPORT extern void pd_3move(FILE *plotfp,
315  double x,
316  double y,
317  double z);
318 PLOT3_EXPORT extern void pd_3cont(FILE *plotfp,
319  double x,
320  double y,
321  double z);
322 PLOT3_EXPORT extern void pd_3line(FILE *plotfp,
323  double x_1,
324  double y_1,
325  double z_1,
326  double x_2,
327  double y_2,
328  double z_2);
329 PLOT3_EXPORT extern void pd_3box(FILE *plotfp,
330  double x_1,
331  double y_1,
332  double z_1,
333  double x_2,
334  double y_2,
335  double z_2);
336 PLOT3_EXPORT extern void pdv_3ray(FILE *fp,
337  const point_t pt,
338  const vect_t dir,
339  double t);
340 
341 
342 PLOT3_EXPORT extern int plot3_invalid(FILE *fp, int mode);
343 
344 __END_DECLS
345 
346 #if defined(PLOT3_IMPLEMENTATION)
347 #include <stdio.h>
348 #include "bu/cv.h"
349 
350 static int pl_outputMode = PL_OUTPUT_MODE_BINARY;
351 
352 /* For the sake of efficiency, we trust putc() to write only one byte */
353 #define putsi(a) putc(a, plotfp); putc((a>>8), plotfp)
354 
355 /* Making a common pd_3 to be used in pd_3cont and pd_3move */
356 static void
357 pd_3(FILE *plotfp, double x, double y, double z, char c)
358 {
359  size_t ret;
360  double in[3];
361  unsigned char out[3*8+1];
362 
363  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
364  in[0] = x;
365  in[1] = y;
366  in[2] = z;
367  bu_cv_htond(&out[1], (unsigned char *)in, 3);
368 
369  out[0] = c;
370  ret = fwrite(out, 1, 3*8+1, plotfp);
371  if (ret != 3*8+1) {
372  perror("fwrite");
373  }
374  } else {
375  fprintf(plotfp, "%c %g %g %g\n", c, x, y, z);
376  }
377 }
378 
379 /* Making a common pdv_3 to be used in pdv_3cont and pdv_3move */
380 static void
381 pdv_3(FILE *plotfp, const fastf_t *pt, char c)
382 {
383  size_t ret;
384  unsigned char out[3*8+1];
385 
386  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
387  bu_cv_htond(&out[1], (unsigned char *)pt, 3);
388 
389  out[0] = c;
390  ret = fwrite(out, 1, 3*8+1, plotfp);
391  if (ret != 3*8+1) {
392  perror("fwrite");
393  }
394  } else {
395  fprintf(plotfp, "%c %g %g %g\n", c, V3ARGS(pt));
396  }
397 }
398 
399 /* Making a common pd to be used in pd_cont and pd_move */
400 static void
401 common_pd(FILE *plotfp, double x, double y, char c)
402 {
403  size_t ret;
404  double in[2];
405  unsigned char out[2*8+1];
406 
407  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
408  in[0] = x;
409  in[1] = y;
410  bu_cv_htond(&out[1], (unsigned char *)in, 2);
411 
412  out[0] = c;
413  ret = fwrite(out, 1, 2*8+1, plotfp);
414  if (ret != 2*8+1) {
415  perror("fwrite");
416  }
417  } else {
418  fprintf(plotfp, "%c %g %g\n", c, x, y);
419  }
420 }
421 
422 /* Making a common pl_3 to be used in pl_3cont and pl_3move */
423 static void
424 pl_3(FILE *plotfp, int x, int y, int z, char c)
425 {
426  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
427  putc( c, plotfp);
428  putsi(x);
429  putsi(y);
430  putsi(z);
431  } else {
432  fprintf(plotfp, "%c %d %d %d\n", c, x, y, z);
433  }
434 }
435 
436 /*
437  * These interfaces provide the standard UNIX-Plot functionality
438  */
439 
440 int
441 pl_getOutputMode(void) {
442  return pl_outputMode;
443 }
444 
445 void
446 pl_setOutputMode(int mode) {
447  pl_outputMode = mode;
448 }
449 
450 /**
451  * @brief
452  * plot a point
453  */
454 void
455 pl_point(FILE *plotfp, int x, int y)
456 {
457  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
458  putc('p', plotfp);
459  putsi(x);
460  putsi(y);
461  } else {
462  fprintf(plotfp, "p %d %d\n", x, y);
463  }
464 }
465 
466 void
467 pl_line(FILE *plotfp, int px1, int py1, int px2, int py2)
468 {
469  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
470  putc('l', plotfp);
471  putsi(px1);
472  putsi(py1);
473  putsi(px2);
474  putsi(py2);
475  } else {
476  fprintf(plotfp, "l %d %d %d %d\n", px1, py1, px2, py2);
477  }
478 }
479 
480 void
481 pl_linmod(FILE *plotfp, const char *s)
482 {
483  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
484  putc('f', plotfp);
485  while (*s)
486  putc(*s++, plotfp);
487  putc('\n', plotfp);
488  } else {
489  fprintf(plotfp, "f %s\n", s);
490  }
491 }
492 
493 void
494 pl_move(FILE *plotfp, int x, int y)
495 {
496  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
497  putc('m', plotfp);
498  putsi(x);
499  putsi(y);
500  } else {
501  fprintf(plotfp, "m %d %d\n", x, y);
502  }
503 }
504 
505 void
506 pl_cont(FILE *plotfp, int x, int y)
507 {
508  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
509  putc('n', plotfp);
510  putsi(x);
511  putsi(y);
512  } else {
513  fprintf(plotfp, "n %d %d\n", x, y);
514  }
515 }
516 
517 void
518 pl_label(FILE *plotfp, const char *s)
519 {
520  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
521  putc('t', plotfp);
522  while (*s)
523  putc(*s++, plotfp);
524  putc('\n', plotfp);
525  } else {
526  fprintf(plotfp, "t %s\n", s);
527  }
528 }
529 
530 void
531 pl_space(FILE *plotfp, int px1, int py1, int px2, int py2)
532 {
533  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
534  putc('s', plotfp);
535  putsi(px1);
536  putsi(py1);
537  putsi(px2);
538  putsi(py2);
539  } else {
540  fprintf(plotfp, "s %d %d %d %d\n", px1, py1, px2, py2);
541  }
542 }
543 
544 void
545 pl_erase(FILE *plotfp)
546 {
547  if (pl_outputMode == PL_OUTPUT_MODE_BINARY)
548  putc('e', plotfp);
549  else
550  fprintf(plotfp, "e\n");
551 }
552 
553 void
554 pl_circle(FILE *plotfp, int x, int y, int r)
555 {
556  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
557  putc('c', plotfp);
558  putsi(x);
559  putsi(y);
560  putsi(r);
561  } else {
562  fprintf(plotfp, "c %d %d %d\n", x, y, r);
563  }
564 }
565 
566 void
567 pl_arc(FILE *plotfp, int xc, int yc, int px1, int py1, int px2, int py2)
568 {
569  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
570  putc('a', plotfp);
571  putsi(xc);
572  putsi(yc);
573  putsi(px1);
574  putsi(py1);
575  putsi(px2);
576  putsi(py2);
577  } else {
578  fprintf(plotfp, "a %d %d %d %d %d %d\n", xc, yc, px1, py1, px2, py2);
579  }
580 }
581 
582 void
583 pl_box(FILE *plotfp, int px1, int py1, int px2, int py2)
584 {
585  pl_move(plotfp, px1, py1);
586  pl_cont(plotfp, px1, py2);
587  pl_cont(plotfp, px2, py2);
588  pl_cont(plotfp, px2, py1);
589  pl_cont(plotfp, px1, py1);
590  pl_move(plotfp, px2, py2);
591 }
592 
593 /*
594  * Here lie the BRL 3-D extensions.
595  */
596 
597 /* Warning: r, g, b are ints. The output is chars. */
598 void
599 pl_color(FILE *plotfp, int r, int g, int b)
600 {
601  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
602  putc('C', plotfp);
603  putc(r, plotfp);
604  putc(g, plotfp);
605  putc(b, plotfp);
606  } else {
607  fprintf(plotfp, "C %d %d %d\n", r, g, b);
608  }
609 }
610 
611 void
612 pl_color_buc(FILE *plotfp, struct bu_color *c)
613 {
614  int r = 0;
615  int g = 0;
616  int b = 0;
617  (void)bu_color_to_rgb_ints(c, &r, &g, &b);
618  pl_color(plotfp, r, g, b);
619 }
620 
621 void
622 pl_flush(FILE *plotfp)
623 {
624  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
625  putc('F', plotfp);
626  } else {
627  fprintf(plotfp, "F\n");
628  }
629 
630  fflush(plotfp);
631 }
632 
633 void
634 pl_3space(FILE *plotfp, int px1, int py1, int pz1, int px2, int py2, int pz2)
635 {
636  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
637  putc('S', plotfp);
638  putsi(px1);
639  putsi(py1);
640  putsi(pz1);
641  putsi(px2);
642  putsi(py2);
643  putsi(pz2);
644  } else {
645  fprintf(plotfp, "S %d %d %d %d %d %d\n", px1, py1, pz1, px2, py2, pz2);
646  }
647 }
648 
649 void
650 pl_3point(FILE *plotfp, int x, int y, int z)
651 {
652  pl_3(plotfp, x, y, z, 'P'); /* calling common function pl_3 */
653 }
654 
655 void
656 pl_3move(FILE *plotfp, int x, int y, int z)
657 {
658  pl_3(plotfp, x, y, z, 'M'); /* calling common function pl_3 */
659 }
660 
661 void
662 pl_3cont(FILE *plotfp, int x, int y, int z)
663 {
664  pl_3(plotfp, x, y, z, 'N'); /* calling common function pl_3 */
665 }
666 
667 void
668 pl_3line(FILE *plotfp, int px1, int py1, int pz1, int px2, int py2, int pz2)
669 {
670  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
671  putc('L', plotfp);
672  putsi(px1);
673  putsi(py1);
674  putsi(pz1);
675  putsi(px2);
676  putsi(py2);
677  putsi(pz2);
678  } else {
679  fprintf(plotfp, "L %d %d %d %d %d %d\n", px1, py1, pz1, px2, py2, pz2);
680  }
681 }
682 
683 void
684 pl_3box(FILE *plotfp, int px1, int py1, int pz1, int px2, int py2, int pz2)
685 {
686  pl_3move(plotfp, px1, py1, pz1);
687  /* first side */
688  pl_3cont(plotfp, px1, py2, pz1);
689  pl_3cont(plotfp, px1, py2, pz2);
690  pl_3cont(plotfp, px1, py1, pz2);
691  pl_3cont(plotfp, px1, py1, pz1);
692  /* across */
693  pl_3cont(plotfp, px2, py1, pz1);
694  /* second side */
695  pl_3cont(plotfp, px2, py2, pz1);
696  pl_3cont(plotfp, px2, py2, pz2);
697  pl_3cont(plotfp, px2, py1, pz2);
698  pl_3cont(plotfp, px2, py1, pz1);
699  /* front edge */
700  pl_3move(plotfp, px1, py2, pz1);
701  pl_3cont(plotfp, px2, py2, pz1);
702  /* bottom back */
703  pl_3move(plotfp, px1, py1, pz2);
704  pl_3cont(plotfp, px2, py1, pz2);
705  /* top back */
706  pl_3move(plotfp, px1, py2, pz2);
707  pl_3cont(plotfp, px2, py2, pz2);
708 }
709 
710 /*
711  * Double floating point versions
712  */
713 
714 void
715 pd_point(FILE *plotfp, double x, double y)
716 {
717  common_pd( plotfp, x, y, 'x'); /* calling common function pd */
718 }
719 
720 void
721 pd_line(FILE *plotfp, double px1, double py1, double px2, double py2)
722 {
723  size_t ret;
724  double in[4];
725  unsigned char out[4*8+1];
726 
727  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
728  in[0] = px1;
729  in[1] = py1;
730  in[2] = px2;
731  in[3] = py2;
732  bu_cv_htond(&out[1], (unsigned char *)in, 4);
733 
734  out[0] = 'v';
735  ret = fwrite(out, 1, 4*8+1, plotfp);
736  if (ret != 4*8+1) {
737  perror("fwrite");
738  }
739  } else {
740  fprintf(plotfp, "v %g %g %g %g\n", px1, py1, px2, py2);
741  }
742 }
743 
744 /* Note: no pd_linmod(), just use pl_linmod() */
745 
746 void
747 pd_move(FILE *plotfp, double x, double y)
748 {
749  common_pd( plotfp, x, y, 'o'); /* calling common function pd */
750 }
751 
752 void
753 pd_cont(FILE *plotfp, double x, double y)
754 {
755  common_pd( plotfp, x, y, 'q'); /* calling common function pd */
756 }
757 
758 void
759 pd_space(FILE *plotfp, double px1, double py1, double px2, double py2)
760 {
761  size_t ret;
762  double in[4];
763  unsigned char out[4*8+1];
764 
765  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
766  in[0] = px1;
767  in[1] = py1;
768  in[2] = px2;
769  in[3] = py2;
770  bu_cv_htond(&out[1], (unsigned char *)in, 4);
771 
772  out[0] = 'w';
773  ret = fwrite(out, 1, 4*8+1, plotfp);
774  if (ret != 4*8+1) {
775  perror("fwrite");
776  }
777  } else {
778  fprintf(plotfp, "w %g %g %g %g\n", px1, py1, px2, py2);
779  }
780 }
781 
782 void
783 pd_circle(FILE *plotfp, double x, double y, double r)
784 {
785  size_t ret;
786  double in[3];
787  unsigned char out[3*8+1];
788 
789  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
790  in[0] = x;
791  in[1] = y;
792  in[2] = r;
793  bu_cv_htond(&out[1], (unsigned char *)in, 3);
794 
795  out[0] = 'i';
796  ret = fwrite(out, 1, 3*8+1, plotfp);
797  if (ret != 3*8+1) {
798  perror("fwrite");
799  }
800  } else {
801  fprintf(plotfp, "i %g %g %g\n", x, y, r);
802  }
803 }
804 
805 void
806 pd_arc(FILE *plotfp, double xc, double yc, double px1, double py1, double px2, double py2)
807 {
808  size_t ret;
809  double in[6];
810  unsigned char out[6*8+1];
811 
812  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
813  in[0] = xc;
814  in[1] = yc;
815  in[2] = px1;
816  in[3] = py1;
817  in[4] = px2;
818  in[5] = py2;
819  bu_cv_htond(&out[1], (unsigned char *)in, 6);
820 
821  out[0] = 'r';
822  ret = fwrite(out, 1, 6*8+1, plotfp);
823  if (ret != 6*8+1) {
824  perror("fwrite");
825  }
826  } else {
827  fprintf(plotfp, "r %g %g %g %g %g %g\n", xc, yc, px1, py1, px2, py2);
828  }
829 }
830 
831 void
832 pd_box(FILE *plotfp, double px1, double py1, double px2, double py2)
833 {
834  pd_move(plotfp, px1, py1);
835  pd_cont(plotfp, px1, py2);
836  pd_cont(plotfp, px2, py2);
837  pd_cont(plotfp, px2, py1);
838  pd_cont(plotfp, px1, py1);
839  pd_move(plotfp, px2, py2);
840 }
841 
842 /* Double 3-D, both in vector and enumerated versions */
843 void
844 pdv_3space(FILE *plotfp, const vect_t min, const vect_t max)
845 {
846  size_t ret;
847  unsigned char out[6*8+1];
848 
849  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
850  bu_cv_htond(&out[1], (unsigned char *)min, 3);
851  bu_cv_htond(&out[3*8+1], (unsigned char *)max, 3);
852 
853  out[0] = 'W';
854  ret = fwrite(out, 1, 6*8+1, plotfp);
855  if (ret != 6*8+1) {
856  perror("fwrite");
857  }
858  } else {
859  fprintf(plotfp, "W %g %g %g %g %g %g\n", V3ARGS(min), V3ARGS(max));
860  }
861 }
862 
863 void
864 pd_3space(FILE *plotfp, double px1, double py1, double pz1, double px2, double py2, double pz2)
865 {
866  size_t ret;
867  double in[6];
868  unsigned char out[6*8+1];
869 
870  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
871  in[0] = px1;
872  in[1] = py1;
873  in[2] = pz1;
874  in[3] = px2;
875  in[4] = py2;
876  in[5] = pz2;
877  bu_cv_htond(&out[1], (unsigned char *)in, 6);
878 
879  out[0] = 'W';
880  ret = fwrite(out, 1, 6*8+1, plotfp);
881  if (ret != 6*8+1) {
882  perror("fwrite");
883  }
884  } else {
885  fprintf(plotfp, "W %g %g %g %g %g %g\n", px1, py1, pz1, px2, py2, pz2);
886  }
887 }
888 
889 void
890 pdv_3point(FILE *plotfp, const point_t pt)
891 {
892  pdv_3(plotfp, pt, 'X'); /* calling common function pdv_3 */
893 }
894 
895 void
896 pd_3point(FILE *plotfp, double x, double y, double z)
897 {
898  pd_3(plotfp, x, y, z, 'X'); /* calling common function pd_3 */
899 }
900 
901 void
902 pdv_3move(FILE *plotfp, const point_t pt)
903 {
904  pdv_3(plotfp, pt, 'O'); /* calling common function pdv_3 */
905 }
906 
907 void
908 pd_3move(FILE *plotfp, double x, double y, double z)
909 {
910  pd_3(plotfp, x, y, z, 'O'); /* calling common function pd_3 */
911 }
912 
913 void
914 pdv_3cont(FILE *plotfp, const point_t pt)
915 {
916  pdv_3(plotfp, pt, 'Q'); /* calling common function pdv_3 */
917 }
918 
919 void
920 pd_3cont(FILE *plotfp, double x, double y, double z)
921 {
922  pd_3(plotfp, x, y, z, 'Q'); /* calling common function pd_3 */
923 }
924 
925 void
926 pdv_3line(FILE *plotfp, const vect_t a, const vect_t b)
927 {
928  size_t ret;
929  unsigned char out[6*8+1];
930 
931  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
932  bu_cv_htond(&out[1], (unsigned char *)a, 3);
933  bu_cv_htond(&out[3*8+1], (unsigned char *)b, 3);
934 
935  out[0] = 'V';
936  ret = fwrite(out, 1, 6*8+1, plotfp);
937  if (ret != 6*8+1) {
938  perror("fwrite");
939  }
940  } else {
941  fprintf(plotfp, "V %g %g %g %g %g %g\n", V3ARGS(a), V3ARGS(b));
942  }
943 }
944 
945 void
946 pd_3line(FILE *plotfp, double px1, double py1, double pz1, double px2, double py2, double pz2)
947 {
948  size_t ret;
949  double in[6];
950  unsigned char out[6*8+1];
951 
952  if (pl_outputMode == PL_OUTPUT_MODE_BINARY) {
953  in[0] = px1;
954  in[1] = py1;
955  in[2] = pz1;
956  in[3] = px2;
957  in[4] = py2;
958  in[5] = pz2;
959  bu_cv_htond(&out[1], (unsigned char *)in, 6);
960 
961  out[0] = 'V';
962  ret = fwrite(out, 1, 6*8+1, plotfp);
963  if (ret != 6*8+1) {
964  perror("fwrite");
965  }
966  } else {
967  fprintf(plotfp, "V %g %g %g %g %g %g\n", px1, py1, pz1, px2, py2, pz2);
968  }
969 }
970 
971 void
972 pdv_3box(FILE *plotfp, const vect_t a, const vect_t b)
973 {
974  pd_3move(plotfp, a[X], a[Y], a[Z]);
975  /* first side */
976  pd_3cont(plotfp, a[X], b[Y], a[Z]);
977  pd_3cont(plotfp, a[X], b[Y], b[Z]);
978  pd_3cont(plotfp, a[X], a[Y], b[Z]);
979  pd_3cont(plotfp, a[X], a[Y], a[Z]);
980  /* across */
981  pd_3cont(plotfp, b[X], a[Y], a[Z]);
982  /* second side */
983  pd_3cont(plotfp, b[X], b[Y], a[Z]);
984  pd_3cont(plotfp, b[X], b[Y], b[Z]);
985  pd_3cont(plotfp, b[X], a[Y], b[Z]);
986  pd_3cont(plotfp, b[X], a[Y], a[Z]);
987  /* front edge */
988  pd_3move(plotfp, a[X], b[Y], a[Z]);
989  pd_3cont(plotfp, b[X], b[Y], a[Z]);
990  /* bottom back */
991  pd_3move(plotfp, a[X], a[Y], b[Z]);
992  pd_3cont(plotfp, b[X], a[Y], b[Z]);
993  /* top back */
994  pd_3move(plotfp, a[X], b[Y], b[Z]);
995  pd_3cont(plotfp, b[X], b[Y], b[Z]);
996 }
997 
998 void
999 pd_3box(FILE *plotfp, double px1, double py1, double pz1, double px2, double py2, double pz2)
1000 {
1001  pd_3move(plotfp, px1, py1, pz1);
1002  /* first side */
1003  pd_3cont(plotfp, px1, py2, pz1);
1004  pd_3cont(plotfp, px1, py2, pz2);
1005  pd_3cont(plotfp, px1, py1, pz2);
1006  pd_3cont(plotfp, px1, py1, pz1);
1007  /* across */
1008  pd_3cont(plotfp, px2, py1, pz1);
1009  /* second side */
1010  pd_3cont(plotfp, px2, py2, pz1);
1011  pd_3cont(plotfp, px2, py2, pz2);
1012  pd_3cont(plotfp, px2, py1, pz2);
1013  pd_3cont(plotfp, px2, py1, pz1);
1014  /* front edge */
1015  pd_3move(plotfp, px1, py2, pz1);
1016  pd_3cont(plotfp, px2, py2, pz1);
1017  /* bottom back */
1018  pd_3move(plotfp, px1, py1, pz2);
1019  pd_3cont(plotfp, px2, py1, pz2);
1020  /* top back */
1021  pd_3move(plotfp, px1, py2, pz2);
1022  pd_3cont(plotfp, px2, py2, pz2);
1023 }
1024 
1025 /**
1026  * Draw a ray
1027  */
1028 void
1029 pdv_3ray(FILE *fp, const point_t pt, const vect_t dir, double t)
1030 {
1031  point_t tip;
1032 
1033  VJOIN1(tip, pt, t, dir);
1034  pdv_3move(fp, pt);
1035  pdv_3cont(fp, tip);
1036 }
1037 
1038 
1039 /*
1040  * Routines to validate a plot file
1041  */
1042 
1043 static int
1044 read_short(FILE *fp, int cnt, int mode)
1045 {
1046  if (mode == PL_OUTPUT_MODE_BINARY) {
1047  for (int i = 0; i < cnt * 2; i++) {
1048  if (getc(fp) == EOF)
1049  return 1;
1050  }
1051  return 0;
1052  }
1053  if (mode == PL_OUTPUT_MODE_TEXT) {
1054  int ret;
1055  double val;
1056  for (int i = 0; i < cnt; i++) {
1057  ret = fscanf(fp, "%lf", &val);
1058  if (ret != 1)
1059  return 1;
1060  }
1061  return 0;
1062  }
1063 
1064  return 1;
1065 }
1066 
1067 static int
1068 read_ieee(FILE *fp, int cnt, int mode)
1069 {
1070  size_t ret;
1071  if (mode == PL_OUTPUT_MODE_BINARY) {
1072  for (int i = 0; i < cnt; i++) {
1073  char inbuf[SIZEOF_NETWORK_DOUBLE];
1074  ret = fread(inbuf, SIZEOF_NETWORK_DOUBLE, 1, fp);
1075  if (ret != 1)
1076  return 1;
1077  }
1078  return 0;
1079  }
1080  if (mode == PL_OUTPUT_MODE_TEXT) {
1081  double val;
1082  for (int i = 0; i < cnt; i++) {
1083  ret = (size_t)fscanf(fp, "%lf", &val);
1084  if (ret != 1)
1085  return 1;
1086  }
1087  return 0;
1088  }
1089  return 1;
1090 }
1091 
1092 static int
1093 read_tstring(FILE *fp, int mode)
1094 {
1095  int ret;
1096  if (mode == PL_OUTPUT_MODE_BINARY) {
1097  int str_done = 0;
1098  int cc;
1099  while (!feof(fp) && !str_done) {
1100  cc = getc(fp);
1101  if (cc == '\n')
1102  str_done = 1;
1103  }
1104  return 0;
1105  }
1106  if (mode == PL_OUTPUT_MODE_TEXT) {
1107  char carg[256] = {0};
1108  ret = fscanf(fp, "%255s\n", &carg[0]);
1109  if (ret != 1)
1110  return 1;
1111  return 0;
1112  }
1113  return 1;
1114 }
1115 
1116 int
1117 plot3_invalid(FILE *fp, int mode)
1118 {
1119 
1120  /* Only two valid modes */
1122  return 1;
1123  }
1124 
1125  /* A non-readable file isn't a valid file */
1126  if (!fp) {
1127  return 1;
1128  }
1129 
1130  int i = 0;
1131  int c;
1132  unsigned int tchar = 0;
1133 
1134  while (!feof(fp) && (c=getc(fp)) != EOF) {
1135  if (c < 'A' || c > 'z') {
1136  return 1;
1137  }
1138  switch (c) {
1139  case 'C':
1140  // TCHAR, 3, "color"
1141  if (mode == PL_OUTPUT_MODE_BINARY) {
1142  for (i = 0; i < 3; i++) {
1143  if (getc(fp) == EOF)
1144  return 1;
1145  }
1146  }
1147  if (mode == PL_OUTPUT_MODE_TEXT) {
1148  i = fscanf(fp, "%u", &tchar);
1149  if (i != 1)
1150  return 1;
1151  }
1152  break;
1153  case 'F':
1154  // TNONE, 0, "flush"
1155  break;
1156  case 'L':
1157  // TSHORT, 6, "3line"
1158  if (read_short(fp, 6, mode))
1159  return 1;
1160  break;
1161  case 'M':
1162  // TSHORT, 3, "3move"
1163  if (read_short(fp, 3, mode))
1164  return 1;
1165  break;
1166  case 'N':
1167  // TSHORT, 3, "3cont"
1168  if (read_short(fp, 3, mode))
1169  return 1;
1170  break;
1171  case 'O':
1172  // TIEEE, 3, "d_3move"
1173  if (read_ieee(fp, 3, mode))
1174  return 1;
1175  break;
1176  case 'P':
1177  // TSHORT, 3, "3point"
1178  if (read_short(fp, 3, mode))
1179  return 1;
1180  break;
1181  case 'Q':
1182  // TIEEE, 3, "d_3cont"
1183  if (read_ieee(fp, 3, mode))
1184  return 1;
1185  break;
1186  case 'S':
1187  // TSHORT, 6, "3space"
1188  if (read_short(fp, 6, mode))
1189  return 1;
1190  break;
1191  case 'V':
1192  // TIEEE, 6, "d_3line"
1193  if (read_ieee(fp, 6, mode))
1194  return 1;
1195  break;
1196  case 'W':
1197  // TIEEE, 6, "d_3space"
1198  if (read_ieee(fp, 6, mode))
1199  return 1;
1200  break;
1201  case 'X':
1202  // TIEEE, 3, "d_3point"
1203  if (read_ieee(fp, 3, mode))
1204  return 1;
1205  break;
1206  case 'a':
1207  // TSHORT, 6, "arc"
1208  if (read_short(fp, 6, mode))
1209  return 1;
1210  break;
1211  case 'c':
1212  // TSHORT, 3, "circle"
1213  if (read_short(fp, 3, mode))
1214  return 1;
1215  break;
1216  case 'e':
1217  // TNONE, 0, "erase"
1218  break;
1219  case 'f':
1220  // TSTRING, 1, "linmod"
1221  if (read_tstring(fp, mode))
1222  return 1;
1223  break;
1224  case 'i':
1225  // TIEEE, 3, "d_circle"
1226  if (read_ieee(fp, 3, mode))
1227  return 1;
1228  break;
1229  case 'l':
1230  // TSHORT, 4, "line"
1231  if (read_short(fp, 4, mode))
1232  return 1;
1233  break;
1234  case 'm':
1235  // TSHORT, 2, "move"
1236  if (read_short(fp, 2, mode))
1237  return 1;
1238  break;
1239  case 'n':
1240  // TSHORT, 2, "cont"
1241  if (read_short(fp, 2, mode))
1242  return 1;
1243  break;
1244  case 'o':
1245  // TIEEE, 2, "d_move"
1246  if (read_ieee(fp, 2, mode))
1247  return 1;
1248  break;
1249  case 'p':
1250  // TSHORT, 2, "point"
1251  if (read_short(fp, 2, mode))
1252  return 1;
1253  break;
1254  case 'q':
1255  // TIEEE, 2, "d_cont"
1256  if (read_ieee(fp, 2, mode))
1257  return 1;
1258  break;
1259  case 'r':
1260  // TIEEE, 6, "d_arc"
1261  if (read_ieee(fp, 6, mode))
1262  return 1;
1263  break;
1264  case 's':
1265  // TSHORT, 4, "space"
1266  if (read_short(fp, 4, mode))
1267  return 1;
1268  break;
1269  case 't':
1270  // TSTRING, 1, "label"
1271  if (read_tstring(fp, mode))
1272  return 1;
1273  break;
1274  case 'v':
1275  // TIEEE, 4, "d_line"
1276  if (read_ieee(fp, 4, mode))
1277  return 1;
1278  break;
1279  case 'w':
1280  // TIEEE, 4, "d_space"
1281  if (read_ieee(fp, 4, mode))
1282  return 1;
1283  break;
1284  case 'x':
1285  // TIEEE, 2, "d_point"
1286  if (read_ieee(fp, 2, mode))
1287  return 1;
1288  break;
1289  default:
1290  return 1;
1291  break;
1292  };
1293  }
1294 
1295  return 0;
1296 }
1297 
1298 #endif // PLOT3_IMPLEMENTATION
1299 
1300 #endif /* PLOT3_H */
1301 
1302 /** @} */
1303 /*
1304  * Local Variables:
1305  * mode: C
1306  * tab-width: 8
1307  * indent-tabs-mode: t
1308  * c-file-style: "stroustrup"
1309  * End:
1310  * ex: shiftwidth=4 tabstop=8
1311  */
Header file for the BRL-CAD common definitions.
int bu_color_to_rgb_ints(const struct bu_color *cp, int *r, int *g, int *b)
#define SIZEOF_NETWORK_DOUBLE
Definition: cv.h:100
void bu_cv_htond(unsigned char *out, const unsigned char *in, size_t count)
void float float * fy
Definition: tig.h:283
void float float * y
Definition: tig.h:73
void float float float float * tx
Definition: tig.h:285
void int char * mode
Definition: tig.h:179
void int char int int double * min
Definition: tig.h:182
void float * fx
Definition: tig.h:282
void float float float float float * ty
Definition: tig.h:286
void float float float * z
Definition: tig.h:90
void int * c
Definition: tig.h:139
void float * x
Definition: tig.h:72
#define pl_3space
Definition: plot3.h:141
#define pl_circle
Definition: plot3.h:144
#define pl_line
Definition: plot3.h:152
#define PL_OUTPUT_MODE_BINARY
Definition: plot3.h:104
#define pl_3move
Definition: plot3.h:139
#define pdv_3cont
Definition: plot3.h:130
#define pd_box
Definition: plot3.h:122
#define pd_3line
Definition: plot3.h:117
#define pl_3point
Definition: plot3.h:140
#define pl_erase
Definition: plot3.h:148
#define pl_3box
Definition: plot3.h:136
#define pd_3box
Definition: plot3.h:115
#define pdv_3line
Definition: plot3.h:131
#define pl_color
Definition: plot3.h:145
#define pd_space
Definition: plot3.h:128
#define pl_point
Definition: plot3.h:155
#define pl_flush
Definition: plot3.h:149
#define pl_3line
Definition: plot3.h:138
#define pl_cont
Definition: plot3.h:147
#define pdv_3move
Definition: plot3.h:132
#define pl_arc
Definition: plot3.h:142
#define plot3_invalid
Definition: plot3.h:158
#define pd_arc
Definition: plot3.h:121
#define pd_3space
Definition: plot3.h:120
#define pdv_3box
Definition: plot3.h:129
#define pl_label
Definition: plot3.h:151
#define PLOT3_EXPORT
Definition: plot3.h:99
#define pd_point
Definition: plot3.h:127
#define pl_3cont
Definition: plot3.h:137
#define pd_circle
Definition: plot3.h:123
#define pdv_3point
Definition: plot3.h:133
#define pl_linmod
Definition: plot3.h:153
#define pl_color_buc
Definition: plot3.h:146
#define pd_move
Definition: plot3.h:126
#define pd_cont
Definition: plot3.h:124
#define pl_box
Definition: plot3.h:143
#define pl_move
Definition: plot3.h:154
#define pl_space
Definition: plot3.h:157
#define pdv_3ray
Definition: plot3.h:134
#define pl_getOutputMode
Definition: plot3.h:150
#define pd_3move
Definition: plot3.h:118
#define pl_setOutputMode
Definition: plot3.h:156
#define pd_3point
Definition: plot3.h:119
#define PL_OUTPUT_MODE_TEXT
Definition: plot3.h:105
#define pd_3cont
Definition: plot3.h:116
#define pdv_3space
Definition: plot3.h:135
#define pd_line
Definition: plot3.h:125
fastf_t vect_t[ELEMENTS_PER_VECT]
3-tuple vector
Definition: vmath.h:349
double fastf_t
fastest 64-bit (or larger) floating point type
Definition: vmath.h:334
#define VJOIN1(o, a, sb, b)
Definition: vmath.h:1335
fastf_t point_t[ELEMENTS_PER_POINT]
3-tuple point
Definition: vmath.h:355
#define V3ARGS(a)
Definition: vmath.h:1543
@ Y
Definition: vmath.h:402
@ X
Definition: vmath.h:401
@ Z
Definition: vmath.h:403
Definition: color.h:54
fundamental vector, matrix, quaternion math macros