BRL-CAD
tclcad_obj.c
Go to the documentation of this file.
1 /* T C L C A D _ O B J . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2000-2014 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 libtclcad */
21 /** @{ */
22 /** @file libtclcad/tclcad_obj.c
23  *
24  * A quasi-object-oriented database interface.
25  *
26  * A GED object contains the attributes and methods for controlling a
27  * BRL-CAD geometry edit object.
28  *
29  */
30 /** @} */
31 
32 #include "common.h"
33 
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include <math.h>
38 #include <errno.h>
39 #include <assert.h>
40 
41 #include <zlib.h>
42 #include <png.h>
43 
44 #include "tcl.h"
45 
46 #include "bn.h"
47 #include "bu/cmd.h"
48 #include "bu/units.h"
49 #include "vmath.h"
50 #include "db.h"
51 #include "rtgeom.h"
52 #include "wdb.h"
53 #include "mater.h"
54 #include "tclcad.h"
55 
56 #include "solid.h"
57 #include "dm.h"
58 #include "dm/bview.h"
59 #include "obj.h"
60 
61 #include "ged.h"
62 
63 #include "fb.h"
64 
65 #include "dm/dm_xvars.h"
66 
67 #ifdef DM_X
68 # ifdef WITH_TK
69 # include "tk.h"
70 #endif
71 # include <X11/Xutil.h>
72 # include "dm/dm_xvars.h"
73 #endif /* DM_X */
74 
75 #ifdef DM_TK
76 # ifdef WITH_TK
77 # include "tk.h"
78 # endif
79 # include "dm/dm_xvars.h"
80 #endif /* DM_TK */
81 
82 #ifdef DM_OGL
83 # include "fb/fb_ogl.h"
84 #endif /* DM_OGL */
85 
86 #ifdef DM_OSG
87 # include "dm/dm_xvars.h"
88 #endif /* DM_OSG */
89 
90 #ifdef DM_OSGL
91 # include "dm/dm_xvars.h"
92 #endif /* DM_OSGL */
93 
94 #ifdef DM_WGL
95 # include <tkwinport.h>
96 # include "fb/fb_wgl.h"
97 # include "dm/dm_xvars.h"
98 #endif /* DM_WGL */
99 
100 #ifdef DM_QT
101 # include "dm/dm_xvars.h"
102 #endif /* DM_QT */
103 
104 /* Private headers */
105 #include "tclcad_private.h"
106 
107 #include "brlcad_version.h"
108 
109 
110 #define TO_UNLIMITED -1
111 
112 /*
113  * Weird upper limit from clipper ---> sqrt(2^63 -1)/2
114  * Probably should be sqrt(2^63 -1)
115  */
116 #define CLIPPER_MAX 1518500249
117 
118 HIDDEN int to_autoview(struct ged *gedp,
119  int argc,
120  const char *argv[],
121  ged_func_ptr func,
122  const char *usage,
123  int maxargs);
124 HIDDEN int to_axes(struct ged *gedp,
125  struct ged_dm_view *gdvp,
126  struct bview_axes_state *gasp,
127  int argc,
128  const char *argv[],
129  const char *usage);
130 HIDDEN int to_base2local(struct ged *gedp,
131  int argc,
132  const char *argv[],
133  ged_func_ptr func,
134  const char *usage,
135  int maxargs);
136 HIDDEN int to_bg(struct ged *gedp,
137  int argc,
138  const char *argv[],
139  ged_func_ptr func,
140  const char *usage,
141  int maxargs);
142 HIDDEN int to_blast(struct ged *gedp,
143  int argc,
144  const char *argv[],
145  ged_func_ptr func,
146  const char *usage,
147  int maxargs);
148 HIDDEN int to_bounds(struct ged *gedp,
149  int argc,
150  const char *argv[],
151  ged_func_ptr func,
152  const char *usage,
153  int maxargs);
154 HIDDEN int to_configure(struct ged *gedp,
155  int argc,
156  const char *argv[],
157  ged_func_ptr func,
158  const char *usage,
159  int maxargs);
160 HIDDEN int to_constrain_rmode(struct ged *gedp,
161  int argc,
162  const char *argv[],
163  ged_func_ptr func,
164  const char *usage,
165  int maxargs);
166 HIDDEN int to_constrain_tmode(struct ged *gedp,
167  int argc,
168  const char *argv[],
169  ged_func_ptr func,
170  const char *usage,
171  int maxargs);
172 HIDDEN int to_copy(struct ged *gedp,
173  int argc,
174  const char *argv[],
175  ged_func_ptr func,
176  const char *usage,
177  int maxargs);
178 HIDDEN int to_data_arrows(struct ged *gedp,
179  int argc,
180  const char *argv[],
181  ged_func_ptr func,
182  const char *usage,
183  int maxargs);
184 HIDDEN int to_data_axes(struct ged *gedp,
185  int argc,
186  const char *argv[],
187  ged_func_ptr func,
188  const char *usage,
189  int maxargs);
190 HIDDEN int to_data_labels(struct ged *gedp,
191  int argc,
192  const char *argv[],
193  ged_func_ptr func,
194  const char *usage,
195  int maxargs);
196 HIDDEN int to_data_lines(struct ged *gedp,
197  int argc,
198  const char *argv[],
199  ged_func_ptr func,
200  const char *usage,
201  int maxargs);
202 HIDDEN int to_data_polygons(struct ged *gedp,
203  int argc,
204  const char *argv[],
205  ged_func_ptr func,
206  const char *usage,
207  int maxargs);
208 HIDDEN int to_data_move(struct ged *gedp,
209  int argc,
210  const char *argv[],
211  ged_func_ptr func,
212  const char *usage,
213  int maxargs);
214 HIDDEN int to_data_move_object_mode(struct ged *gedp,
215  int argc,
216  const char *argv[],
217  ged_func_ptr func,
218  const char *usage,
219  int maxargs);
220 HIDDEN int to_data_move_point_mode(struct ged *gedp,
221  int argc,
222  const char *argv[],
223  ged_func_ptr func,
224  const char *usage,
225  int maxargs);
226 HIDDEN int to_data_pick(struct ged *gedp,
227  int argc,
228  const char *argv[],
229  ged_func_ptr func,
230  const char *usage,
231  int maxargs);
232 HIDDEN int to_data_vZ(struct ged *gedp,
233  int argc,
234  const char *argv[],
235  ged_func_ptr func,
236  const char *usage,
237  int maxargs);
238 HIDDEN int to_dlist_on(struct ged *gedp,
239  int argc,
240  const char *argv[],
241  ged_func_ptr func,
242  const char *usage,
243  int maxargs);
244 HIDDEN int to_bot_edge_split(struct ged *gedp,
245  int argc,
246  const char *argv[],
247  ged_func_ptr func,
248  const char *usage,
249  int maxargs);
250 HIDDEN int to_bot_face_split(struct ged *gedp,
251  int argc,
252  const char *argv[],
253  ged_func_ptr func,
254  const char *usage,
255  int maxargs);
256 HIDDEN int to_fontsize(struct ged *gedp,
257  int argc,
258  const char *argv[],
259  ged_func_ptr func,
260  const char *usage,
261  int maxargs);
262 HIDDEN int to_get_prev_mouse(struct ged *gedp,
263  int argc,
264  const char *argv[],
265  ged_func_ptr func,
266  const char *usage,
267  int maxargs);
268 HIDDEN int to_init_view_bindings(struct ged *gedp,
269  int argc,
270  const char *argv[],
271  ged_func_ptr func,
272  const char *usage,
273  int maxargs);
274 HIDDEN int to_delete_view(struct ged *gedp,
275  int argc,
276  const char *argv[],
277  ged_func_ptr func,
278  const char *usage,
279  int maxargs);
280 HIDDEN int to_faceplate(struct ged *gedp,
281  int argc,
282  const char *argv[],
283  ged_func_ptr func,
284  const char *usage,
285  int maxargs);
286 HIDDEN int to_handle_expose(struct ged *gedp,
287  int argc,
288  const char *argv[],
289  ged_func_ptr func,
290  const char *usage,
291  int maxargs);
292 HIDDEN int to_handle_refresh(struct ged *gedp,
293  const char *name);
294 HIDDEN int to_hide_view(struct ged *gedp,
295  int argc,
296  const char *argv[],
297  ged_func_ptr func,
298  const char *usage,
299  int maxargs);
300 HIDDEN int to_idle_mode(struct ged *gedp,
301  int argc,
302  const char *argv[],
303  ged_func_ptr func,
304  const char *usage,
305  int maxargs);
306 HIDDEN int to_is_viewable(struct ged_dm_view *gdvp);
307 HIDDEN int to_light(struct ged *gedp,
308  int argc,
309  const char *argv[],
310  ged_func_ptr func,
311  const char *usage,
312  int maxargs);
313 HIDDEN int to_list_views(struct ged *gedp,
314  int argc,
315  const char *argv[],
316  ged_func_ptr func,
317  const char *usage,
318  int maxargs);
319 HIDDEN int to_listen(struct ged *gedp,
320  int argc,
321  const char *argv[],
322  ged_func_ptr func,
323  const char *usage,
324  int maxargs);
325 HIDDEN int to_local2base(struct ged *gedp,
326  int argc,
327  const char *argv[],
328  ged_func_ptr func,
329  const char *usage,
330  int maxargs);
331 HIDDEN int to_lod(struct ged *gedp,
332  int argc,
333  const char *argv[],
334  ged_func_ptr func,
335  const char *usage,
336  int maxargs);
337 HIDDEN int to_make(struct ged *gedp,
338  int argc,
339  const char *argv[],
340  ged_func_ptr func,
341  const char *usage,
342  int maxargs);
343 HIDDEN int to_mirror(struct ged *gedp,
344  int argc,
345  const char *argv[],
346  ged_func_ptr func,
347  const char *usage,
348  int maxargs);
349 HIDDEN int to_model_axes(struct ged *gedp,
350  int argc,
351  const char *argv[],
352  ged_func_ptr func,
353  const char *usage,
354  int maxargs);
355 HIDDEN int to_edit_motion_delta_callback(struct ged *gedp,
356  int argc,
357  const char *argv[],
358  ged_func_ptr func,
359  const char *usage,
360  int maxargs);
361 HIDDEN int to_more_args_callback(struct ged *gedp,
362  int argc,
363  const char *argv[],
364  ged_func_ptr func,
365  const char *usage,
366  int maxargs);
367 HIDDEN int to_mouse_append_pt_common(struct ged *gedp,
368  int argc,
369  const char *argv[],
370  ged_func_ptr func,
371  const char *usage,
372  int maxargs);
373 HIDDEN int to_mouse_brep_selection_append(struct ged *gedp,
374  int argc,
375  const char *argv[],
376  ged_func_ptr func,
377  const char *usage,
378  int maxargs);
380  int argc,
381  const char *argv[],
382  ged_func_ptr func,
383  const char *usage,
384  int maxargs);
385 HIDDEN int to_mouse_constrain_rot(struct ged *gedp,
386  int argc,
387  const char *argv[],
388  ged_func_ptr func,
389  const char *usage,
390  int maxargs);
391 HIDDEN int to_mouse_constrain_trans(struct ged *gedp,
392  int argc,
393  const char *argv[],
394  ged_func_ptr func,
395  const char *usage,
396  int maxargs);
397 HIDDEN int to_mouse_find_arb_edge(struct ged *gedp,
398  int argc,
399  const char *argv[],
400  ged_func_ptr func,
401  const char *usage,
402  int maxargs);
403 HIDDEN int to_mouse_find_bot_edge(struct ged *gedp,
404  int argc,
405  const char *argv[],
406  ged_func_ptr func,
407  const char *usage,
408  int maxargs);
409 HIDDEN int to_mouse_find_botpt(struct ged *gedp,
410  int argc,
411  const char *argv[],
412  ged_func_ptr func,
413  const char *usage,
414  int maxargs);
415 HIDDEN int to_mouse_find_metaballpt(struct ged *gedp,
416  int argc,
417  const char *argv[],
418  ged_func_ptr func,
419  const char *usage,
420  int maxargs);
421 HIDDEN int to_mouse_find_pipept(struct ged *gedp,
422  int argc,
423  const char *argv[],
424  ged_func_ptr func,
425  const char *usage,
426  int maxargs);
427 HIDDEN int to_mouse_joint_select(struct ged *gedp,
428  int argc,
429  const char *argv[],
430  ged_func_ptr func,
431  const char *usage,
432  int maxargs);
434  int argc,
435  const char *argv[],
436  ged_func_ptr func,
437  const char *usage,
438  int maxargs);
439 HIDDEN int to_mouse_move_arb_edge(struct ged *gedp,
440  int argc,
441  const char *argv[],
442  ged_func_ptr func,
443  const char *usage,
444  int maxargs);
445 HIDDEN int to_mouse_move_arb_face(struct ged *gedp,
446  int argc,
447  const char *argv[],
448  ged_func_ptr func,
449  const char *usage,
450  int maxargs);
451 HIDDEN int to_mouse_move_botpt(struct ged *gedp,
452  int argc,
453  const char *argv[],
454  ged_func_ptr func,
455  const char *usage,
456  int maxargs);
457 HIDDEN int to_mouse_move_botpts(struct ged *gedp,
458  int argc,
459  const char *argv[],
460  ged_func_ptr func,
461  const char *usage,
462  int maxargs);
463 HIDDEN int to_mouse_move_pt_common(struct ged *gedp,
464  int argc,
465  const char *argv[],
466  ged_func_ptr func,
467  const char *usage,
468  int maxargs);
469 HIDDEN int to_mouse_orotate(struct ged *gedp,
470  int argc,
471  const char *argv[],
472  ged_func_ptr func,
473  const char *usage,
474  int maxargs);
475 HIDDEN int to_mouse_oscale(struct ged *gedp,
476  int argc,
477  const char *argv[],
478  ged_func_ptr func,
479  const char *usage,
480  int maxargs);
481 HIDDEN int to_mouse_otranslate(struct ged *gedp,
482  int argc,
483  const char *argv[],
484  ged_func_ptr func,
485  const char *usage,
486  int maxargs);
487 HIDDEN int to_mouse_poly_circ(struct ged *gedp,
488  int argc,
489  const char *argv[],
490  ged_func_ptr func,
491  const char *usage,
492  int maxargs);
493 HIDDEN int to_mouse_poly_cont(struct ged *gedp,
494  int argc,
495  const char *argv[],
496  ged_func_ptr func,
497  const char *usage,
498  int maxargs);
499 HIDDEN int to_mouse_poly_ell(struct ged *gedp,
500  int argc,
501  const char *argv[],
502  ged_func_ptr func,
503  const char *usage,
504  int maxargs);
505 HIDDEN int to_mouse_poly_rect(struct ged *gedp,
506  int argc,
507  const char *argv[],
508  ged_func_ptr func,
509  const char *usage,
510  int maxargs);
511 HIDDEN int to_mouse_ray(struct ged *gedp,
512  int argc,
513  const char *argv[],
514  ged_func_ptr func,
515  const char *usage,
516  int maxargs);
517 HIDDEN int to_mouse_rect(struct ged *gedp,
518  int argc,
519  const char *argv[],
520  ged_func_ptr func,
521  const char *usage,
522  int maxargs);
523 HIDDEN int to_mouse_rot(struct ged *gedp,
524  int argc,
525  const char *argv[],
526  ged_func_ptr func,
527  const char *usage,
528  int maxargs);
529 HIDDEN int to_mouse_rotate_arb_face(struct ged *gedp,
530  int argc,
531  const char *argv[],
532  ged_func_ptr func,
533  const char *usage,
534  int maxargs);
535 HIDDEN int to_mouse_data_scale(struct ged *gedp,
536  int argc,
537  const char *argv[],
538  ged_func_ptr func,
539  const char *usage,
540  int maxargs);
541 HIDDEN int to_mouse_scale(struct ged *gedp,
542  int argc,
543  const char *argv[],
544  ged_func_ptr func,
545  const char *usage,
546  int maxargs);
547 HIDDEN int to_mouse_protate(struct ged *gedp,
548  int argc,
549  const char *argv[],
550  ged_func_ptr func,
551  const char *usage,
552  int maxargs);
553 HIDDEN int to_mouse_pscale(struct ged *gedp,
554  int argc,
555  const char *argv[],
556  ged_func_ptr func,
557  const char *usage,
558  int maxargs);
559 HIDDEN int to_mouse_ptranslate(struct ged *gedp,
560  int argc,
561  const char *argv[],
562  ged_func_ptr func,
563  const char *usage,
564  int maxargs);
565 HIDDEN int to_mouse_trans(struct ged *gedp,
566  int argc,
567  const char *argv[],
568  ged_func_ptr func,
569  const char *usage,
570  int maxargs);
571 HIDDEN int to_move_arb_edge_mode(struct ged *gedp,
572  int argc,
573  const char *argv[],
574  ged_func_ptr func,
575  const char *usage,
576  int maxargs);
577 HIDDEN int to_move_arb_face_mode(struct ged *gedp,
578  int argc,
579  const char *argv[],
580  ged_func_ptr func,
581  const char *usage,
582  int maxargs);
583 HIDDEN int to_move_botpt(struct ged *gedp,
584  int argc,
585  const char *argv[],
586  ged_func_ptr func,
587  const char *usage,
588  int maxargs);
589 HIDDEN int to_move_botpts(struct ged *gedp,
590  int argc,
591  const char *argv[],
592  ged_func_ptr func,
593  const char *usage,
594  int maxargs);
595 HIDDEN int to_move_botpt_mode(struct ged *gedp,
596  int argc,
597  const char *argv[],
598  ged_func_ptr func,
599  const char *usage,
600  int maxargs);
601 HIDDEN int to_move_botpts_mode(struct ged *gedp,
602  int argc,
603  const char *argv[],
604  ged_func_ptr func,
605  const char *usage,
606  int maxargs);
607 HIDDEN int to_move_metaballpt_mode(struct ged *gedp,
608  int argc,
609  const char *argv[],
610  ged_func_ptr func,
611  const char *usage,
612  int maxargs);
613 HIDDEN int to_move_pipept_mode(struct ged *gedp,
614  int argc,
615  const char *argv[],
616  ged_func_ptr func,
617  const char *usage,
618  int maxargs);
619 HIDDEN int to_move_pt_common(struct ged *gedp,
620  int argc,
621  const char *argv[],
622  ged_func_ptr func,
623  const char *usage,
624  int maxargs);
625 HIDDEN int to_new_view(struct ged *gedp,
626  int argc,
627  const char *argv[],
628  ged_func_ptr func,
629  const char *usage,
630  int maxargs);
631 HIDDEN int to_orotate_mode(struct ged *gedp,
632  int argc,
633  const char *argv[],
634  ged_func_ptr func,
635  const char *usage,
636  int maxargs);
637 HIDDEN int to_oscale_mode(struct ged *gedp,
638  int argc,
639  const char *argv[],
640  ged_func_ptr func,
641  const char *usage,
642  int maxargs);
643 HIDDEN int to_otranslate_mode(struct ged *gedp,
644  int argc,
645  const char *argv[],
646  ged_func_ptr func,
647  const char *usage,
648  int maxargs);
649 HIDDEN int to_paint_rect_area(struct ged *gedp,
650  int argc,
651  const char *argv[],
652  ged_func_ptr func,
653  const char *usage,
654  int maxargs);
655 #if defined(DM_OGL) || defined(DM_WGL)
656 HIDDEN int to_pix(struct ged *gedp,
657  int argc,
658  const char *argv[],
659  ged_func_ptr func,
660  const char *usage,
661  int maxargs);
662 HIDDEN int to_png(struct ged *gedp,
663  int argc,
664  const char *argv[],
665  ged_func_ptr func,
666  const char *usage,
667  int maxargs);
668 #endif
669 
670 HIDDEN int to_poly_circ_mode(struct ged *gedp,
671  int argc,
672  const char *argv[],
673  ged_func_ptr func,
674  const char *usage,
675  int maxargs);
676 HIDDEN int to_poly_cont_build(struct ged *gedp,
677  int argc,
678  const char *argv[],
679  ged_func_ptr func,
680  const char *usage,
681  int maxargs);
682 HIDDEN int to_poly_cont_build_end(struct ged *gedp,
683  int argc,
684  const char *argv[],
685  ged_func_ptr func,
686  const char *usage,
687  int maxargs);
688 HIDDEN int to_poly_ell_mode(struct ged *gedp,
689  int argc,
690  const char *argv[],
691  ged_func_ptr func,
692  const char *usage,
693  int maxargs);
694 HIDDEN int to_poly_rect_mode(struct ged *gedp,
695  int argc,
696  const char *argv[],
697  ged_func_ptr func,
698  const char *usage,
699  int maxargs);
700 HIDDEN int to_prim_label(struct ged *gedp,
701  int argc,
702  const char *argv[],
703  ged_func_ptr func,
704  const char *usage,
705  int maxargs);
706 HIDDEN int to_redraw(struct ged *gedp,
707  int argc,
708  const char *argv[],
709  ged_func_ptr func,
710  const char *usage,
711  int maxargs);
712 HIDDEN int to_rect_mode(struct ged *gedp,
713  int argc,
714  const char *argv[],
715  ged_func_ptr func,
716  const char *usage,
717  int maxargs);
718 HIDDEN int to_refresh(struct ged *gedp,
719  int argc,
720  const char *argv[],
721  ged_func_ptr func,
722  const char *usage,
723  int maxargs);
724 HIDDEN int to_refresh_all(struct ged *gedp,
725  int argc,
726  const char *argv[],
727  ged_func_ptr func,
728  const char *usage,
729  int maxargs);
730 HIDDEN int to_refresh_on(struct ged *gedp,
731  int argc,
732  const char *argv[],
733  ged_func_ptr func,
734  const char *usage,
735  int maxargs);
736 HIDDEN int to_rotate_arb_face_mode(struct ged *gedp,
737  int argc,
738  const char *argv[],
739  ged_func_ptr func,
740  const char *usage,
741  int maxargs);
742 HIDDEN int to_rotate_mode(struct ged *gedp,
743  int argc,
744  const char *argv[],
745  ged_func_ptr func,
746  const char *usage,
747  int maxargs);
748 HIDDEN int to_rt_end_callback(struct ged *gedp,
749  int argc,
750  const char *argv[],
751  ged_func_ptr func,
752  const char *usage,
753  int maxargs);
754 HIDDEN int to_rt_gettrees(struct ged *gedp,
755  int argc,
756  const char *argv[],
757  ged_func_ptr func,
758  const char *usage,
759  int maxargs);
760 HIDDEN int to_protate_mode(struct ged *gedp,
761  int argc,
762  const char *argv[],
763  ged_func_ptr func,
764  const char *usage,
765  int maxargs);
766 HIDDEN int to_pscale_mode(struct ged *gedp,
767  int argc,
768  const char *argv[],
769  ged_func_ptr func,
770  const char *usage,
771  int maxargs);
772 HIDDEN int to_ptranslate_mode(struct ged *gedp,
773  int argc,
774  const char *argv[],
775  ged_func_ptr func,
776  const char *usage,
777  int maxargs);
778 HIDDEN int to_data_scale_mode(struct ged *gedp,
779  int argc,
780  const char *argv[],
781  ged_func_ptr func,
782  const char *usage,
783  int maxargs);
784 HIDDEN int to_scale_mode(struct ged *gedp,
785  int argc,
786  const char *argv[],
787  ged_func_ptr func,
788  const char *usage,
789  int maxargs);
790 HIDDEN int to_screen2model(struct ged *gedp,
791  int argc,
792  const char *argv[],
793  ged_func_ptr func,
794  const char *usage,
795  int maxargs);
796 HIDDEN int to_screen2view(struct ged *gedp,
797  int argc,
798  const char *argv[],
799  ged_func_ptr func,
800  const char *usage,
801  int maxargs);
802 HIDDEN int to_set_coord(struct ged *gedp,
803  int argc,
804  const char *argv[],
805  ged_func_ptr func,
806  const char *usage,
807  int maxargs);
808 HIDDEN int to_set_fb_mode(struct ged *gedp,
809  int argc,
810  const char *argv[],
811  ged_func_ptr func,
812  const char *usage,
813  int maxargs);
814 HIDDEN int to_snap_view(struct ged *gedp,
815  int argc,
816  const char *argv[],
817  ged_func_ptr func,
818  const char *usage,
819  int maxargs);
820 HIDDEN int to_translate_mode(struct ged *gedp,
821  int argc,
822  const char *argv[],
823  ged_func_ptr func,
824  const char *usage,
825  int maxargs);
826 HIDDEN int to_transparency(struct ged *gedp,
827  int argc,
828  const char *argv[],
829  ged_func_ptr func,
830  const char *usage,
831  int maxargs);
832 HIDDEN int to_view_axes(struct ged *gedp,
833  int argc,
834  const char *argv[],
835  ged_func_ptr func,
836  const char *usage,
837  int maxargs);
838 HIDDEN int to_view_callback(struct ged *gedp,
839  int argc,
840  const char *argv[],
841  ged_func_ptr func,
842  const char *usage,
843  int maxargs);
844 HIDDEN int to_view_win_size(struct ged *gedp,
845  int argc,
846  const char *argv[],
847  ged_func_ptr func,
848  const char *usage,
849  int maxargs);
850 HIDDEN int to_view2screen(struct ged *gedp,
851  int argc,
852  const char *argv[],
853  ged_func_ptr func,
854  const char *usage,
855  int maxargs);
856 HIDDEN int to_vmake(struct ged *gedp,
857  int argc,
858  const char *argv[],
859  ged_func_ptr func,
860  const char *usage,
861  int maxargs);
862 HIDDEN int to_vslew(struct ged *gedp,
863  int argc,
864  const char *argv[],
865  ged_func_ptr func,
866  const char *usage,
867  int maxargs);
868 HIDDEN int to_zbuffer(struct ged *gedp,
869  int argc,
870  const char *argv[],
871  ged_func_ptr func,
872  const char *usage,
873  int maxargs);
874 HIDDEN int to_zclip(struct ged *gedp,
875  int argc,
876  const char *argv[],
877  ged_func_ptr func,
878  const char *usage,
879  int maxargs);
880 
881 /* Wrapper Functions */
882 
883 HIDDEN int to_autoview_func(struct ged *gedp,
884  int argc,
885  const char *argv[],
886  ged_func_ptr func,
887  const char *usage,
888  int maxargs);
889 HIDDEN int to_more_args_func(struct ged *gedp,
890  int argc,
891  const char *argv[],
892  ged_func_ptr func,
893  const char *usage,
894  int maxargs);
895 HIDDEN int to_pass_through_func(struct ged *gedp,
896  int argc,
897  const char *argv[],
898  ged_func_ptr func,
899  const char *usage,
900  int maxargs);
902  int argc,
903  const char *argv[],
904  ged_func_ptr func,
905  const char *usage,
906  int maxargs);
907 HIDDEN int to_view_func(struct ged *gedp,
908  int argc,
909  const char *argv[],
910  ged_func_ptr func,
911  const char *usage,
912  int maxargs);
913 HIDDEN int to_view_func_common(struct ged *gedp,
914  int argc,
915  const char *argv[],
916  ged_func_ptr func,
917  const char *usage,
918  int maxargs,
919  int cflag,
920  int rflag);
921 HIDDEN int to_view_func_less(struct ged *gedp,
922  int argc,
923  const char *argv[],
924  ged_func_ptr func,
925  const char *usage,
926  int maxargs);
927 HIDDEN int to_view_func_plus(struct ged *gedp,
928  int argc,
929  const char *argv[],
930  ged_func_ptr func,
931  const char *usage,
932  int maxargs);
933 HIDDEN int to_dm_func(struct ged *gedp,
934  int argc,
935  const char *argv[],
936  ged_func_ptr func,
937  const char *usage,
938  int maxargs);
939 
940 /* Utility Functions */
941 HIDDEN int to_close_fbs(struct ged_dm_view *gdvp);
942 HIDDEN void to_dm_get_display_image(struct ged *gedp, unsigned char **idata);
943 HIDDEN void to_fbs_callback();
944 HIDDEN int to_open_fbs(struct ged_dm_view *gdvp, Tcl_Interp *interp);
945 
946 HIDDEN void to_create_vlist_callback(struct display_list *gdlp);
947 HIDDEN void to_free_vlist_callback(unsigned int dlist, int range);
949 HIDDEN void to_refresh_view(struct ged_dm_view *gdvp);
950 HIDDEN void to_refresh_handler(void *clientdata);
951 HIDDEN void to_autoview_view(struct ged_dm_view *gdvp, const char *scale);
953 HIDDEN void to_rt_end_callback_internal(int aborted);
954 
955 HIDDEN void to_output_handler(struct ged *gedp, char *line);
956 HIDDEN int to_log_output_handler(void *client_data, void *vpstr);
957 
958 HIDDEN int to_edit_redraw(struct ged *gedp, int argc, const char *argv[]);
959 
960 typedef int (*to_wrapper_func_ptr)(struct ged *, int, const char *[], ged_func_ptr, const char *, int);
961 #define TO_WRAPPER_FUNC_PTR_NULL (to_wrapper_func_ptr)0
962 
963 static struct tclcad_obj HeadTclcadObj;
964 static struct tclcad_obj *current_top = TCLCAD_OBJ_NULL;
965 
968  double dx;
969  double dy;
970  mat_t edit_mat;
971 };
972 
973 struct to_cmdtab {
974  char *to_name;
975  char *to_usage;
978  ged_func_ptr to_func;
979 };
980 
981 
982 static struct to_cmdtab to_cmds[] = {
983  {"3ptarb", (char *)0, TO_UNLIMITED, to_more_args_func, ged_3ptarb},
984  {"adc", "args", 7, to_view_func, ged_adc},
985  {"adjust", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_adjust},
986  {"ae2dir", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_ae2dir},
987  {"aet", "[[-i] az el [tw]]", 6, to_view_func_plus, ged_aet},
988  {"analyze", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_analyze},
989  {"annotate", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_annotate},
990  {"append_pipept", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_append_pipept},
991  {"arb", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_arb},
992  {"arced", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_arced},
993  {"arot", "x y z angle", 6, to_view_func_plus, ged_arot},
994  {"attr", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_attr},
995  {"autoview", "vname", TO_UNLIMITED, to_autoview, GED_FUNC_PTR_NULL},
996  {"bb", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bb},
997  {"bev", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bev},
998  {"base2local", (char *)0, TO_UNLIMITED, to_base2local, GED_FUNC_PTR_NULL},
999  {"bg", "[r g b]", TO_UNLIMITED, to_bg, GED_FUNC_PTR_NULL},
1000  {"blast", (char *)0, TO_UNLIMITED, to_blast, GED_FUNC_PTR_NULL},
1001  {"bo", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bo},
1002  {"bot", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot},
1003  {"bot_condense", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_condense},
1004  {"bot_decimate", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_decimate},
1005  {"bot_dump", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_dump},
1006  {"bot_face_fuse", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_face_fuse},
1007  {"bot_face_sort", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_face_sort},
1008  {"bot_edge_split", "bot face", TO_UNLIMITED, to_bot_edge_split, GED_FUNC_PTR_NULL},
1009  {"bot_face_split", "bot face", TO_UNLIMITED, to_bot_face_split, GED_FUNC_PTR_NULL},
1010  {"bot_flip", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_flip},
1011  {"bot_fuse", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_fuse},
1012  {"bot_merge", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_merge},
1013  {"bot_smooth", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_smooth},
1014  {"bot_split", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_split},
1015  {"bot_sync", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_sync},
1016  {"bot_vertex_fuse", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_bot_vertex_fuse},
1017  {"bounds", "[\"minX maxX minY maxY minZ maxZ\"]", TO_UNLIMITED, to_bounds, GED_FUNC_PTR_NULL},
1018  {"brep", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_brep},
1019  {"c", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_comb_std},
1020  {"cat", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_cat},
1021  {"center", "[x y z]", 5, to_view_func_plus, ged_center},
1022  {"clear", (char *)0, TO_UNLIMITED, to_pass_through_and_refresh_func, ged_zap},
1023  {"clone", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_clone},
1024  {"coil", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_coil},
1025  {"color", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_color},
1026  {"comb", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_comb},
1027  {"comb_color", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_comb_color},
1028  {"combmem", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_combmem},
1029  {"configure", "vname", TO_UNLIMITED, to_configure, GED_FUNC_PTR_NULL},
1030  {"constrain_rmode", "x|y|z x y", TO_UNLIMITED, to_constrain_rmode, GED_FUNC_PTR_NULL},
1031  {"constrain_tmode", "x|y|z x y", TO_UNLIMITED, to_constrain_tmode, GED_FUNC_PTR_NULL},
1032  {"constraint", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_constraint},
1033  {"copyeval", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_copyeval},
1034  {"copymat", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_copymat},
1035  {"cp", "[-f] from to", TO_UNLIMITED, to_copy, GED_FUNC_PTR_NULL},
1036  {"cpi", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_cpi},
1038  {"data_arrows", "???", TO_UNLIMITED, to_data_arrows, GED_FUNC_PTR_NULL},
1039  {"data_axes", "???", TO_UNLIMITED, to_data_axes, GED_FUNC_PTR_NULL},
1040  {"data_labels", "???", TO_UNLIMITED, to_data_labels, GED_FUNC_PTR_NULL},
1041  {"data_lines", "???", TO_UNLIMITED, to_data_lines, GED_FUNC_PTR_NULL},
1042  {"data_polygons", "???", TO_UNLIMITED, to_data_polygons, GED_FUNC_PTR_NULL},
1043  {"data_move", "???", TO_UNLIMITED, to_data_move, GED_FUNC_PTR_NULL},
1044  {"data_move_object_mode", "x y", TO_UNLIMITED, to_data_move_object_mode, GED_FUNC_PTR_NULL},
1045  {"data_move_point_mode", "x y", TO_UNLIMITED, to_data_move_point_mode, GED_FUNC_PTR_NULL},
1046  {"data_pick", "???", TO_UNLIMITED, to_data_pick, GED_FUNC_PTR_NULL},
1047  {"data_scale_mode", "x y", TO_UNLIMITED, to_data_scale_mode, GED_FUNC_PTR_NULL},
1048  {"data_vZ", "[z]", TO_UNLIMITED, to_data_vZ, GED_FUNC_PTR_NULL},
1049  {"dbconcat", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_concat},
1050  {"dbfind", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_find},
1051  {"dbip", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_dbip},
1052  {"dbot_dump", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_dbot_dump},
1053  {"debugbu", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_debugbu},
1054  {"debugdir", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_debugdir},
1055  {"debuglib", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_debuglib},
1056  {"debugmem", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_debugmem},
1057  {"debugnmg", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_debugnmg},
1058  {"decompose", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_decompose},
1059  {"delay", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_delay},
1060  {"delete_metaballpt", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_delete_metaballpt},
1061  {"delete_pipept", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_delete_pipept},
1062  {"delete_view", "vname", TO_UNLIMITED, to_delete_view, GED_FUNC_PTR_NULL},
1063  {"dir2ae", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_dir2ae},
1064  {"dlist_on", "[0|1]", TO_UNLIMITED, to_dlist_on, GED_FUNC_PTR_NULL},
1065  {"draw", (char *)0, TO_UNLIMITED, to_autoview_func, ged_draw},
1066  {"dump", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_dump},
1067  {"dup", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_dup},
1068  {"E", (char *)0, TO_UNLIMITED, to_autoview_func, ged_E},
1069  {"e", (char *)0, TO_UNLIMITED, to_autoview_func, ged_draw},
1070  {"eac", (char *)0, TO_UNLIMITED, to_autoview_func, ged_eac},
1071  {"echo", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_echo},
1072  {"edarb", (char *)0, TO_UNLIMITED, to_more_args_func, ged_edarb},
1073  {"edcodes", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_edcodes},
1074  {"edcolor", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_edcolor},
1075  {"edcomb", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_edcomb},
1076  {"edit", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_edit},
1077  {"edmater", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_edmater},
1079  {"ev", (char *)0, TO_UNLIMITED, to_autoview_func, ged_ev},
1080  {"expand", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_expand},
1081  {"eye", "[x y z]", 5, to_view_func_plus, ged_eye},
1082  {"eye_pos", "[x y z]", 5, to_view_func_plus, ged_eye_pos},
1083  {"eye_pt", "[x y z]", 5, to_view_func_plus, ged_eye},
1084  {"exists", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_exists},
1085  {"faceplate", "center_dot|prim_labels|view_params|view_scale color|draw [val(s)]", TO_UNLIMITED, to_faceplate, GED_FUNC_PTR_NULL},
1086  {"facetize", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_facetize},
1087  {"voxelize", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_voxelize},
1088  {"fb2pix", "[-h -i -c] [-s squaresize] [-w width] [-n height] [file.pix]", TO_UNLIMITED, to_view_func, ged_fb2pix},
1089  {"fbclear", "[r g b]", TO_UNLIMITED, to_view_func, ged_fbclear},
1090  {"find_arb_edge", "arb vx vy ptol", 5, to_view_func, ged_find_arb_edge_nearest_pt},
1091  {"find_bot_edge", "bot vx vy", 5, to_view_func, ged_find_bot_edge_nearest_pt},
1092  {"find_botpt", "bot vx vy", 5, to_view_func, ged_find_botpt_nearest_pt},
1093  {"find_pipept", "pipe x y z", 6, to_view_func, ged_find_pipept_nearest_pt},
1094  {"fontsize", "[fontsize]", 3, to_fontsize, GED_FUNC_PTR_NULL},
1095  {"form", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_form},
1096  {"fracture", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_fracture},
1097  {"g", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_group},
1098  {"gdiff", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_gdiff},
1099  {"get", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_get},
1100  {"get_autoview", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_get_autoview},
1101  {"get_bot_edges", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_get_bot_edges},
1102  {"get_comb", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_get_comb},
1103  {"get_eyemodel", "vname", 2, to_view_func, ged_get_eyemodel},
1104  {"get_prev_mouse", "vname", TO_UNLIMITED, to_get_prev_mouse, GED_FUNC_PTR_NULL},
1105  {"get_type", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_get_type},
1106  {"glob", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_glob},
1107  {"gqa", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_gqa},
1108  {"graph", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_graph},
1109  {"grid", "args", 6, to_view_func, ged_grid},
1110  {"grid2model_lu", "x y", 4, to_view_func_less, ged_grid2model_lu},
1111  {"grid2view_lu", "x y", 4, to_view_func_less, ged_grid2view_lu},
1112  {"handle_expose", "vname count", TO_UNLIMITED, to_handle_expose, GED_FUNC_PTR_NULL},
1113  {"hide", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_hide},
1114  {"hide_view", "vname [0|1]", 3, to_hide_view, GED_FUNC_PTR_NULL},
1115  {"how", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_how},
1116  {"human", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_human},
1117  {"i", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_instance},
1118  {"idents", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_tables},
1119  {"idle_mode", "vname", TO_UNLIMITED, to_idle_mode, GED_FUNC_PTR_NULL},
1121  {"importFg4Section", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_importFg4Section},
1122  {"in", (char *)0, TO_UNLIMITED, to_more_args_func, ged_in},
1123  {"init_view_bindings", "vname", TO_UNLIMITED, to_init_view_bindings, GED_FUNC_PTR_NULL},
1124  {"inside", (char *)0, TO_UNLIMITED, to_more_args_func, ged_inside},
1125  {"isize", "vname", 2, to_view_func, ged_isize},
1126  {"item", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_item},
1127  {"joint", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_joint},
1128  {"joint2", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_joint2},
1129  {"keep", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_keep},
1130  {"keypoint", "[x y z]", 5, to_view_func, ged_keypoint},
1132  {"killall", (char *)0, TO_UNLIMITED, to_pass_through_and_refresh_func, ged_killall},
1133  {"killrefs", (char *)0, TO_UNLIMITED, to_pass_through_and_refresh_func, ged_killrefs},
1134  {"killtree", (char *)0, TO_UNLIMITED, to_pass_through_and_refresh_func, ged_killtree},
1135  {"l", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_list},
1136  {"lc", "[-d|-s|-r] [-z] [-0|-1|-2|-3|-4|-5] [-f {FileName}] {GroupName}", TO_UNLIMITED, to_pass_through_func, ged_lc},
1137  {"light", "[0|1]", TO_UNLIMITED, to_light, GED_FUNC_PTR_NULL},
1138  {"list_views", (char *)0, TO_UNLIMITED, to_list_views, GED_FUNC_PTR_NULL},
1139  {"listen", "[port]", TO_UNLIMITED, to_listen, GED_FUNC_PTR_NULL},
1140  {"listeval", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_pathsum},
1141  {"loadview", "filename", 3, to_view_func, ged_loadview},
1142  {"local2base", (char *)0, TO_UNLIMITED, to_local2base, GED_FUNC_PTR_NULL},
1143  {"lod", (char *)0, TO_UNLIMITED, to_lod, ged_lod},
1144  {"log", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_log},
1145  {"lookat", "x y z", 5, to_view_func_plus, ged_lookat},
1146  {"ls", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_ls},
1147  {"lt", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_lt},
1148  {"m2v_point", "x y z", 5, to_view_func, ged_m2v_point},
1149  {"make", (char *)0, TO_UNLIMITED, to_make, GED_FUNC_PTR_NULL},
1150  {"make_name", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_make_name},
1151  {"make_pnts", (char *)0, TO_UNLIMITED, to_more_args_func, ged_make_pnts},
1152  {"match", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_match},
1153  {"mater", (char *)0, TO_UNLIMITED, to_more_args_func, ged_mater},
1154  {"memprint", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_memprint},
1155  {"mirror", (char *)0, TO_UNLIMITED, to_mirror, GED_FUNC_PTR_NULL},
1156  {"model2grid_lu", "x y z", 5, to_view_func_less, ged_model2grid_lu},
1157  {"model2view", "vname", 2, to_view_func, ged_model2view},
1158  {"model2view_lu", "x y z", 5, to_view_func_less, ged_model2view_lu},
1159  {"model_axes", "???", TO_UNLIMITED, to_model_axes, GED_FUNC_PTR_NULL},
1160  {"edit_motion_delta_callback", "vname [args]", TO_UNLIMITED, to_edit_motion_delta_callback, GED_FUNC_PTR_NULL},
1161  {"more_args_callback", "set/get the \"more args\" callback", TO_UNLIMITED, to_more_args_callback, GED_FUNC_PTR_NULL},
1162  {"move_arb_edge", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_move_arb_edge},
1163  {"move_arb_edge_mode", "obj edge x y", TO_UNLIMITED, to_move_arb_edge_mode, GED_FUNC_PTR_NULL},
1164  {"move_arb_face", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_move_arb_face},
1165  {"move_arb_face_mode", "obj face x y", TO_UNLIMITED, to_move_arb_face_mode, GED_FUNC_PTR_NULL},
1166  {"move_botpt", (char *)0, TO_UNLIMITED, to_move_botpt, GED_FUNC_PTR_NULL},
1167  {"move_botpts", (char *)0, TO_UNLIMITED, to_move_botpts, GED_FUNC_PTR_NULL},
1168  {"move_botpt_mode", "obj i mx my", TO_UNLIMITED, to_move_botpt_mode, GED_FUNC_PTR_NULL},
1169  {"move_botpts_mode", "mx my obj i1 [i2 ... iN]", TO_UNLIMITED, to_move_botpts_mode, GED_FUNC_PTR_NULL},
1170  {"move_metaballpt", (char *)0, TO_UNLIMITED, to_move_pt_common, ged_move_metaballpt},
1171  {"move_metaballpt_mode", "obj pt_i mx my", TO_UNLIMITED, to_move_metaballpt_mode, GED_FUNC_PTR_NULL},
1172  {"move_pipept", (char *)0, TO_UNLIMITED, to_move_pt_common, ged_move_pipept},
1173  {"move_pipept_mode", "obj seg_i mx my", TO_UNLIMITED, to_move_pipept_mode, GED_FUNC_PTR_NULL},
1174  {"mouse_add_metaballpt", "obj mx my", TO_UNLIMITED, to_mouse_append_pt_common, ged_add_metaballpt},
1175  {"mouse_append_pipept", "obj mx my", TO_UNLIMITED, to_mouse_append_pt_common, ged_append_pipept},
1176  {"mouse_brep_selection_append", "obj mx my", 5, to_mouse_brep_selection_append, GED_FUNC_PTR_NULL},
1177  {"mouse_brep_selection_translate", "obj mx my", 5, to_mouse_brep_selection_translate, GED_FUNC_PTR_NULL},
1178  {"mouse_constrain_rot", "coord mx my", TO_UNLIMITED, to_mouse_constrain_rot, GED_FUNC_PTR_NULL},
1179  {"mouse_constrain_trans", "coord mx my", TO_UNLIMITED, to_mouse_constrain_trans, GED_FUNC_PTR_NULL},
1180  {"mouse_data_scale", "mx my", TO_UNLIMITED, to_mouse_data_scale, GED_FUNC_PTR_NULL},
1181  {"mouse_find_arb_edge", "obj mx my ptol", TO_UNLIMITED, to_mouse_find_arb_edge, GED_FUNC_PTR_NULL},
1182  {"mouse_find_bot_edge", "obj mx my", TO_UNLIMITED, to_mouse_find_bot_edge, GED_FUNC_PTR_NULL},
1183  {"mouse_find_botpt", "obj mx my", TO_UNLIMITED, to_mouse_find_botpt, GED_FUNC_PTR_NULL},
1184  {"mouse_find_metaballpt", "obj mx my", TO_UNLIMITED, to_mouse_find_metaballpt, GED_FUNC_PTR_NULL},
1185  {"mouse_find_pipept", "obj mx my", TO_UNLIMITED, to_mouse_find_pipept, GED_FUNC_PTR_NULL},
1186  {"mouse_joint_select", "obj mx my", 5, to_mouse_joint_select, GED_FUNC_PTR_NULL},
1187  {"mouse_joint_selection_translate", "obj mx my", 5, to_mouse_joint_selection_translate, GED_FUNC_PTR_NULL},
1188  {"mouse_move_arb_edge", "obj edge mx my", TO_UNLIMITED, to_mouse_move_arb_edge, GED_FUNC_PTR_NULL},
1189  {"mouse_move_arb_face", "obj face mx my", TO_UNLIMITED, to_mouse_move_arb_face, GED_FUNC_PTR_NULL},
1190  {"mouse_move_botpt", "[-r] obj i mx my", TO_UNLIMITED, to_mouse_move_botpt, GED_FUNC_PTR_NULL},
1191  {"mouse_move_botpts", "mx my obj i1 [i2 ... iN]", TO_UNLIMITED, to_mouse_move_botpts, GED_FUNC_PTR_NULL},
1192  {"mouse_move_metaballpt", "obj i mx my", TO_UNLIMITED, to_mouse_move_pt_common, ged_move_metaballpt},
1193  {"mouse_move_pipept", "obj i mx my", TO_UNLIMITED, to_mouse_move_pt_common, ged_move_pipept},
1194  {"mouse_orotate", "obj mx my", TO_UNLIMITED, to_mouse_orotate, GED_FUNC_PTR_NULL},
1195  {"mouse_oscale", "obj mx my", TO_UNLIMITED, to_mouse_oscale, GED_FUNC_PTR_NULL},
1196  {"mouse_otranslate", "obj mx my", TO_UNLIMITED, to_mouse_otranslate, GED_FUNC_PTR_NULL},
1197  {"mouse_poly_circ", "mx my", TO_UNLIMITED, to_mouse_poly_circ, GED_FUNC_PTR_NULL},
1198  {"mouse_poly_cont", "mx my", TO_UNLIMITED, to_mouse_poly_cont, GED_FUNC_PTR_NULL},
1199  {"mouse_poly_ell", "mx my", TO_UNLIMITED, to_mouse_poly_ell, GED_FUNC_PTR_NULL},
1200  {"mouse_poly_rect", "mx my", TO_UNLIMITED, to_mouse_poly_rect, GED_FUNC_PTR_NULL},
1201  {"mouse_prepend_pipept", "obj mx my", TO_UNLIMITED, to_mouse_append_pt_common, ged_prepend_pipept},
1202  {"mouse_ray", "mx my", TO_UNLIMITED, to_mouse_ray, GED_FUNC_PTR_NULL},
1203  {"mouse_rect", "mx my", TO_UNLIMITED, to_mouse_rect, GED_FUNC_PTR_NULL},
1204  {"mouse_rot", "mx my", TO_UNLIMITED, to_mouse_rot, GED_FUNC_PTR_NULL},
1205  {"mouse_rotate_arb_face", "obj face v mx my", TO_UNLIMITED, to_mouse_rotate_arb_face, GED_FUNC_PTR_NULL},
1206  {"mouse_scale", "mx my", TO_UNLIMITED, to_mouse_scale, GED_FUNC_PTR_NULL},
1207  {"mouse_protate", "obj attribute mx my", TO_UNLIMITED, to_mouse_protate, GED_FUNC_PTR_NULL},
1208  {"mouse_pscale", "obj attribute mx my", TO_UNLIMITED, to_mouse_pscale, GED_FUNC_PTR_NULL},
1209  {"mouse_ptranslate", "obj attribute mx my", TO_UNLIMITED, to_mouse_ptranslate, GED_FUNC_PTR_NULL},
1210  {"mouse_trans", "mx my", TO_UNLIMITED, to_mouse_trans, GED_FUNC_PTR_NULL},
1211  {"mv", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_move},
1212  {"mvall", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_move_all},
1213  {"new_view", "vname type [args]", TO_UNLIMITED, to_new_view, GED_FUNC_PTR_NULL},
1214  {"nirt", "[args]", TO_UNLIMITED, to_view_func, ged_nirt},
1215  {"nmg_collapse", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_nmg_collapse},
1216  {"nmg_fix_normals", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_nmg_fix_normals},
1217  {"nmg_simplify", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_nmg_simplify},
1218  {"ocenter", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_ocenter},
1220  {"orient", "quat", 6, to_view_func_plus, ged_orient},
1221  {"orientation", "quat", 6, to_view_func_plus, ged_orient},
1222  {"orotate", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_orotate},
1223  {"orotate_mode", "obj x y", TO_UNLIMITED, to_orotate_mode, GED_FUNC_PTR_NULL},
1224  {"oscale", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_oscale},
1225  {"oscale_mode", "obj x y", TO_UNLIMITED, to_oscale_mode, GED_FUNC_PTR_NULL},
1226  {"otranslate", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_otranslate},
1227  {"otranslate_mode", "obj x y", TO_UNLIMITED, to_otranslate_mode, GED_FUNC_PTR_NULL},
1228  {"overlay", (char *)0, TO_UNLIMITED, to_autoview_func, ged_overlay},
1229  {"paint_rect_area", "vname", TO_UNLIMITED, to_paint_rect_area, GED_FUNC_PTR_NULL},
1230  {"pathlist", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_pathlist},
1231  {"paths", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_pathsum},
1232  {"perspective", "[angle]", 3, to_view_func_plus, ged_perspective},
1233  {"pix2fb", "[options] [file.pix]", TO_UNLIMITED, to_view_func, ged_pix2fb},
1234  {"plot", "[options] file.pl", 16, to_view_func, ged_plot},
1235  {"pmat", "[mat]", 3, to_view_func, ged_pmat},
1236  {"pmodel2view", "vname", 2, to_view_func, ged_pmodel2view},
1237 #if defined(DM_OGL) || defined(DM_WGL)
1238  {"pix", "file", TO_UNLIMITED, to_pix, GED_FUNC_PTR_NULL},
1239  {"png", "file", TO_UNLIMITED, to_png, GED_FUNC_PTR_NULL},
1240 #endif
1241  {"pngwf", "[options] file.png", 16, to_view_func, ged_png},
1242  {"poly_circ_mode", "x y", TO_UNLIMITED, to_poly_circ_mode, GED_FUNC_PTR_NULL},
1243  {"poly_cont_build", "x y", TO_UNLIMITED, to_poly_cont_build, GED_FUNC_PTR_NULL},
1244  {"poly_cont_build_end", "y", TO_UNLIMITED, to_poly_cont_build_end, GED_FUNC_PTR_NULL},
1245  {"poly_ell_mode", "x y", TO_UNLIMITED, to_poly_ell_mode, GED_FUNC_PTR_NULL},
1246  {"poly_rect_mode", "x y [s]", TO_UNLIMITED, to_poly_rect_mode, GED_FUNC_PTR_NULL},
1247  {"polybinout", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_polybinout},
1248  {"pov", "center quat scale eye_pos perspective", 7, to_view_func_plus, ged_pmat},
1249  {"prcolor", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_prcolor},
1250  {"prefix", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_prefix},
1251  {"prepend_pipept", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_prepend_pipept},
1252  {"preview", "[options] script", TO_UNLIMITED, to_dm_func, ged_preview},
1253  {"prim_label", "[prim_1 prim_2 ... prim_N]", TO_UNLIMITED, to_prim_label, GED_FUNC_PTR_NULL},
1254  {"protate", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_protate},
1255  {"protate_mode", "obj attribute x y", TO_UNLIMITED, to_protate_mode, GED_FUNC_PTR_NULL},
1256  {"ps", "[options] file.ps", 16, to_view_func, ged_ps},
1257  {"pscale", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_pscale},
1258  {"pscale_mode", "obj attribute x y", TO_UNLIMITED, to_pscale_mode, GED_FUNC_PTR_NULL},
1259  {"pset", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_pset},
1260  {"ptranslate", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_ptranslate},
1261  {"ptranslate_mode", "obj attribute x y", TO_UNLIMITED, to_ptranslate_mode, GED_FUNC_PTR_NULL},
1262  {"push", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_push},
1263  {"put", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_put},
1264  {"put_comb", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_put_comb},
1265  {"putmat", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_putmat},
1266  {"qray", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_qray},
1267  {"quat", "a b c d", 6, to_view_func_plus, ged_quat},
1268  {"qvrot", "x y z angle", 6, to_view_func_plus, ged_qvrot},
1269  {"r", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_region},
1270  {"rcodes", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_rcodes},
1271  {"rect", "args", 6, to_view_func, ged_rect},
1272  {"rect_mode", "x y", TO_UNLIMITED, to_rect_mode, GED_FUNC_PTR_NULL},
1273  {"red", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_red},
1274  {"redraw", "obj", 2, to_redraw, GED_FUNC_PTR_NULL},
1275  {"refresh", "vname", TO_UNLIMITED, to_refresh, GED_FUNC_PTR_NULL},
1276  {"refresh_all", (char *)0, TO_UNLIMITED, to_refresh_all, GED_FUNC_PTR_NULL},
1277  {"refresh_on", "[0|1]", TO_UNLIMITED, to_refresh_on, GED_FUNC_PTR_NULL},
1278  {"regdef", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_regdef},
1279  {"regions", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_tables},
1280  {"report", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_report},
1281  {"rfarb", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_rfarb},
1283  {"rmap", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_rmap},
1284  {"rmat", "[mat]", 3, to_view_func, ged_rmat},
1285  {"rmater", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_rmater},
1286  {"rot", "[-m|-v] x y z", 6, to_view_func_plus, ged_rot},
1287  {"rot_about", "[e|k|m|v]", 3, to_view_func, ged_rotate_about},
1288  {"rot_point", "x y z", 5, to_view_func, ged_rot_point},
1289  {"rotate_arb_face", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_rotate_arb_face},
1290  {"rotate_arb_face_mode", "obj face v x y", TO_UNLIMITED, to_rotate_arb_face_mode, GED_FUNC_PTR_NULL},
1291  {"rotate_mode", "x y", TO_UNLIMITED, to_rotate_mode, GED_FUNC_PTR_NULL},
1292  {"rrt", "[args]", TO_UNLIMITED, to_view_func, ged_rrt},
1293  {"rselect", (char *)0, TO_UNLIMITED, to_view_func, ged_rselect},
1294  {"rt", "[args]", TO_UNLIMITED, to_view_func, ged_rt},
1295  {"rt_end_callback", "[args]", TO_UNLIMITED, to_rt_end_callback, GED_FUNC_PTR_NULL},
1296  {"rt_gettrees", "[-i] [-u] pname object", TO_UNLIMITED, to_rt_gettrees, GED_FUNC_PTR_NULL},
1297  {"rtabort", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_rtabort},
1298  {"rtarea", "[args]", TO_UNLIMITED, to_view_func, ged_rt},
1299  {"rtcheck", "[args]", TO_UNLIMITED, to_view_func, ged_rtcheck},
1300  {"rtedge", "[args]", TO_UNLIMITED, to_view_func, ged_rt},
1301  {"rtweight", "[args]", TO_UNLIMITED, to_view_func, ged_rt},
1302  {"rtwizard", "[args]", TO_UNLIMITED, to_view_func, ged_rtwizard},
1303  {"savekey", "filename", 3, to_view_func, ged_savekey},
1304  {"saveview", "filename", 3, to_view_func, ged_saveview},
1305  {"sca", "sf", 3, to_view_func_plus, ged_scale},
1306  {"scale_mode", "x y", TO_UNLIMITED, to_scale_mode, GED_FUNC_PTR_NULL},
1307  {"screen2model", "x y", TO_UNLIMITED, to_screen2model, GED_FUNC_PTR_NULL},
1308  {"screen2view", "x y", TO_UNLIMITED, to_screen2view, GED_FUNC_PTR_NULL},
1309  {"screengrab", "imagename.ext", TO_UNLIMITED, to_dm_func, ged_screen_grab},
1310  {"sdata_arrows", "???", TO_UNLIMITED, to_data_arrows, GED_FUNC_PTR_NULL},
1311  {"sdata_axes", "???", TO_UNLIMITED, to_data_axes, GED_FUNC_PTR_NULL},
1312  {"sdata_labels", "???", TO_UNLIMITED, to_data_labels, GED_FUNC_PTR_NULL},
1313  {"sdata_lines", "???", TO_UNLIMITED, to_data_lines, GED_FUNC_PTR_NULL},
1314  {"sdata_polygons", "???", TO_UNLIMITED, to_data_polygons, GED_FUNC_PTR_NULL},
1315  {"search", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_search},
1316  {"select", (char *)0, TO_UNLIMITED, to_view_func, ged_select},
1317  {"set_coord", "[m|v]", TO_UNLIMITED, to_set_coord, GED_FUNC_PTR_NULL},
1318  {"set_fb_mode", "[mode]", TO_UNLIMITED, to_set_fb_mode, GED_FUNC_PTR_NULL},
1319  {"set_output_script", "[script]", TO_UNLIMITED, to_pass_through_func, ged_set_output_script},
1320  {"set_transparency", (char *)0, TO_UNLIMITED, to_pass_through_and_refresh_func, ged_set_transparency},
1321  {"set_uplotOutputMode", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_set_uplotOutputMode},
1322  {"setview", "x y z", 5, to_view_func_plus, ged_setview},
1323  {"shaded_mode", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_shaded_mode},
1324  {"shader", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_shader},
1325  {"shells", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_shells},
1326  {"showmats", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_showmats},
1327  {"size", "[size]", 3, to_view_func_plus, ged_size},
1328  {"slew", "x y [z]", 5, to_view_func_plus, ged_slew},
1329  {"snap_view", "vx vy", 4, to_snap_view, GED_FUNC_PTR_NULL},
1330  {"solids", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_tables},
1331  {"solids_on_ray", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_solids_on_ray},
1332  {"summary", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_summary},
1333  {"sv", "x y [z]", 5, to_view_func_plus, ged_slew},
1334  {"sync", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_sync},
1335  {"t", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_ls},
1336  {"tire", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_tire},
1337  {"title", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_title},
1338  {"tol", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_tol},
1339  {"tops", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_tops},
1340  {"tra", "[-m|-v] x y z", 6, to_view_func_plus, ged_tra},
1341  {"track", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_track},
1342  {"translate_mode", "x y", TO_UNLIMITED, to_translate_mode, GED_FUNC_PTR_NULL},
1343  {"transparency", "[val]", TO_UNLIMITED, to_transparency, GED_FUNC_PTR_NULL},
1344  {"tree", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_tree},
1345  {"unhide", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_unhide},
1346  {"units", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_units},
1347  {"v2m_point", "x y z", 5, to_view_func, ged_v2m_point},
1349  {"version", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_version},
1350  {"view", "quat|ypr|aet|center|eye|size [args]", 7, to_view_func_plus, ged_view_func},
1351  {"view_axes", "vname [args]", TO_UNLIMITED, to_view_axes, GED_FUNC_PTR_NULL},
1352  {"view_callback", "vname [args]", TO_UNLIMITED, to_view_callback, GED_FUNC_PTR_NULL},
1353  {"view_win_size", "[s] | [x y]", 4, to_view_win_size, GED_FUNC_PTR_NULL},
1354  {"view2grid_lu", "x y z", 5, to_view_func_less, ged_view2grid_lu},
1355  {"view2model", "", 2, to_view_func_less, ged_view2model},
1356  {"view2model_lu", "x y z", 5, to_view_func_less, ged_view2model_lu},
1357  {"view2model_vec", "x y z", 5, to_view_func_less, ged_view2model_vec},
1358  {"view2screen", "", 2, to_view2screen, GED_FUNC_PTR_NULL},
1359  {"viewdir", "[-i]", 3, to_view_func_less, ged_viewdir},
1360  {"vmake", "pname ptype", TO_UNLIMITED, to_vmake, GED_FUNC_PTR_NULL},
1361  {"vnirt", "[args]", TO_UNLIMITED, to_view_func, ged_vnirt},
1362  {"vslew", "x y", TO_UNLIMITED, to_vslew, GED_FUNC_PTR_NULL},
1363  {"wcodes", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_wcodes},
1364  {"whatid", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_whatid},
1365  {"which_shader", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_which_shader},
1366  {"whichair", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_which},
1367  {"whichid", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_which},
1368  {"who", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_who},
1369  {"wmater", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_wmater},
1370  {"x", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_report},
1371  {"xpush", (char *)0, TO_UNLIMITED, to_pass_through_func, ged_xpush},
1372  {"ypr", "yaw pitch roll", 5, to_view_func_plus, ged_ypr},
1374  {"zbuffer", "[0|1]", TO_UNLIMITED, to_zbuffer, GED_FUNC_PTR_NULL},
1375  {"zclip", "[0|1]", TO_UNLIMITED, to_zclip, GED_FUNC_PTR_NULL},
1376  {"zoom", "sf", 3, to_view_func_plus, ged_zoom},
1377  {(char *)0, (char *)0, 0, TO_WRAPPER_FUNC_PTR_NULL, GED_FUNC_PTR_NULL}
1378 };
1379 
1380 
1381 static fastf_t
1382 screen_to_view_x(dm *dmp, fastf_t x)
1383 {
1384  int width = dm_get_width(dmp);
1385  return x / (fastf_t)width * 2.0 - 1.0;
1386 }
1387 
1388 
1389 static fastf_t
1390 screen_to_view_y(dm *dmp, fastf_t y)
1391 {
1392  int height = dm_get_height(dmp);
1393  return (y / (fastf_t)height * -2.0 + 1.0) / dm_get_aspect(dmp);
1394 }
1395 
1396 
1397 /**
1398  * @brief
1399  * A TCL interface to dm_list_types()).
1400  *
1401  * @return a list of available dm types.
1402  */
1403 int
1404 dm_list_tcl(ClientData UNUSED(clientData),
1405  Tcl_Interp *interp,
1406  int UNUSED(argc),
1407  const char **UNUSED(argv))
1408 {
1409  struct bu_vls *list = dm_list_types(',');
1410  Tcl_SetResult(interp, bu_vls_addr(list), TCL_VOLATILE);
1411  bu_vls_free(list);
1412  BU_PUT(list, struct bu_vls);
1413  return TCL_OK;
1414 }
1415 
1416 /**
1417  * @brief create the Tcl command for to_open
1418  *
1419  */
1420 int
1421 Go_Init(Tcl_Interp *interp)
1422 {
1423  if (library_initialized(0))
1424  return TCL_OK;
1425 
1426  {
1427  const char *version_str = brlcad_version();
1428  tclcad_eval_noresult(interp, "set brlcad_version", 1, &version_str);
1429  }
1430 
1431  /*XXX Use of brlcad_interp is temporary */
1433 
1434  BU_LIST_INIT(&HeadTclcadObj.l);
1435  (void)Tcl_CreateCommand(interp, (const char *)"go_open", to_open_tcl,
1436  (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
1437 
1438  (void)Tcl_CreateCommand(interp, (const char *)"dm_list", dm_list_tcl,
1439  (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
1440 
1441  (void)library_initialized(1);
1442 
1443  return TCL_OK;
1444 }
1445 
1446 
1447 /**
1448  * @brief
1449  * Generic interface for database commands.
1450  *
1451  * @par Usage:
1452  * procname cmd ?args?
1453  *
1454  * @return result of ged command.
1455  */
1456 HIDDEN int
1457 to_cmd(ClientData clientData,
1458  Tcl_Interp *interp,
1459  int argc,
1460  char **argv)
1461 {
1462  register struct to_cmdtab *ctp;
1463  struct tclcad_obj *top = (struct tclcad_obj *)clientData;
1464  Tcl_DString ds;
1465  int ret = GED_ERROR;
1466 
1467  Tcl_DStringInit(&ds);
1468 
1469  if (argc < 2) {
1470  Tcl_DStringAppend(&ds, "subcommand not specified; must be one of: ", -1);
1471  for (ctp = to_cmds; ctp->to_name != (char *)NULL; ctp++) {
1472  Tcl_DStringAppend(&ds, " ", -1);
1473  Tcl_DStringAppend(&ds, ctp->to_name, -1);
1474  }
1475  Tcl_DStringAppend(&ds, "\n", -1);
1476  Tcl_DStringResult(interp, &ds);
1477 
1478  return TCL_ERROR;
1479  }
1480 
1481  current_top = top;
1482 
1483  for (ctp = to_cmds; ctp->to_name != (char *)0; ctp++) {
1484  if (ctp->to_name[0] == argv[1][0] &&
1485  BU_STR_EQUAL(ctp->to_name, argv[1])) {
1486  struct ged *gedp = top->to_gop->go_gedp;
1487 
1488  /* temporarily comment out the bu_log() hook due to threaded command
1489  * output being slightly tricky; Tcl_Interp objects can only be used
1490  * by the thread which created them.
1491  */
1492 
1493  /* bu_log_add_hook(to_log_output_handler, (void *)gedp); */
1494  ret = (*ctp->to_wrapper_func)(gedp, argc-1, (const char **)argv+1, ctp->to_func, ctp->to_usage, ctp->to_maxargs);
1495  /* bu_log_delete_hook(to_log_output_handler, (void *)gedp); */
1496  break;
1497  }
1498  }
1499 
1500  /* Command not found. */
1501  if (ctp->to_name == (char *)0) {
1502  Tcl_DStringAppend(&ds, "unknown subcommand: ", -1);
1503  Tcl_DStringAppend(&ds, argv[1], -1);
1504  Tcl_DStringAppend(&ds, "; must be one of: ", -1);
1505 
1506  for (ctp = to_cmds; ctp->to_name != (char *)NULL; ctp++) {
1507  Tcl_DStringAppend(&ds, " ", -1);
1508  Tcl_DStringAppend(&ds, ctp->to_name, -1);
1509  }
1510  Tcl_DStringAppend(&ds, "\n", -1);
1511  Tcl_DStringResult(interp, &ds);
1512 
1513  return TCL_ERROR;
1514  }
1515 
1516  Tcl_DStringAppend(&ds, bu_vls_addr(top->to_gop->go_gedp->ged_result_str), -1);
1517  Tcl_DStringResult(interp, &ds);
1518 
1519  if (ret & GED_ERROR)
1520  return TCL_ERROR;
1521 
1522  return TCL_OK;
1523 }
1524 
1525 
1526 HIDDEN int
1528 {
1529  struct path_edit_params *pp = (struct path_edit_params *)bu_get_hash_value(entry);
1530  BU_PUT(pp, struct path_edit_params);
1531  return 0;
1532 }
1533 
1534 
1535 /**
1536  * @brief
1537  * Called by Tcl when the object is destroyed.
1538  */
1539 void
1540 to_deleteProc(ClientData clientData)
1541 {
1542  struct tclcad_obj *top = (struct tclcad_obj *)clientData;
1543  struct ged_dm_view *gdvp;
1544 
1545  if (current_top == top)
1546  current_top = TCLCAD_OBJ_NULL;
1547 
1548  BU_LIST_DEQUEUE(&top->l);
1549  bu_vls_free(&top->to_gop->go_name);
1550  ged_close(top->to_gop->go_gedp);
1551  if (top->to_gop->go_gedp)
1552  BU_PUT(top->to_gop->go_gedp, struct ged);
1553 
1556 
1557  while (BU_LIST_WHILE(gdvp, ged_dm_view, &top->to_gop->go_head_views.l)) {
1558  BU_LIST_DEQUEUE(&(gdvp->l));
1559  bu_vls_free(&gdvp->gdv_name);
1560  bu_vls_free(&gdvp->gdv_callback);
1562  (void)dm_close(gdvp->gdv_dmp);
1563  bu_free((void *)gdvp->gdv_view, "ged_view");
1564 
1565  to_close_fbs(gdvp);
1566 
1567  bu_free((void *)gdvp, "ged_dm_view");
1568  }
1569 
1570  bu_free((void *)top, "struct ged_obj");
1571 }
1572 
1573 
1574 /**
1575  * @brief
1576  * Create a command named "oname" in "interp" using "gedp" as its state.
1577  *
1578  */
1579 int
1580 to_create_cmd(Tcl_Interp *interp,
1581  struct tclcad_obj *top, /* pointer to object */
1582  const char *oname) /* object name */
1583 {
1584  if (top == TCLCAD_OBJ_NULL) {
1585  Tcl_AppendResult(interp, "to_create_cmd ", oname, " failed", NULL);
1586  return TCL_ERROR;
1587  }
1588 
1589  /* Instantiate the newprocname, with clientData of top */
1590  /* Beware, returns a "token", not TCL_OK. */
1591  (void)Tcl_CreateCommand(interp, oname, (Tcl_CmdProc *)to_cmd,
1592  (ClientData)top, to_deleteProc);
1593 
1594  /* Return new function name as result */
1595  Tcl_AppendResult(interp, oname, (char *)NULL);
1596 
1597  return TCL_OK;
1598 }
1599 
1600 
1601 /**
1602  * @brief
1603  * A TCL interface to wdb_fopen() and wdb_dbopen().
1604  *
1605  * @par Implicit return -
1606  * Creates a new TCL proc which responds to get/put/etc. arguments
1607  * when invoked. clientData of that proc will be ged_obj pointer for
1608  * this instance of the database. Easily allows keeping track of
1609  * multiple databases.
1610  *
1611  * @return wdb pointer, for more traditional C-style interfacing.
1612  *
1613  * @par Example -
1614  * set top [go_open .inmem inmem $dbip]
1615  *@n .inmem get box.s
1616  *@n .inmem close
1617  *
1618  *@n go_open db file "bob.g"
1619  *@n db get white.r
1620  *@n db close
1621  */
1622 int
1623 to_open_tcl(ClientData UNUSED(clientData),
1624  Tcl_Interp *interp,
1625  int argc,
1626  const char **argv)
1627 {
1628  struct tclcad_obj *top = NULL;
1629  struct ged *gedp = NULL;
1630  const char *dbname = NULL;
1631 
1632  if (argc == 1) {
1633  /* get list of database objects */
1634  for (BU_LIST_FOR(top, tclcad_obj, &HeadTclcadObj.l))
1635  Tcl_AppendResult(interp, bu_vls_addr(&top->to_gop->go_name), " ", (char *)NULL);
1636 
1637  return TCL_OK;
1638  }
1639 
1640  if (argc < 3 || 4 < argc) {
1641  Tcl_AppendResult(interp, "\
1642 Usage: go_open\n\
1643  go_open newprocname file filename\n\
1644  go_open newprocname disk $dbip\n\
1645  go_open newprocname disk_append $dbip\n\
1646  go_open newprocname inmem $dbip\n\
1647  go_open newprocname inmem_append $dbip\n\
1648  go_open newprocname db filename\n\
1649  go_open newprocname filename\n",
1650  NULL);
1651  return TCL_ERROR;
1652  }
1653 
1654  /* Delete previous proc (if any) to release all that memory, first */
1655  (void)Tcl_DeleteCommand(interp, argv[1]);
1656 
1657  if (argc == 3 || BU_STR_EQUAL(argv[2], "db")) {
1658  if (argc == 3) {
1659  dbname = argv[2];
1660  gedp = ged_open("filename", dbname, 0);
1661  } else {
1662  dbname = argv[3];
1663  gedp = ged_open("db", dbname, 0);
1664  }
1665  } else {
1666  dbname = argv[3];
1667  gedp = ged_open(argv[2], dbname, 0);
1668  }
1669 
1670  if (gedp == GED_NULL) {
1671  Tcl_AppendResult(interp, "Unable to open geometry database: ", dbname, (char *)NULL);
1672  return TCL_ERROR;
1673  }
1674 
1675  /* initialize tclcad_obj */
1676  BU_ALLOC(top, struct tclcad_obj);
1677  top->to_interp = interp;
1678 
1679  /* initialize ged_obj */
1680  BU_ALLOC(top->to_gop, struct ged_obj);
1681 
1682  BU_ASSERT_PTR(gedp, !=, NULL);
1683  top->to_gop->go_gedp = gedp;
1684 
1689 
1690  BU_ASSERT_PTR(gedp->ged_gdp, !=, NULL);
1692 
1693  bu_vls_init(&top->to_gop->go_name);
1694  bu_vls_strcpy(&top->to_gop->go_name, argv[1]);
1698  top->to_gop->go_refresh_on = 1;
1700 
1702 
1703  /* append to list of tclcad_obj */
1704  BU_LIST_APPEND(&HeadTclcadObj.l, &top->l);
1705 
1706  return to_create_cmd(interp, top, argv[1]);
1707 }
1708 
1709 
1710 /*************************** Local Command Functions ***************************/
1711 
1712 HIDDEN int
1713 to_autoview(struct ged *gedp,
1714  int argc,
1715  const char *argv[],
1716  ged_func_ptr UNUSED(func),
1717  const char *usage,
1718  int UNUSED(maxargs))
1719 {
1720  struct ged_dm_view *gdvp;
1721 
1722  /* initialize result */
1723  bu_vls_trunc(gedp->ged_result_str, 0);
1724 
1725  if (argc > 3) {
1726  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s [scale]", argv[0], usage);
1727  return GED_ERROR;
1728  }
1729 
1730  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
1731  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
1732  break;
1733  }
1734 
1735  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
1736  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
1737  return GED_ERROR;
1738  }
1739 
1740  if (argc > 2)
1741  to_autoview_view(gdvp, argv[2]);
1742  else
1743  to_autoview_view(gdvp, NULL);
1744 
1745  return GED_OK;
1746 }
1747 
1748 
1749 HIDDEN int
1750 to_axes(struct ged *gedp,
1751  struct ged_dm_view *gdvp,
1752  struct bview_axes_state *gasp,
1753  int argc,
1754  const char *argv[],
1755  const char *usage)
1756 {
1757 
1758  if (BU_STR_EQUAL(argv[2], "draw")) {
1759  if (argc == 3) {
1760  bu_vls_printf(gedp->ged_result_str, "%d", gasp->draw);
1761  return GED_OK;
1762  }
1763 
1764  if (argc == 4) {
1765  int i;
1766 
1767  if (bu_sscanf(argv[3], "%d", &i) != 1)
1768  goto bad;
1769 
1770  if (i)
1771  gasp->draw = 1;
1772  else
1773  gasp->draw = 0;
1774 
1775  to_refresh_view(gdvp);
1776  return GED_OK;
1777  }
1778 
1779  goto bad;
1780  }
1781 
1782  if (BU_STR_EQUAL(argv[2], "axes_size")) {
1783  if (argc == 3) {
1784  bu_vls_printf(gedp->ged_result_str, "%lf", gasp->axes_size);
1785  return GED_OK;
1786  }
1787 
1788  if (argc == 4) {
1789  double size; /* must be double for scanf */
1790 
1791  if (bu_sscanf(argv[3], "%lf", &size) != 1)
1792  goto bad;
1793 
1794  gasp->axes_size = size;
1795 
1796  to_refresh_view(gdvp);
1797  return GED_OK;
1798  }
1799 
1800  goto bad;
1801  }
1802 
1803  if (BU_STR_EQUAL(argv[2], "axes_pos")) {
1804  if (argc == 3) {
1805  bu_vls_printf(gedp->ged_result_str, "%lf %lf %lf",
1806  V3ARGS(gasp->axes_pos));
1807  return GED_OK;
1808  }
1809 
1810  if (argc == 6) {
1811  double x, y, z; /* must be double for scanf */
1812 
1813  if (bu_sscanf(argv[3], "%lf", &x) != 1 ||
1814  bu_sscanf(argv[4], "%lf", &y) != 1 ||
1815  bu_sscanf(argv[5], "%lf", &z) != 1)
1816  goto bad;
1817 
1818  VSET(gasp->axes_pos, x, y, z);
1819 
1820  to_refresh_view(gdvp);
1821  return GED_OK;
1822  }
1823 
1824  goto bad;
1825  }
1826 
1827  if (BU_STR_EQUAL(argv[2], "axes_color")) {
1828  if (argc == 3) {
1829  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
1830  V3ARGS(gasp->axes_color));
1831  return GED_OK;
1832  }
1833 
1834  if (argc == 6) {
1835  int r, g, b;
1836 
1837  /* set background color */
1838  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
1839  bu_sscanf(argv[4], "%d", &g) != 1 ||
1840  bu_sscanf(argv[5], "%d", &b) != 1)
1841  goto bad;
1842 
1843  /* validate color */
1844  if (r < 0 || 255 < r ||
1845  g < 0 || 255 < g ||
1846  b < 0 || 255 < b)
1847  goto bad;
1848 
1849  VSET(gasp->axes_color, r, g, b);
1850 
1851  to_refresh_view(gdvp);
1852  return GED_OK;
1853  }
1854 
1855  goto bad;
1856  }
1857 
1858  if (BU_STR_EQUAL(argv[2], "label_color")) {
1859  if (argc == 3) {
1860  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
1861  V3ARGS(gasp->label_color));
1862  return GED_OK;
1863  }
1864 
1865  if (argc == 6) {
1866  int r, g, b;
1867 
1868  /* set background color */
1869  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
1870  bu_sscanf(argv[4], "%d", &g) != 1 ||
1871  bu_sscanf(argv[5], "%d", &b) != 1)
1872  goto bad;
1873 
1874  /* validate color */
1875  if (r < 0 || 255 < r ||
1876  g < 0 || 255 < g ||
1877  b < 0 || 255 < b)
1878  goto bad;
1879 
1880  VSET(gasp->label_color, r, g, b);
1881 
1882  to_refresh_view(gdvp);
1883  return GED_OK;
1884  }
1885 
1886  goto bad;
1887  }
1888 
1889  if (BU_STR_EQUAL(argv[2], "line_width")) {
1890  if (argc == 3) {
1891  bu_vls_printf(gedp->ged_result_str, "%d", gasp->line_width);
1892  return GED_OK;
1893  }
1894 
1895  if (argc == 4) {
1896  int line_width;
1897 
1898  if (bu_sscanf(argv[3], "%d", &line_width) != 1)
1899  goto bad;
1900 
1901  gasp->line_width = line_width;
1902 
1903  to_refresh_view(gdvp);
1904  return GED_OK;
1905  }
1906 
1907  goto bad;
1908  }
1909 
1910  if (BU_STR_EQUAL(argv[2], "pos_only")) {
1911  if (argc == 3) {
1912  bu_vls_printf(gedp->ged_result_str, "%d", gasp->pos_only);
1913  return GED_OK;
1914  }
1915 
1916  if (argc == 4) {
1917  int i;
1918 
1919  if (bu_sscanf(argv[3], "%d", &i) != 1)
1920  goto bad;
1921 
1922  if (i)
1923  gasp->pos_only = 1;
1924  else
1925  gasp->pos_only = 0;
1926 
1927  to_refresh_view(gdvp);
1928  return GED_OK;
1929  }
1930 
1931  goto bad;
1932  }
1933 
1934  if (BU_STR_EQUAL(argv[2], "tick_color")) {
1935  if (argc == 3) {
1936  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
1937  V3ARGS(gasp->tick_color));
1938  return GED_OK;
1939  }
1940 
1941  if (argc == 6) {
1942  int r, g, b;
1943 
1944  /* set background color */
1945  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
1946  bu_sscanf(argv[4], "%d", &g) != 1 ||
1947  bu_sscanf(argv[5], "%d", &b) != 1)
1948  goto bad;
1949 
1950  /* validate color */
1951  if (r < 0 || 255 < r ||
1952  g < 0 || 255 < g ||
1953  b < 0 || 255 < b)
1954  goto bad;
1955 
1956  VSET(gasp->tick_color, r, g, b);
1957 
1958  to_refresh_view(gdvp);
1959  return GED_OK;
1960  }
1961 
1962  goto bad;
1963  }
1964 
1965  if (BU_STR_EQUAL(argv[2], "tick_enable")) {
1966  if (argc == 3) {
1967  bu_vls_printf(gedp->ged_result_str, "%d", gasp->tick_enabled);
1968  return GED_OK;
1969  }
1970 
1971  if (argc == 4) {
1972  int i;
1973 
1974  if (bu_sscanf(argv[3], "%d", &i) != 1)
1975  goto bad;
1976 
1977  if (i)
1978  gasp->tick_enabled = 1;
1979  else
1980  gasp->tick_enabled = 0;
1981 
1982  to_refresh_view(gdvp);
1983  return GED_OK;
1984  }
1985 
1986  goto bad;
1987  }
1988 
1989  if (BU_STR_EQUAL(argv[2], "tick_interval")) {
1990  if (argc == 3) {
1991  bu_vls_printf(gedp->ged_result_str, "%f", gasp->tick_interval);
1992  return GED_OK;
1993  }
1994 
1995  if (argc == 4) {
1996  int tick_interval;
1997 
1998  if (bu_sscanf(argv[3], "%d", &tick_interval) != 1)
1999  goto bad;
2000 
2001  gasp->tick_interval = tick_interval;
2002 
2003  to_refresh_view(gdvp);
2004  return GED_OK;
2005  }
2006 
2007  goto bad;
2008  }
2009 
2010  if (BU_STR_EQUAL(argv[2], "tick_length")) {
2011  if (argc == 3) {
2012  bu_vls_printf(gedp->ged_result_str, "%d", gasp->tick_length);
2013  return GED_OK;
2014  }
2015 
2016  if (argc == 4) {
2017  int tick_length;
2018 
2019  if (bu_sscanf(argv[3], "%d", &tick_length) != 1)
2020  goto bad;
2021 
2022  gasp->tick_length = tick_length;
2023 
2024  to_refresh_view(gdvp);
2025  return GED_OK;
2026  }
2027 
2028  goto bad;
2029  }
2030 
2031  if (BU_STR_EQUAL(argv[2], "tick_major_color")) {
2032  if (argc == 3) {
2033  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
2034  V3ARGS(gasp->tick_major_color));
2035  return GED_OK;
2036  }
2037 
2038  if (argc == 6) {
2039  int r, g, b;
2040 
2041  /* set background color */
2042  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
2043  bu_sscanf(argv[4], "%d", &g) != 1 ||
2044  bu_sscanf(argv[5], "%d", &b) != 1)
2045  goto bad;
2046 
2047  /* validate color */
2048  if (r < 0 || 255 < r ||
2049  g < 0 || 255 < g ||
2050  b < 0 || 255 < b)
2051  goto bad;
2052 
2053  VSET(gasp->tick_major_color, r, g, b);
2054 
2055  to_refresh_view(gdvp);
2056  return GED_OK;
2057  }
2058 
2059  goto bad;
2060  }
2061 
2062  if (BU_STR_EQUAL(argv[2], "tick_major_length")) {
2063  if (argc == 3) {
2064  bu_vls_printf(gedp->ged_result_str, "%d", gasp->tick_major_length);
2065  return GED_OK;
2066  }
2067 
2068  if (argc == 4) {
2069  int tick_major_length;
2070 
2071  if (bu_sscanf(argv[3], "%d", &tick_major_length) != 1)
2072  goto bad;
2073 
2074  gasp->tick_major_length = tick_major_length;
2075 
2076  to_refresh_view(gdvp);
2077  return GED_OK;
2078  }
2079 
2080  goto bad;
2081  }
2082 
2083  if (BU_STR_EQUAL(argv[2], "ticks_per_major")) {
2084  if (argc == 3) {
2085  bu_vls_printf(gedp->ged_result_str, "%d", gasp->ticks_per_major);
2086  return GED_OK;
2087  }
2088 
2089  if (argc == 4) {
2090  int ticks_per_major;
2091 
2092  if (bu_sscanf(argv[3], "%d", &ticks_per_major) != 1)
2093  goto bad;
2094 
2095  gasp->ticks_per_major = ticks_per_major;
2096 
2097  to_refresh_view(gdvp);
2098  return GED_OK;
2099  }
2100 
2101  goto bad;
2102  }
2103 
2104  if (BU_STR_EQUAL(argv[2], "tick_threshold")) {
2105  if (argc == 3) {
2106  bu_vls_printf(gedp->ged_result_str, "%d", gasp->tick_threshold);
2107  return GED_OK;
2108  }
2109 
2110  if (argc == 4) {
2111  int tick_threshold;
2112 
2113  if (bu_sscanf(argv[3], "%d", &tick_threshold) != 1)
2114  goto bad;
2115 
2116  if (tick_threshold < 1)
2117  tick_threshold = 1;
2118 
2119  gasp->tick_threshold = tick_threshold;
2120 
2121  to_refresh_view(gdvp);
2122  return GED_OK;
2123  }
2124 
2125  goto bad;
2126  }
2127 
2128  if (BU_STR_EQUAL(argv[2], "triple_color")) {
2129  if (argc == 3) {
2130  bu_vls_printf(gedp->ged_result_str, "%d", gasp->triple_color);
2131  return GED_OK;
2132  }
2133 
2134  if (argc == 4) {
2135  int i;
2136 
2137  if (bu_sscanf(argv[3], "%d", &i) != 1)
2138  goto bad;
2139 
2140  if (i)
2141  gasp->triple_color = 1;
2142  else
2143  gasp->triple_color = 0;
2144 
2145  to_refresh_view(gdvp);
2146  return GED_OK;
2147  }
2148 
2149  goto bad;
2150  }
2151 
2152 bad:
2153  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2154  return GED_ERROR;
2155 }
2156 
2157 
2158 HIDDEN int
2159 to_base2local(struct ged *gedp,
2160  int UNUSED(argc),
2161  const char *UNUSED(argv[]),
2162  ged_func_ptr UNUSED(func),
2163  const char *UNUSED(usage),
2164  int UNUSED(maxargs))
2165 {
2166  /* initialize result */
2167  bu_vls_trunc(gedp->ged_result_str, 0);
2168 
2169  bu_vls_printf(gedp->ged_result_str, "%lf", current_top->to_gop->go_gedp->ged_wdbp->dbip->dbi_base2local);
2170 
2171  return GED_OK;
2172 }
2173 
2174 
2175 HIDDEN int
2176 to_bg(struct ged *gedp,
2177  int argc,
2178  const char *argv[],
2179  ged_func_ptr UNUSED(func),
2180  const char *usage,
2181  int UNUSED(maxargs))
2182 {
2183  int r, g, b;
2184  struct ged_dm_view *gdvp;
2185 
2186  /* initialize result */
2187  bu_vls_trunc(gedp->ged_result_str, 0);
2188 
2189  /* must be wanting help */
2190  if (argc == 1) {
2191  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2192  return GED_HELP;
2193  }
2194 
2195  if (argc != 2 && argc != 5) {
2196  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2197  return GED_ERROR;
2198  }
2199 
2200  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
2201  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
2202  break;
2203  }
2204 
2205  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
2206  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
2207  return GED_ERROR;
2208  }
2209 
2210  /* get background color */
2211  if (argc == 2) {
2212  unsigned char *dm_bg = dm_get_bg(gdvp->gdv_dmp);
2213  if (dm_bg) {
2214  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
2215  dm_bg[0],
2216  dm_bg[1],
2217  dm_bg[2]);
2218  }
2219  return GED_OK;
2220  }
2221 
2222  /* set background color */
2223  if (bu_sscanf(argv[2], "%d", &r) != 1 ||
2224  bu_sscanf(argv[3], "%d", &g) != 1 ||
2225  bu_sscanf(argv[4], "%d", &b) != 1)
2226  goto bad_color;
2227 
2228  /* validate color */
2229  if (r < 0 || 255 < r ||
2230  g < 0 || 255 < g ||
2231  b < 0 || 255 < b)
2232  goto bad_color;
2233 
2234  (void)dm_make_current(gdvp->gdv_dmp);
2235  (void)dm_set_bg(gdvp->gdv_dmp, (unsigned char)r, (unsigned char)g, (unsigned char)b);
2236 
2237  to_refresh_view(gdvp);
2238 
2239  return GED_OK;
2240 
2241 bad_color:
2242  bu_vls_printf(gedp->ged_result_str, "%s: %s %s %s", argv[0], argv[2], argv[3], argv[4]);
2243  return GED_ERROR;
2244 }
2245 
2246 
2247 HIDDEN int
2248 to_blast(struct ged *gedp,
2249  int argc,
2250  const char *argv[],
2251  ged_func_ptr UNUSED(func),
2252  const char *UNUSED(usage),
2253  int UNUSED(maxargs))
2254 {
2255  int ret;
2256 
2257  ret = ged_blast(gedp, argc, argv);
2258 
2259  if (ret != GED_OK)
2260  return ret;
2261 
2262  to_autoview_all_views(current_top);
2263 
2264  return ret;
2265 }
2266 
2267 
2268 HIDDEN int
2269 to_bounds(struct ged *gedp,
2270  int argc,
2271  const char *argv[],
2272  ged_func_ptr UNUSED(func),
2273  const char *usage,
2274  int UNUSED(maxargs))
2275 {
2276  struct ged_dm_view *gdvp;
2277  fastf_t bounds[6];
2278 
2279  /* must be double for scanf */
2280  double scan[6];
2281 
2282  /* initialize result */
2283  bu_vls_trunc(gedp->ged_result_str, 0);
2284 
2285  /* must be wanting help */
2286  if (argc == 1) {
2287  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2288  return GED_HELP;
2289  }
2290 
2291  if (argc != 2 && argc != 3) {
2292  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2293  return GED_ERROR;
2294  }
2295 
2296  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
2297  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
2298  break;
2299  }
2300 
2301  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
2302  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
2303  return GED_ERROR;
2304  }
2305 
2306  /* get window bounds */
2307  if (argc == 2) {
2308  vect_t *cmin = dm_get_clipmin(gdvp->gdv_dmp);
2309  vect_t *cmax = dm_get_clipmax(gdvp->gdv_dmp);
2310  if (cmin && cmax) {
2311  bu_vls_printf(gedp->ged_result_str, "%g %g %g %g %g %g",
2312  (*cmin)[X], (*cmax)[X], (*cmin)[Y], (*cmax)[Y], (*cmin)[Z], (*cmax)[Z]);
2313  }
2314  return GED_OK;
2315  }
2316 
2317  /* set window bounds */
2318  if (bu_sscanf(argv[2], "%lf %lf %lf %lf %lf %lf",
2319  &scan[0], &scan[1],
2320  &scan[2], &scan[3],
2321  &scan[4], &scan[5]) != 6) {
2322  bu_vls_printf(gedp->ged_result_str, "%s: invalid bounds - %s", argv[0], argv[2]);
2323  return GED_ERROR;
2324  }
2325  /* convert double to fastf_t */
2326  VMOVE(bounds, scan); /* first point */
2327  VMOVE(&bounds[3], &scan[3]); /* second point */
2328 
2329  /*
2330  * Since dm_bound doesn't appear to be used anywhere, I'm going to
2331  * use it for controlling the location of the zclipping plane in
2332  * dm-ogl.c. dm-X.c uses dm_clipmin and dm_clipmax.
2333  */
2334  if (dm_get_clipmax(gdvp->gdv_dmp) && (*dm_get_clipmax(gdvp->gdv_dmp))[2] <= GED_MAX)
2335  dm_set_bound(gdvp->gdv_dmp, 1.0);
2336  else
2337  dm_set_bound(gdvp->gdv_dmp, GED_MAX/((*dm_get_clipmax(gdvp->gdv_dmp))[2]));
2338 
2339  (void)dm_make_current(gdvp->gdv_dmp);
2340  (void)dm_set_win_bounds(gdvp->gdv_dmp, bounds);
2341 
2342  return GED_OK;
2343 }
2344 
2345 
2346 HIDDEN int
2347 to_configure(struct ged *gedp,
2348  int argc,
2349  const char *argv[],
2350  ged_func_ptr UNUSED(func),
2351  const char *usage,
2352  int UNUSED(maxargs))
2353 {
2354  struct ged_dm_view *gdvp;
2355  int status;
2356 
2357  /* initialize result */
2358  bu_vls_trunc(gedp->ged_result_str, 0);
2359 
2360  if (argc != 2) {
2361  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2362  return GED_ERROR;
2363  }
2364 
2365  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
2366  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
2367  break;
2368  }
2369 
2370  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
2371  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
2372  return GED_ERROR;
2373  }
2374 
2375  /* configure the display manager window */
2376  status = dm_configure_win(gdvp->gdv_dmp, 0);
2377 
2378  /* configure the framebuffer window */
2379  if (gdvp->gdv_fbs.fbs_fbp != FB_NULL)
2380  (void)fb_configure_window(gdvp->gdv_fbs.fbs_fbp, dm_get_width(gdvp->gdv_dmp), dm_get_height(gdvp->gdv_dmp));
2381 
2382  {
2383  char cdimX[32];
2384  char cdimY[32];
2385  char *av[5];
2386 
2387  snprintf(cdimX, 32, "%d", dm_get_width(gdvp->gdv_dmp));
2388  snprintf(cdimY, 32, "%d", dm_get_height(gdvp->gdv_dmp));
2389 
2390  av[0] = "rect";
2391  av[1] = "cdim";
2392  av[2] = cdimX;
2393  av[3] = cdimY;
2394  av[4] = NULL;
2395 
2396  gedp->ged_gvp = gdvp->gdv_view;
2397  (void)ged_rect(gedp, 4, (const char **)av);
2398  }
2399 
2400  if (status == TCL_OK) {
2401  to_refresh_view(gdvp);
2402  return GED_OK;
2403  }
2404 
2405  return GED_ERROR;
2406 }
2407 
2408 
2409 HIDDEN int
2411  int argc,
2412  const char *argv[],
2413  ged_func_ptr UNUSED(func),
2414  const char *usage,
2415  int UNUSED(maxargs))
2416 {
2417  struct bu_vls bindings = BU_VLS_INIT_ZERO;
2418  struct ged_dm_view *gdvp;
2419 
2420  /* must be double for scanf */
2421  double x, y;
2422 
2423  /* initialize result */
2424  bu_vls_trunc(gedp->ged_result_str, 0);
2425 
2426  /* must be wanting help */
2427  if (argc == 1) {
2428  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2429  return GED_HELP;
2430  }
2431 
2432  if (argc != 5) {
2433  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2434  return GED_ERROR;
2435  }
2436 
2437  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
2438  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
2439  break;
2440  }
2441 
2442  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
2443  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
2444  return GED_ERROR;
2445  }
2446 
2447  if ((argv[2][0] != 'x' &&
2448  argv[2][0] != 'y' &&
2449  argv[2][0] != 'z') || argv[2][1] != '\0') {
2450  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2451  return GED_OK;
2452  }
2453 
2454  if (bu_sscanf(argv[3], "%lf", &x) != 1 ||
2455  bu_sscanf(argv[4], "%lf", &y) != 1) {
2456  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2457  return GED_ERROR;
2458  }
2459 
2460  gdvp->gdv_view->gv_prevMouseX = x;
2461  gdvp->gdv_view->gv_prevMouseY = y;
2463 
2464  if (dm_get_pathname(gdvp->gdv_dmp)) {
2465  bu_vls_printf(&bindings, "bind %s <Motion> {%s mouse_constrain_rot %s %s %%x %%y}; break",
2467  bu_vls_addr(&current_top->to_gop->go_name),
2468  bu_vls_addr(&gdvp->gdv_name),
2469  argv[2]);
2470  Tcl_Eval(current_top->to_interp, bu_vls_addr(&bindings));
2471  }
2472  bu_vls_free(&bindings);
2473 
2474  return GED_OK;
2475 }
2476 
2477 
2478 HIDDEN int
2480  int argc,
2481  const char *argv[],
2482  ged_func_ptr UNUSED(func),
2483  const char *usage,
2484  int UNUSED(maxargs))
2485 {
2486  struct bu_vls bindings = BU_VLS_INIT_ZERO;
2487  struct ged_dm_view *gdvp;
2488 
2489  /* must be double for scanf */
2490  double x, y;
2491 
2492  /* initialize result */
2493  bu_vls_trunc(gedp->ged_result_str, 0);
2494 
2495  /* must be wanting help */
2496  if (argc == 1) {
2497  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2498  return GED_HELP;
2499  }
2500 
2501  if (argc != 5) {
2502  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2503  return GED_ERROR;
2504  }
2505 
2506  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
2507  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
2508  break;
2509  }
2510 
2511  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
2512  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
2513  return GED_ERROR;
2514  }
2515 
2516  if ((argv[2][0] != 'x' &&
2517  argv[2][0] != 'y' &&
2518  argv[2][0] != 'z') || argv[2][1] != '\0') {
2519  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2520  return GED_OK;
2521  }
2522 
2523  if (bu_sscanf(argv[3], "%lf", &x) != 1 ||
2524  bu_sscanf(argv[4], "%lf", &y) != 1) {
2525  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2526  return GED_ERROR;
2527  }
2528 
2529  gdvp->gdv_view->gv_prevMouseX = x;
2530  gdvp->gdv_view->gv_prevMouseY = y;
2532 
2533  if (dm_get_pathname(gdvp->gdv_dmp)) {
2534  bu_vls_printf(&bindings, "bind %s <Motion> {%s mouse_constrain_trans %s %s %%x %%y}; break",
2536  bu_vls_addr(&current_top->to_gop->go_name),
2537  bu_vls_addr(&gdvp->gdv_name),
2538  argv[2]);
2539  Tcl_Eval(current_top->to_interp, bu_vls_addr(&bindings));
2540  }
2541  bu_vls_free(&bindings);
2542 
2543  return GED_OK;
2544 }
2545 
2546 
2547 HIDDEN int
2548 to_copy(struct ged *gedp,
2549  int argc,
2550  const char *argv[],
2551  ged_func_ptr UNUSED(func),
2552  const char *usage,
2553  int UNUSED(maxargs))
2554 {
2555  struct ged *from_gedp = GED_NULL;
2556  struct ged *to_gedp = GED_NULL;
2557  int ret;
2558  char *cp;
2559  struct tclcad_obj *top;
2560  struct bu_vls db_vls = BU_VLS_INIT_ZERO;
2561  struct bu_vls from_vls = BU_VLS_INIT_ZERO;
2562  struct bu_vls to_vls = BU_VLS_INIT_ZERO;
2563  int fflag;
2564 
2565  /* initialize result */
2566  bu_vls_trunc(gedp->ged_result_str, 0);
2567 
2568  /* must be wanting help */
2569  if (argc == 1) {
2570  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2571  return GED_HELP;
2572  }
2573 
2574  if (argc < 3 || 4 < argc) {
2575  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2576  return GED_ERROR;
2577  }
2578 
2579  if (argc == 4) {
2580  if (argv[1][0] != '-' || argv[1][1] != 'f' || argv[1][2] != '\0') {
2581  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2582  return GED_ERROR;
2583  }
2584 
2585  fflag = 1;
2586 
2587  /* Advance past the -f option */
2588  --argc;
2589  ++argv;
2590  } else
2591  fflag = 0;
2592 
2593  cp = strchr(argv[1], ':');
2594  if (cp) {
2595  bu_vls_strncpy(&db_vls, argv[1], cp-argv[1]);
2596  bu_vls_strcpy(&from_vls, cp+1);
2597 
2598  for (BU_LIST_FOR(top, tclcad_obj, &HeadTclcadObj.l)) {
2599  if (BU_STR_EQUAL(bu_vls_addr(&top->to_gop->go_name), bu_vls_addr(&db_vls))) {
2600  from_gedp = top->to_gop->go_gedp;
2601  break;
2602  }
2603  }
2604 
2605  bu_vls_free(&db_vls);
2606 
2607  if (from_gedp == GED_NULL) {
2608  bu_vls_free(&from_vls);
2609  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2610  return GED_ERROR;
2611  }
2612  } else {
2613  bu_vls_strcpy(&from_vls, argv[1]);
2614  from_gedp = gedp;
2615  }
2616 
2617  cp = strchr(argv[2], ':');
2618  if (cp) {
2619  bu_vls_trunc(&db_vls, 0);
2620  bu_vls_strncpy(&db_vls, argv[2], cp-argv[2]);
2621  bu_vls_strcpy(&to_vls, cp+1);
2622 
2623  for (BU_LIST_FOR(top, tclcad_obj, &HeadTclcadObj.l)) {
2624  if (BU_STR_EQUAL(bu_vls_addr(&top->to_gop->go_name), bu_vls_addr(&db_vls))) {
2625  to_gedp = top->to_gop->go_gedp;
2626  break;
2627  }
2628  }
2629 
2630  bu_vls_free(&db_vls);
2631 
2632  if (to_gedp == GED_NULL) {
2633  bu_vls_free(&from_vls);
2634  bu_vls_free(&to_vls);
2635  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2636  return GED_ERROR;
2637  }
2638  } else {
2639  bu_vls_strcpy(&to_vls, argv[2]);
2640  to_gedp = gedp;
2641  }
2642 
2643  if (from_gedp == to_gedp) {
2644  ret = ged_dbcopy(from_gedp, to_gedp,
2645  bu_vls_addr(&from_vls),
2646  bu_vls_addr(&to_vls),
2647  fflag);
2648 
2649  if (ret != GED_OK && from_gedp != gedp)
2651  } else {
2652  ret = ged_dbcopy(from_gedp, to_gedp,
2653  bu_vls_addr(&from_vls),
2654  bu_vls_addr(&to_vls),
2655  fflag);
2656 
2657  if (ret != GED_OK) {
2658  if (bu_vls_strlen(from_gedp->ged_result_str)) {
2659  if (from_gedp != gedp)
2661  } else if (to_gedp != gedp && bu_vls_strlen(to_gedp->ged_result_str))
2663  }
2664  }
2665 
2666  bu_vls_free(&from_vls);
2667  bu_vls_free(&to_vls);
2668 
2669  return ret;
2670 }
2671 
2672 
2673 HIDDEN int
2674 to_data_arrows(struct ged *gedp,
2675  int argc,
2676  const char *argv[],
2677  ged_func_ptr UNUSED(func),
2678  const char *usage,
2679  int UNUSED(maxargs))
2680 {
2681  struct ged_dm_view *gdvp;
2682  struct bview_data_arrow_state *gdasp;
2683 
2684  /* initialize result */
2685  bu_vls_trunc(gedp->ged_result_str, 0);
2686 
2687  /* must be wanting help */
2688  if (argc == 1) {
2689  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2690  return GED_HELP;
2691  }
2692 
2693  if (argc < 3 || 6 < argc) {
2694  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2695  return GED_ERROR;
2696  }
2697 
2698  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
2699  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
2700  break;
2701  }
2702 
2703  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
2704  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
2705  return GED_ERROR;
2706  }
2707 
2708  if (argv[0][0] == 's')
2709  gdasp = &gdvp->gdv_view->gv_sdata_arrows;
2710  else
2711  gdasp = &gdvp->gdv_view->gv_data_arrows;
2712 
2713  if (BU_STR_EQUAL(argv[2], "draw")) {
2714  if (argc == 3) {
2715  bu_vls_printf(gedp->ged_result_str, "%d", gdasp->gdas_draw);
2716  return GED_OK;
2717  }
2718 
2719  if (argc == 4) {
2720  int i;
2721 
2722  if (bu_sscanf(argv[3], "%d", &i) != 1)
2723  goto bad;
2724 
2725  if (i)
2726  gdasp->gdas_draw = 1;
2727  else
2728  gdasp->gdas_draw = 0;
2729 
2730  to_refresh_view(gdvp);
2731  return GED_OK;
2732  }
2733 
2734  goto bad;
2735  }
2736 
2737  if (BU_STR_EQUAL(argv[2], "color")) {
2738  if (argc == 3) {
2739  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
2740  V3ARGS(gdasp->gdas_color));
2741  return GED_OK;
2742  }
2743 
2744  if (argc == 6) {
2745  int r, g, b;
2746 
2747  /* set background color */
2748  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
2749  bu_sscanf(argv[4], "%d", &g) != 1 ||
2750  bu_sscanf(argv[5], "%d", &b) != 1)
2751  goto bad;
2752 
2753  /* validate color */
2754  if (r < 0 || 255 < r ||
2755  g < 0 || 255 < g ||
2756  b < 0 || 255 < b)
2757  goto bad;
2758 
2759  VSET(gdasp->gdas_color, r, g, b);
2760 
2761  to_refresh_view(gdvp);
2762  return GED_OK;
2763  }
2764 
2765  goto bad;
2766  }
2767 
2768  if (BU_STR_EQUAL(argv[2], "line_width")) {
2769  if (argc == 3) {
2770  bu_vls_printf(gedp->ged_result_str, "%d", gdasp->gdas_line_width);
2771  return GED_OK;
2772  }
2773 
2774  if (argc == 4) {
2775  int line_width;
2776 
2777  if (bu_sscanf(argv[3], "%d", &line_width) != 1)
2778  goto bad;
2779 
2780  gdasp->gdas_line_width = line_width;
2781 
2782  to_refresh_view(gdvp);
2783  return GED_OK;
2784  }
2785 
2786  goto bad;
2787  }
2788 
2789  if (BU_STR_EQUAL(argv[2], "points")) {
2790  register int i;
2791 
2792  if (argc == 3) {
2793  for (i = 0; i < gdasp->gdas_num_points; ++i) {
2794  bu_vls_printf(gedp->ged_result_str, " {%lf %lf %lf} ",
2795  V3ARGS(gdasp->gdas_points[i]));
2796  }
2797  return GED_OK;
2798  }
2799 
2800  if (argc == 4) {
2801  int ac;
2802  const char **av;
2803 
2804  if (Tcl_SplitList(current_top->to_interp, argv[3], &ac, &av) != TCL_OK) {
2805  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
2806  return GED_ERROR;
2807  }
2808 
2809  if (ac % 2) {
2810  bu_vls_printf(gedp->ged_result_str, "%s: must be an even number of points", argv[0]);
2811  return GED_ERROR;
2812  }
2813 
2814  if (gdasp->gdas_num_points) {
2815  bu_free((void *)gdasp->gdas_points, "data points");
2816  gdasp->gdas_points = (point_t *)0;
2817  gdasp->gdas_num_points = 0;
2818  }
2819 
2820  /* Clear out data points */
2821  if (ac < 1) {
2822  to_refresh_view(gdvp);
2823  Tcl_Free((char *)av);
2824  return GED_OK;
2825  }
2826 
2827  gdasp->gdas_num_points = ac;
2828  gdasp->gdas_points = (point_t *)bu_calloc(ac, sizeof(point_t), "data points");
2829  for (i = 0; i < ac; ++i) {
2830  double scan[ELEMENTS_PER_VECT];
2831 
2832  if (bu_sscanf(av[i], "%lf %lf %lf", &scan[X], &scan[Y], &scan[Z]) != 3) {
2833 
2834  bu_vls_printf(gedp->ged_result_str, "bad data point - %s\n", av[i]);
2835 
2836  bu_free((void *)gdasp->gdas_points, "data points");
2837  gdasp->gdas_points = (point_t *)0;
2838  gdasp->gdas_num_points = 0;
2839 
2840  to_refresh_view(gdvp);
2841  Tcl_Free((char *)av);
2842  return GED_ERROR;
2843  }
2844  /* convert double to fastf_t */
2845  VMOVE(gdasp->gdas_points[i], scan);
2846  }
2847 
2848  to_refresh_view(gdvp);
2849  Tcl_Free((char *)av);
2850  return GED_OK;
2851  }
2852  }
2853 
2854  if (BU_STR_EQUAL(argv[2], "tip_length")) {
2855  if (argc == 3) {
2856  bu_vls_printf(gedp->ged_result_str, "%d", gdasp->gdas_tip_length);
2857  return GED_OK;
2858  }
2859 
2860  if (argc == 4) {
2861  int tip_length;
2862 
2863  if (bu_sscanf(argv[3], "%d", &tip_length) != 1)
2864  goto bad;
2865 
2866  gdasp->gdas_tip_length = tip_length;
2867 
2868  to_refresh_view(gdvp);
2869  return GED_OK;
2870  }
2871 
2872  goto bad;
2873  }
2874 
2875  if (BU_STR_EQUAL(argv[2], "tip_width")) {
2876  if (argc == 3) {
2877  bu_vls_printf(gedp->ged_result_str, "%d", gdasp->gdas_tip_width);
2878  return GED_OK;
2879  }
2880 
2881  if (argc == 4) {
2882  int tip_width;
2883 
2884  if (bu_sscanf(argv[3], "%d", &tip_width) != 1)
2885  goto bad;
2886 
2887  gdasp->gdas_tip_width = tip_width;
2888 
2889  to_refresh_view(gdvp);
2890  return GED_OK;
2891  }
2892 
2893  goto bad;
2894  }
2895 
2896 bad:
2897  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2898  return GED_ERROR;
2899 }
2900 
2901 
2902 HIDDEN int
2903 to_data_axes(struct ged *gedp,
2904  int argc,
2905  const char *argv[],
2906  ged_func_ptr UNUSED(func),
2907  const char *usage,
2908  int UNUSED(maxargs))
2909 {
2910  struct ged_dm_view *gdvp;
2911  struct bview_data_axes_state *gdasp;
2912 
2913  /* initialize result */
2914  bu_vls_trunc(gedp->ged_result_str, 0);
2915 
2916  /* must be wanting help */
2917  if (argc == 1) {
2918  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2919  return GED_HELP;
2920  }
2921 
2922  if (argc < 3 || 6 < argc) {
2923  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
2924  return GED_ERROR;
2925  }
2926 
2927  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
2928  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
2929  break;
2930  }
2931 
2932  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
2933  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
2934  return GED_ERROR;
2935  }
2936 
2937  if (argv[0][0] == 's')
2938  gdasp = &gdvp->gdv_view->gv_sdata_axes;
2939  else
2940  gdasp = &gdvp->gdv_view->gv_data_axes;
2941 
2942  if (BU_STR_EQUAL(argv[2], "draw")) {
2943  if (argc == 3) {
2944  bu_vls_printf(gedp->ged_result_str, "%d", gdasp->draw);
2945  return GED_OK;
2946  }
2947 
2948  if (argc == 4) {
2949  int i;
2950 
2951  if (bu_sscanf(argv[3], "%d", &i) != 1)
2952  goto bad;
2953 
2954  if (0 <= i && i <= 2)
2955  gdasp->draw = i;
2956  else
2957  gdasp->draw = 0;
2958 
2959  to_refresh_view(gdvp);
2960  return GED_OK;
2961  }
2962 
2963  goto bad;
2964  }
2965 
2966  if (BU_STR_EQUAL(argv[2], "color")) {
2967  if (argc == 3) {
2968  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
2969  V3ARGS(gdasp->color));
2970  return GED_OK;
2971  }
2972 
2973  if (argc == 6) {
2974  int r, g, b;
2975 
2976  /* set background color */
2977  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
2978  bu_sscanf(argv[4], "%d", &g) != 1 ||
2979  bu_sscanf(argv[5], "%d", &b) != 1)
2980  goto bad;
2981 
2982  /* validate color */
2983  if (r < 0 || 255 < r ||
2984  g < 0 || 255 < g ||
2985  b < 0 || 255 < b)
2986  goto bad;
2987 
2988  VSET(gdasp->color, r, g, b);
2989 
2990  to_refresh_view(gdvp);
2991  return GED_OK;
2992  }
2993 
2994  goto bad;
2995  }
2996 
2997  if (BU_STR_EQUAL(argv[2], "line_width")) {
2998  if (argc == 3) {
2999  bu_vls_printf(gedp->ged_result_str, "%d", gdasp->line_width);
3000  return GED_OK;
3001  }
3002 
3003  if (argc == 4) {
3004  int line_width;
3005 
3006  if (bu_sscanf(argv[3], "%d", &line_width) != 1)
3007  goto bad;
3008 
3009  gdasp->line_width = line_width;
3010 
3011  to_refresh_view(gdvp);
3012  return GED_OK;
3013  }
3014 
3015  goto bad;
3016  }
3017 
3018  if (BU_STR_EQUAL(argv[2], "size")) {
3019  if (argc == 3) {
3020  bu_vls_printf(gedp->ged_result_str, "%lf", gdasp->size);
3021  return GED_OK;
3022  }
3023 
3024  if (argc == 4) {
3025  double size; /* must be double for scanf */
3026 
3027  if (bu_sscanf(argv[3], "%lf", &size) != 1)
3028  goto bad;
3029 
3030  gdasp->size = size;
3031 
3032  to_refresh_view(gdvp);
3033  return GED_OK;
3034  }
3035 
3036  goto bad;
3037  }
3038 
3039  if (BU_STR_EQUAL(argv[2], "points")) {
3040  register int i;
3041 
3042  if (argc == 3) {
3043  for (i = 0; i < gdasp->num_points; ++i) {
3044  bu_vls_printf(gedp->ged_result_str, " {%lf %lf %lf} ",
3045  V3ARGS(gdasp->points[i]));
3046  }
3047  return GED_OK;
3048  }
3049 
3050  if (argc == 4) {
3051  int ac;
3052  const char **av;
3053 
3054  if (Tcl_SplitList(current_top->to_interp, argv[3], &ac, &av) != TCL_OK) {
3055  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
3056  return GED_ERROR;
3057  }
3058 
3059  if (gdasp->num_points) {
3060  bu_free((void *)gdasp->points, "data points");
3061  gdasp->points = (point_t *)0;
3062  gdasp->num_points = 0;
3063  }
3064 
3065  /* Clear out data points */
3066  if (ac < 1) {
3067  to_refresh_view(gdvp);
3068  Tcl_Free((char *)av);
3069  return GED_OK;
3070  }
3071 
3072  gdasp->num_points = ac;
3073  gdasp->points = (point_t *)bu_calloc(ac, sizeof(point_t), "data points");
3074  for (i = 0; i < ac; ++i) {
3075  double scan[3];
3076 
3077  if (bu_sscanf(av[i], "%lf %lf %lf", &scan[X], &scan[Y], &scan[Z]) != 3) {
3078  bu_vls_printf(gedp->ged_result_str, "bad data point - %s\n", av[i]);
3079 
3080  bu_free((void *)gdasp->points, "data points");
3081  gdasp->points = (point_t *)0;
3082  gdasp->num_points = 0;
3083 
3084  to_refresh_view(gdvp);
3085  Tcl_Free((char *)av);
3086  return GED_ERROR;
3087  }
3088  /* convert double to fastf_t */
3089  VMOVE(gdasp->points[i], scan);
3090  }
3091 
3092  to_refresh_view(gdvp);
3093  Tcl_Free((char *)av);
3094  return GED_OK;
3095  }
3096  }
3097 
3098 bad:
3099  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3100  return GED_ERROR;
3101 }
3102 
3103 
3104 HIDDEN int
3105 to_data_labels(struct ged *gedp,
3106  int argc,
3107  const char *argv[],
3108  ged_func_ptr UNUSED(func),
3109  const char *usage,
3110  int UNUSED(maxargs))
3111 {
3112  struct ged_dm_view *gdvp;
3113  struct bview_data_label_state *gdlsp;
3114 
3115  /* initialize result */
3116  bu_vls_trunc(gedp->ged_result_str, 0);
3117 
3118  /* must be wanting help */
3119  if (argc == 1) {
3120  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3121  return GED_HELP;
3122  }
3123 
3124  if (argc < 3 || 6 < argc) {
3125  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3126  return GED_ERROR;
3127  }
3128 
3129  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
3130  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
3131  break;
3132  }
3133 
3134  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
3135  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
3136  return GED_ERROR;
3137  }
3138 
3139  if (argv[0][0] == 's')
3140  gdlsp = &gdvp->gdv_view->gv_sdata_labels;
3141  else
3142  gdlsp = &gdvp->gdv_view->gv_data_labels;
3143 
3144  if (BU_STR_EQUAL(argv[2], "draw")) {
3145  if (argc == 3) {
3146  bu_vls_printf(gedp->ged_result_str, "%d", gdlsp->gdls_draw);
3147  return GED_OK;
3148  }
3149 
3150  if (argc == 4) {
3151  int i;
3152 
3153  if (bu_sscanf(argv[3], "%d", &i) != 1)
3154  goto bad;
3155 
3156  if (i)
3157  gdlsp->gdls_draw = 1;
3158  else
3159  gdlsp->gdls_draw = 0;
3160 
3161  to_refresh_view(gdvp);
3162  return GED_OK;
3163  }
3164 
3165  goto bad;
3166  }
3167 
3168  if (BU_STR_EQUAL(argv[2], "color")) {
3169  if (argc == 3) {
3170  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
3171  V3ARGS(gdlsp->gdls_color));
3172  return GED_OK;
3173  }
3174 
3175  if (argc == 6) {
3176  int r, g, b;
3177 
3178  /* set background color */
3179  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
3180  bu_sscanf(argv[4], "%d", &g) != 1 ||
3181  bu_sscanf(argv[5], "%d", &b) != 1)
3182  goto bad;
3183 
3184  /* validate color */
3185  if (r < 0 || 255 < r ||
3186  g < 0 || 255 < g ||
3187  b < 0 || 255 < b)
3188  goto bad;
3189 
3190  VSET(gdlsp->gdls_color, r, g, b);
3191 
3192  to_refresh_view(gdvp);
3193  return GED_OK;
3194  }
3195 
3196  goto bad;
3197  }
3198 
3199  if (BU_STR_EQUAL(argv[2], "labels")) {
3200  register int i;
3201 
3202  /* { {{label this} {0 0 0}} {{label that} {100 100 100}} }*/
3203 
3204  if (argc == 3) {
3205  for (i = 0; i < gdlsp->gdls_num_labels; ++i) {
3206  bu_vls_printf(gedp->ged_result_str, "{{%s}", gdlsp->gdls_labels[i]);
3207  bu_vls_printf(gedp->ged_result_str, " {%lf %lf %lf}} ",
3208  V3ARGS(gdlsp->gdls_points[i]));
3209  }
3210  return GED_OK;
3211  }
3212 
3213  if (argc == 4) {
3214  int ac;
3215  const char **av;
3216 
3217  if (Tcl_SplitList(current_top->to_interp, argv[3], &ac, &av) != TCL_OK) {
3218  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
3219  return GED_ERROR;
3220  }
3221 
3222  if (gdlsp->gdls_num_labels) {
3223  for (i = 0; i < gdlsp->gdls_num_labels; ++i)
3224  bu_free((void *)gdlsp->gdls_labels[i], "data label");
3225 
3226  bu_free((void *)gdlsp->gdls_labels, "data labels");
3227  bu_free((void *)gdlsp->gdls_points, "data points");
3228  gdlsp->gdls_labels = (char **)0;
3229  gdlsp->gdls_points = (point_t *)0;
3230  gdlsp->gdls_num_labels = 0;
3231  }
3232 
3233  /* Clear out data points */
3234  if (ac < 1) {
3235  Tcl_Free((char *)av);
3236  to_refresh_view(gdvp);
3237  return GED_OK;
3238  }
3239 
3240  gdlsp->gdls_num_labels = ac;
3241  gdlsp->gdls_labels = (char **)bu_calloc(ac, sizeof(char *), "data labels");
3242  gdlsp->gdls_points = (point_t *)bu_calloc(ac, sizeof(point_t), "data points");
3243  for (i = 0; i < ac; ++i) {
3244  int sub_ac;
3245  const char **sub_av;
3246  double scan[ELEMENTS_PER_VECT];
3247 
3248  if (Tcl_SplitList(current_top->to_interp, av[i], &sub_ac, &sub_av) != TCL_OK) {
3249  /*XXX Need a macro for the following lines. Do something similar for the rest. */
3250  bu_free((void *)gdlsp->gdls_labels, "data labels");
3251  bu_free((void *)gdlsp->gdls_points, "data points");
3252  gdlsp->gdls_labels = (char **)0;
3253  gdlsp->gdls_points = (point_t *)0;
3254  gdlsp->gdls_num_labels = 0;
3255 
3256  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
3257  Tcl_Free((char *)av);
3258  to_refresh_view(gdvp);
3259  return GED_ERROR;
3260  }
3261 
3262  if (sub_ac != 2) {
3263  /*XXX Need a macro for the following lines. Do something similar for the rest. */
3264  bu_free((void *)gdlsp->gdls_labels, "data labels");
3265  bu_free((void *)gdlsp->gdls_points, "data points");
3266  gdlsp->gdls_labels = (char **)0;
3267  gdlsp->gdls_points = (point_t *)0;
3268  gdlsp->gdls_num_labels = 0;
3269 
3270  bu_vls_printf(gedp->ged_result_str, "Each list element must contain a label and a point (i.e. {{some label} {0 0 0}})");
3271  Tcl_Free((char *)sub_av);
3272  Tcl_Free((char *)av);
3273  to_refresh_view(gdvp);
3274  return GED_ERROR;
3275  }
3276 
3277  if (bu_sscanf(sub_av[1], "%lf %lf %lf", &scan[X], &scan[Y], &scan[Z]) != 3) {
3278  bu_vls_printf(gedp->ged_result_str, "bad data point - %s\n", sub_av[1]);
3279 
3280  /*XXX Need a macro for the following lines. Do something similar for the rest. */
3281  bu_free((void *)gdlsp->gdls_labels, "data labels");
3282  bu_free((void *)gdlsp->gdls_points, "data points");
3283  gdlsp->gdls_labels = (char **)0;
3284  gdlsp->gdls_points = (point_t *)0;
3285  gdlsp->gdls_num_labels = 0;
3286 
3287  Tcl_Free((char *)sub_av);
3288  Tcl_Free((char *)av);
3289  to_refresh_view(gdvp);
3290  return GED_ERROR;
3291  }
3292  /* convert double to fastf_t */
3293  VMOVE(gdlsp->gdls_points[i], scan);
3294 
3295  gdlsp->gdls_labels[i] = bu_strdup(sub_av[0]);
3296  Tcl_Free((char *)sub_av);
3297  }
3298 
3299  Tcl_Free((char *)av);
3300  to_refresh_view(gdvp);
3301  return GED_OK;
3302  }
3303  }
3304 
3305  if (BU_STR_EQUAL(argv[2], "size")) {
3306  if (argc == 3) {
3307  bu_vls_printf(gedp->ged_result_str, "%d", gdlsp->gdls_size);
3308  return GED_OK;
3309  }
3310 
3311  if (argc == 4) {
3312  int size;
3313 
3314  if (bu_sscanf(argv[3], "%d", &size) != 1)
3315  goto bad;
3316 
3317  gdlsp->gdls_size = size;
3318 
3319  to_refresh_view(gdvp);
3320  return GED_OK;
3321  }
3322 
3323  goto bad;
3324  }
3325 
3326 
3327 bad:
3328  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3329  return GED_ERROR;
3330 }
3331 
3332 
3333 HIDDEN int
3334 to_data_lines(struct ged *gedp,
3335  int argc,
3336  const char *argv[],
3337  ged_func_ptr UNUSED(func),
3338  const char *usage,
3339  int UNUSED(maxargs))
3340 {
3341  struct ged_dm_view *gdvp;
3342  struct bview_data_line_state *gdlsp;
3343 
3344  /* initialize result */
3345  bu_vls_trunc(gedp->ged_result_str, 0);
3346 
3347  /* must be wanting help */
3348  if (argc == 1) {
3349  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3350  return GED_HELP;
3351  }
3352 
3353  if (argc < 3 || 6 < argc) {
3354  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3355  return GED_ERROR;
3356  }
3357 
3358  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
3359  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
3360  break;
3361  }
3362 
3363  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
3364  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
3365  return GED_ERROR;
3366  }
3367 
3368  if (argv[0][0] == 's')
3369  gdlsp = &gdvp->gdv_view->gv_sdata_lines;
3370  else
3371  gdlsp = &gdvp->gdv_view->gv_data_lines;
3372 
3373  if (BU_STR_EQUAL(argv[2], "draw")) {
3374  if (argc == 3) {
3375  bu_vls_printf(gedp->ged_result_str, "%d", gdlsp->gdls_draw);
3376  return GED_OK;
3377  }
3378 
3379  if (argc == 4) {
3380  int i;
3381 
3382  if (bu_sscanf(argv[3], "%d", &i) != 1)
3383  goto bad;
3384 
3385  if (i)
3386  gdlsp->gdls_draw = 1;
3387  else
3388  gdlsp->gdls_draw = 0;
3389 
3390  to_refresh_view(gdvp);
3391  return GED_OK;
3392  }
3393 
3394  goto bad;
3395  }
3396 
3397  if (BU_STR_EQUAL(argv[2], "color")) {
3398  if (argc == 3) {
3399  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
3400  V3ARGS(gdlsp->gdls_color));
3401  return GED_OK;
3402  }
3403 
3404  if (argc == 6) {
3405  int r, g, b;
3406 
3407  /* set background color */
3408  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
3409  bu_sscanf(argv[4], "%d", &g) != 1 ||
3410  bu_sscanf(argv[5], "%d", &b) != 1)
3411  goto bad;
3412 
3413  /* validate color */
3414  if (r < 0 || 255 < r ||
3415  g < 0 || 255 < g ||
3416  b < 0 || 255 < b)
3417  goto bad;
3418 
3419  VSET(gdlsp->gdls_color, r, g, b);
3420 
3421  to_refresh_view(gdvp);
3422  return GED_OK;
3423  }
3424 
3425  goto bad;
3426  }
3427 
3428  if (BU_STR_EQUAL(argv[2], "line_width")) {
3429  if (argc == 3) {
3430  bu_vls_printf(gedp->ged_result_str, "%d", gdlsp->gdls_line_width);
3431  return GED_OK;
3432  }
3433 
3434  if (argc == 4) {
3435  int line_width;
3436 
3437  if (bu_sscanf(argv[3], "%d", &line_width) != 1)
3438  goto bad;
3439 
3440  gdlsp->gdls_line_width = line_width;
3441 
3442  to_refresh_view(gdvp);
3443  return GED_OK;
3444  }
3445 
3446  goto bad;
3447  }
3448 
3449  if (BU_STR_EQUAL(argv[2], "points")) {
3450  register int i;
3451 
3452  if (argc == 3) {
3453  for (i = 0; i < gdlsp->gdls_num_points; ++i) {
3454  bu_vls_printf(gedp->ged_result_str, " {%lf %lf %lf} ",
3455  V3ARGS(gdlsp->gdls_points[i]));
3456  }
3457  return GED_OK;
3458  }
3459 
3460  if (argc == 4) {
3461  int ac;
3462  const char **av;
3463 
3464  if (Tcl_SplitList(current_top->to_interp, argv[3], &ac, &av) != TCL_OK) {
3465  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
3466  return GED_ERROR;
3467  }
3468 
3469  if (ac % 2) {
3470  bu_vls_printf(gedp->ged_result_str, "%s: must be an even number of points", argv[0]);
3471  return GED_ERROR;
3472  }
3473 
3474  if (gdlsp->gdls_num_points) {
3475  bu_free((void *)gdlsp->gdls_points, "data points");
3476  gdlsp->gdls_points = (point_t *)0;
3477  gdlsp->gdls_num_points = 0;
3478  }
3479 
3480  /* Clear out data points */
3481  if (ac < 1) {
3482  to_refresh_view(gdvp);
3483  Tcl_Free((char *)av);
3484  return GED_OK;
3485  }
3486 
3487  gdlsp->gdls_num_points = ac;
3488  gdlsp->gdls_points = (point_t *)bu_calloc(ac, sizeof(point_t), "data points");
3489  for (i = 0; i < ac; ++i) {
3490  double scan[3];
3491 
3492  if (bu_sscanf(av[i], "%lf %lf %lf", &scan[X], &scan[Y], &scan[Z]) != 3) {
3493  bu_vls_printf(gedp->ged_result_str, "bad data point - %s\n", av[i]);
3494 
3495  bu_free((void *)gdlsp->gdls_points, "data points");
3496  gdlsp->gdls_points = (point_t *)0;
3497  gdlsp->gdls_num_points = 0;
3498 
3499  to_refresh_view(gdvp);
3500  Tcl_Free((char *)av);
3501  return GED_ERROR;
3502  }
3503  /* convert double to fastf_t */
3504  VMOVE(gdlsp->gdls_points[i], scan);
3505  }
3506 
3507  to_refresh_view(gdvp);
3508  Tcl_Free((char *)av);
3509  return GED_OK;
3510  }
3511  }
3512 
3513 bad:
3514  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3515  return GED_ERROR;
3516 }
3517 
3518 
3519 /* These functions should be macros */
3520 HIDDEN void
3522 {
3523  register size_t j;
3524 
3525  if (gpp->gp_num_contours == 0)
3526  return;
3527 
3528  for (j = 0; j < gpp->gp_num_contours; ++j)
3529  bu_free((void *)gpp->gp_contour[j].gpc_point, "gp_contour points");
3530 
3531  bu_free((void *)gpp->gp_contour, "gp_contour");
3532  bu_free((void *)gpp->gp_hole, "gp_hole");
3533  gpp->gp_num_contours = 0;
3534 }
3535 
3536 
3537 HIDDEN void
3539 {
3540  register size_t i;
3541 
3542  if (gpp->gp_num_polygons == 0)
3543  return;
3544 
3545  for (i = 0; i < gpp->gp_num_polygons; ++i) {
3546  to_polygon_free(&gpp->gp_polygon[i]);
3547  }
3548 
3549  bu_free((void *)gpp->gp_polygon, "data polygons");
3550  gpp->gp_polygon = (bview_polygon *)0;
3551  gpp->gp_num_polygons = 0;
3552 }
3553 
3554 
3555 HIDDEN int
3556 to_extract_contours_av(struct ged *gedp, struct ged_dm_view *gdvp, bview_polygon *gpp, size_t contour_ac, const char **contour_av, int mode, int vflag)
3557 {
3558  register size_t j = 0, k = 0;
3559 
3560  gpp->gp_num_contours = contour_ac;
3561  gpp->gp_hole = NULL;
3562  gpp->gp_contour = NULL;
3563 
3564  if (contour_ac == 0)
3565  return GED_OK;
3566 
3567  gpp->gp_hole = (int *)bu_calloc(contour_ac, sizeof(int), "gp_hole");
3568  gpp->gp_contour = (bview_poly_contour *)bu_calloc(contour_ac, sizeof(bview_poly_contour), "gp_contour");
3569 
3570  for (j = 0; j < contour_ac; ++j) {
3571  int ac;
3572  size_t point_ac;
3573  const char **point_av;
3574  int hole;
3575 
3576  /* Split contour j into points */
3577  if (Tcl_SplitList(current_top->to_interp, contour_av[j], &ac, &point_av) != TCL_OK) {
3578  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
3579  return GED_ERROR;
3580  }
3581  point_ac = ac;
3582 
3583  /* point_ac includes a hole flag */
3584  if (mode != TCLCAD_POLY_CONTOUR_MODE && point_ac < 4) {
3585  bu_vls_printf(gedp->ged_result_str, "There must be at least 3 points per contour");
3586  Tcl_Free((char *)point_av);
3587  return GED_ERROR;
3588  }
3589 
3590  gpp->gp_contour[j].gpc_num_points = point_ac - 1;
3591  gpp->gp_contour[j].gpc_point = (point_t *)bu_calloc(point_ac, sizeof(point_t), "gpc_point");
3592 
3593  if (bu_sscanf(point_av[0], "%d", &hole) != 1) {
3594  bu_vls_printf(gedp->ged_result_str, "contour %zu, point %zu: bad hole flag - %s\n",
3595  j, k, point_av[k]);
3596  Tcl_Free((char *)point_av);
3597  return GED_ERROR;
3598  }
3599  gpp->gp_hole[j] = hole;
3600 
3601  for (k = 1; k < point_ac; ++k) {
3602  double pt[ELEMENTS_PER_POINT]; /* must be double for scanf */
3603 
3604  if (bu_sscanf(point_av[k], "%lf %lf %lf", &pt[X], &pt[Y], &pt[Z]) != 3) {
3605  bu_vls_printf(gedp->ged_result_str, "contour %zu, point %zu: bad data point - %s\n",
3606  j, k, point_av[k]);
3607  Tcl_Free((char *)point_av);
3608  return GED_ERROR;
3609  }
3610 
3611  if (vflag) {
3612  MAT4X3PNT(gpp->gp_contour[j].gpc_point[k-1], gdvp->gdv_view->gv_view2model, pt);
3613  } else {
3614  VMOVE(gpp->gp_contour[j].gpc_point[k-1], pt);
3615  }
3616 
3617  }
3618 
3619  Tcl_Free((char *)point_av);
3620  }
3621 
3622  return GED_OK;
3623 }
3624 
3625 
3626 HIDDEN int
3627 to_extract_polygons_av(struct ged *gedp, struct ged_dm_view *gdvp, bview_polygons *gpp, size_t polygon_ac, const char **polygon_av, int mode, int vflag)
3628 {
3629  register size_t i;
3630  int ac;
3631 
3632  gpp->gp_num_polygons = polygon_ac;
3633  gpp->gp_polygon = (bview_polygon *)bu_calloc(polygon_ac, sizeof(bview_polygon), "data polygons");
3634 
3635  for (i = 0; i < polygon_ac; ++i) {
3636  size_t contour_ac;
3637  const char **contour_av;
3638 
3639  /* Split polygon i into contours */
3640  if (Tcl_SplitList(current_top->to_interp, polygon_av[i], &ac, &contour_av) != TCL_OK) {
3641  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
3642  return GED_ERROR;
3643  }
3644  contour_ac = ac;
3645 
3646  if (to_extract_contours_av(gedp, gdvp, &gpp->gp_polygon[i], contour_ac, contour_av, mode, vflag) != GED_OK) {
3647  Tcl_Free((char *)contour_av);
3648  return GED_ERROR;
3649  }
3650 
3651  if (contour_ac)
3652  Tcl_Free((char *)contour_av);
3653  }
3654 
3655  return GED_OK;
3656 }
3657 
3658 
3659 HIDDEN int
3660 to_data_polygons(struct ged *gedp,
3661  int argc,
3662  const char *argv[],
3663  ged_func_ptr UNUSED(func),
3664  const char *usage,
3665  int UNUSED(maxargs))
3666 {
3667  struct ged_dm_view *gdvp;
3668  bview_data_polygon_state *gdpsp;
3669 
3670  /* initialize result */
3671  bu_vls_trunc(gedp->ged_result_str, 0);
3672 
3673  /* must be wanting help */
3674  if (argc == 1) {
3675  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3676  return GED_HELP;
3677  }
3678 
3679  if (argc < 3 || 7 < argc) {
3680  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
3681  return GED_ERROR;
3682  }
3683 
3684  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
3685  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
3686  break;
3687  }
3688 
3689  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
3690  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
3691  return GED_ERROR;
3692  }
3693 
3694  if (argv[0][0] == 's')
3695  gdpsp = &gdvp->gdv_view->gv_sdata_polygons;
3696  else
3697  gdpsp = &gdvp->gdv_view->gv_data_polygons;
3698 
3699  gdpsp->gdps_scale = gdvp->gdv_view->gv_scale;
3700  gdpsp->gdps_data_vZ = gdvp->gdv_view->gv_data_vZ;
3701  VMOVE(gdpsp->gdps_origin, gdvp->gdv_view->gv_center);
3702  MAT_COPY(gdpsp->gdps_rotation, gdvp->gdv_view->gv_rotation);
3703  MAT_COPY(gdpsp->gdps_model2view, gdvp->gdv_view->gv_model2view);
3704  MAT_COPY(gdpsp->gdps_view2model, gdvp->gdv_view->gv_view2model);
3705 
3706  if (BU_STR_EQUAL(argv[2], "target_poly")) {
3707  if (argc == 3) {
3708  bu_vls_printf(gedp->ged_result_str, "%zu", gdpsp->gdps_target_polygon_i);
3709  return GED_OK;
3710  }
3711 
3712  if (argc == 4) {
3713  size_t i;
3714 
3715  if (bu_sscanf(argv[3], "%zu", &i) != 1 || i > gdpsp->gdps_polygons.gp_num_polygons)
3716  goto bad;
3717 
3718  gdpsp->gdps_target_polygon_i = i;
3719 
3720  return GED_OK;
3721  }
3722 
3723  goto bad;
3724  }
3725 
3726  if (BU_STR_EQUAL(argv[2], "clip_type")) {
3727  if (argc == 3) {
3728  bu_vls_printf(gedp->ged_result_str, "%d", gdpsp->gdps_clip_type);
3729  return GED_OK;
3730  }
3731 
3732  if (argc == 4) {
3733  int op;
3734 
3735  if (bu_sscanf(argv[3], "%d", &op) != 1 || op > gctXor)
3736  goto bad;
3737 
3738  gdpsp->gdps_clip_type = (ClipType)op;
3739 
3740  return GED_OK;
3741  }
3742 
3743  goto bad;
3744  }
3745 
3746  if (BU_STR_EQUAL(argv[2], "draw")) {
3747  if (argc == 3) {
3748  bu_vls_printf(gedp->ged_result_str, "%d", gdpsp->gdps_draw);
3749  return GED_OK;
3750  }
3751 
3752  if (argc == 4) {
3753  int i;
3754 
3755  if (bu_sscanf(argv[3], "%d", &i) != 1)
3756  goto bad;
3757 
3758  if (i)
3759  gdpsp->gdps_draw = 1;
3760  else
3761  gdpsp->gdps_draw = 0;
3762 
3763  to_refresh_view(gdvp);
3764  return GED_OK;
3765  }
3766 
3767  goto bad;
3768  }
3769 
3770  /* Usage: poly_color i [r g b]
3771  *
3772  * Set/get the color of polygon i.
3773  */
3774  if (BU_STR_EQUAL(argv[2], "poly_color")) {
3775  size_t i;
3776 
3777  if (argc == 4) {
3778  /* Get the color for polygon i */
3779  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
3780  i >= gdpsp->gdps_polygons.gp_num_polygons)
3781  goto bad;
3782 
3783  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
3785 
3786  return GED_OK;
3787  }
3788 
3789  if (argc == 7) {
3790  int r, g, b;
3791 
3792  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
3793  i >= gdpsp->gdps_polygons.gp_num_polygons)
3794  goto bad;
3795 
3796  /* set background color */
3797  if (bu_sscanf(argv[4], "%d", &r) != 1 ||
3798  bu_sscanf(argv[5], "%d", &g) != 1 ||
3799  bu_sscanf(argv[6], "%d", &b) != 1)
3800  goto bad;
3801 
3802  /* validate color */
3803  if (r < 0 || 255 < r ||
3804  g < 0 || 255 < g ||
3805  b < 0 || 255 < b)
3806  goto bad;
3807 
3808  /* Set the color for polygon i */
3809  VSET(gdpsp->gdps_polygons.gp_polygon[i].gp_color, r, g, b);
3810 
3811  to_refresh_view(gdvp);
3812  return GED_OK;
3813  }
3814 
3815  goto bad;
3816  }
3817 
3818  /* Usage: color [r g b]
3819  *
3820  * Set the color of all polygons, or get the default polygon color.
3821  */
3822  if (BU_STR_EQUAL(argv[2], "color")) {
3823  size_t i;
3824 
3825  if (argc == 3) {
3826  bu_vls_printf(gedp->ged_result_str, "%d %d %d",
3827  V3ARGS(gdpsp->gdps_color));
3828 
3829  return GED_OK;
3830  }
3831 
3832  if (argc == 6) {
3833  int r, g, b;
3834 
3835  /* set background color */
3836  if (bu_sscanf(argv[3], "%d", &r) != 1 ||
3837  bu_sscanf(argv[4], "%d", &g) != 1 ||
3838  bu_sscanf(argv[5], "%d", &b) != 1)
3839  goto bad;
3840 
3841  /* validate color */
3842  if (r < 0 || 255 < r ||
3843  g < 0 || 255 < g ||
3844  b < 0 || 255 < b)
3845  goto bad;
3846 
3847  /* Set the color for all polygons */
3848  for (i = 0; i < gdpsp->gdps_polygons.gp_num_polygons; ++i) {
3849  VSET(gdpsp->gdps_polygons.gp_polygon[i].gp_color, r, g, b);
3850  }
3851 
3852  /* Set the default polygon color */
3853  VSET(gdpsp->gdps_color, r, g, b);
3854 
3855  to_refresh_view(gdvp);
3856  return GED_OK;
3857  }
3858 
3859  goto bad;
3860  }
3861 
3862  /* Usage: poly_line_width i [w]
3863  *
3864  * Set/get the line width of polygon i.
3865  */
3866  if (BU_STR_EQUAL(argv[2], "poly_line_width")) {
3867  size_t i;
3868 
3869  if (argc == 4) {
3870  /* Get the line width for polygon i */
3871  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
3872  i >= gdpsp->gdps_polygons.gp_num_polygons)
3873  goto bad;
3874 
3876 
3877  return GED_OK;
3878  }
3879 
3880  if (argc == 5) {
3881  int line_width;
3882 
3883  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
3884  i >= gdpsp->gdps_polygons.gp_num_polygons)
3885  goto bad;
3886 
3887  if (bu_sscanf(argv[4], "%d", &line_width) != 1)
3888  goto bad;
3889 
3890  if (line_width < 0)
3891  line_width = 0;
3892 
3893  gdpsp->gdps_polygons.gp_polygon[i].gp_line_width = line_width;
3894 
3895  to_refresh_view(gdvp);
3896  return GED_OK;
3897  }
3898 
3899  goto bad;
3900  }
3901 
3902  /* Usage: line_width [w]
3903  *
3904  * Set the line width of all polygons, or get the default polygon line width.
3905  */
3906  if (BU_STR_EQUAL(argv[2], "line_width")) {
3907  size_t i;
3908 
3909  if (argc == 3) {
3910  bu_vls_printf(gedp->ged_result_str, "%d", gdpsp->gdps_line_width);
3911  return GED_OK;
3912  }
3913 
3914  if (argc == 4) {
3915  int line_width;
3916 
3917  if (bu_sscanf(argv[3], "%d", &line_width) != 1)
3918  goto bad;
3919 
3920  if (line_width < 0)
3921  line_width = 0;
3922 
3923  /* Set the line width for all polygons */
3924  for (i = 0; i < gdpsp->gdps_polygons.gp_num_polygons; ++i) {
3925  gdpsp->gdps_polygons.gp_polygon[i].gp_line_width = line_width;
3926  }
3927 
3928  /* Set the default line width */
3929  gdpsp->gdps_line_width = line_width;
3930 
3931  to_refresh_view(gdvp);
3932  return GED_OK;
3933  }
3934 
3935  goto bad;
3936  }
3937 
3938  /* Usage: poly_line_style i [w]
3939  *
3940  * Set/get the line style of polygon i.
3941  */
3942  if (BU_STR_EQUAL(argv[2], "poly_line_style")) {
3943  size_t i;
3944 
3945  if (argc == 4) {
3946  /* Get the line style for polygon i */
3947  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
3948  i >= gdpsp->gdps_polygons.gp_num_polygons)
3949  goto bad;
3950 
3952 
3953  return GED_OK;
3954  }
3955 
3956  if (argc == 5) {
3957  int line_style;
3958 
3959  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
3960  i >= gdpsp->gdps_polygons.gp_num_polygons)
3961  goto bad;
3962 
3963  if (bu_sscanf(argv[4], "%d", &line_style) != 1)
3964  goto bad;
3965 
3966 
3967  if (line_style <= 0)
3968  gdpsp->gdps_polygons.gp_polygon[i].gp_line_style = 0;
3969  else
3970  gdpsp->gdps_polygons.gp_polygon[i].gp_line_style = 1;
3971 
3972  to_refresh_view(gdvp);
3973  return GED_OK;
3974  }
3975 
3976  goto bad;
3977  }
3978 
3979  /* Usage: line_style [w]
3980  *
3981  * Set the line style of all polygons, or get the default polygon line style.
3982  */
3983  if (BU_STR_EQUAL(argv[2], "line_style")) {
3984  size_t i;
3985 
3986  if (argc == 3) {
3987  bu_vls_printf(gedp->ged_result_str, "%d", gdpsp->gdps_line_style);
3988  return GED_OK;
3989  }
3990 
3991  if (argc == 4) {
3992  int line_style;
3993 
3994  if (bu_sscanf(argv[3], "%d", &line_style) != 1)
3995  goto bad;
3996 
3997  if (line_style <= 0)
3998  line_style = 0;
3999  else
4000  line_style = 1;
4001 
4002  /* Set the line width for all polygons */
4003  for (i = 0; i < gdpsp->gdps_polygons.gp_num_polygons; ++i) {
4004  gdpsp->gdps_polygons.gp_polygon[i].gp_line_style = line_style;
4005  }
4006 
4007  /* Set the default line style */
4008  gdpsp->gdps_line_style = line_style;
4009 
4010  to_refresh_view(gdvp);
4011  return GED_OK;
4012  }
4013 
4014  goto bad;
4015  }
4016 
4017  /* Usage: append_poly plist
4018  *
4019  * Append the polygon specified by plist.
4020  */
4021  if (BU_STR_EQUAL(argv[2], "append_poly")) {
4022  if (argc != 4)
4023  goto bad;
4024 
4025  if (argc == 4) {
4026  register size_t i;
4027  int ac;
4028  size_t contour_ac;
4029  const char **contour_av;
4030 
4031  /* Split the polygon in argv[3] into contours */
4032  if (Tcl_SplitList(current_top->to_interp, argv[3], &ac, &contour_av) != TCL_OK ||
4033  ac < 1) {
4034  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
4035  return GED_ERROR;
4036  }
4037  contour_ac = ac;
4038 
4039  i = gdpsp->gdps_polygons.gp_num_polygons;
4040  ++gdpsp->gdps_polygons.gp_num_polygons;
4042  gdpsp->gdps_polygons.gp_num_polygons * sizeof(bview_polygon),
4043  "realloc gp_polygon");
4044 
4045  if (to_extract_contours_av(gedp, gdvp, &gdpsp->gdps_polygons.gp_polygon[i],
4046  contour_ac, contour_av, gdvp->gdv_view->gv_mode, 0) != GED_OK) {
4047  Tcl_Free((char *)contour_av);
4048  return GED_ERROR;
4049  }
4050 
4051  VMOVE(gdpsp->gdps_polygons.gp_polygon[i].gp_color, gdpsp->gdps_color);
4054 
4055  Tcl_Free((char *)contour_av);
4056 
4057  to_refresh_view(gdvp);
4058  return GED_OK;
4059  }
4060  }
4061 
4062 
4063  /* Usage: clip [i j [op]]
4064  *
4065  * Clip polygon i using polygon j and op.
4066  */
4067  if (BU_STR_EQUAL(argv[2], "clip")) {
4068  size_t i, j;
4069  int op;
4070  bview_polygon *gpp;
4071 
4072  if (argc > 6)
4073  goto bad;
4074 
4075  if (argc > 3) {
4076  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4077  i >= gdpsp->gdps_polygons.gp_num_polygons)
4078  goto bad;
4079  } else
4080  i = gdpsp->gdps_target_polygon_i;
4081 
4082  if (argc > 4) {
4083  if (bu_sscanf(argv[4], "%zu", &j) != 1 ||
4084  j >= gdpsp->gdps_polygons.gp_num_polygons)
4085  goto bad;
4086  } else
4087  j = gdpsp->gdps_polygons.gp_num_polygons - 1; /* Default - use last polygon as the clip polygon */
4088 
4089  if (argc != 6)
4090  op = gdpsp->gdps_clip_type;
4091  else if (bu_sscanf(argv[5], "%d", &op) != 1 || op > gctXor)
4092  goto bad;
4093 
4094  gpp = ged_clip_polygon((ClipType)op,
4095  &gdpsp->gdps_polygons.gp_polygon[i],
4096  &gdpsp->gdps_polygons.gp_polygon[j],
4097  CLIPPER_MAX,
4098  gdpsp->gdps_model2view,
4099  gdpsp->gdps_view2model);
4100 
4101  /* Free the target polygon */
4103 
4104  /* When using defaults, the clip polygon is assumed to be temporary and is removed after clipping */
4105  if (argc == 3) {
4106  /* Free the clip polygon */
4108 
4109  /* No longer need space for the clip polygon */
4110  --gdpsp->gdps_polygons.gp_num_polygons;
4112  gdpsp->gdps_polygons.gp_num_polygons * sizeof(bview_polygon),
4113  "realloc gp_polygon");
4114  }
4115 
4116  /* Replace the target polygon with the newly clipped polygon. */
4117  /* Not doing a struct copy to avoid overwriting the color, line width and line style. */
4119  gdpsp->gdps_polygons.gp_polygon[i].gp_hole = gpp->gp_hole;
4120  gdpsp->gdps_polygons.gp_polygon[i].gp_contour = gpp->gp_contour;
4121 
4122  /* Free the clipped polygon container */
4123  bu_free((void *)gpp, "clip gpp");
4124 
4125  to_refresh_view(gdvp);
4126  return GED_OK;
4127  }
4128 
4129  /* Usage: export i sketch_name
4130  *
4131  * Export polygon i to sketch_name
4132  */
4133  if (BU_STR_EQUAL(argv[2], "export")) {
4134  size_t i;
4135  int ret;
4136 
4137  if (argc != 5)
4138  goto bad;
4139 
4140  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4141  i >= gdpsp->gdps_polygons.gp_num_polygons)
4142  goto bad;
4143 
4144  if ((ret = ged_export_polygon(gedp, gdpsp, i, argv[4])) != GED_OK)
4145  bu_vls_printf(gedp->ged_result_str, "%s: failed to export polygon %zu to %s", argv[0], i, argv[4]);
4146 
4147  return ret;
4148  }
4149 
4150  /* Usage: import sketch_name
4151  *
4152  * Import sketch_name and append
4153  */
4154  if (BU_STR_EQUAL(argv[2], "import")) {
4155  bview_polygon *gpp;
4156  size_t i;
4157 
4158  if (argc != 4)
4159  goto bad;
4160 
4161  if ((gpp = ged_import_polygon(gedp, argv[3])) == (bview_polygon *)0) {
4162  bu_vls_printf(gedp->ged_result_str, "%s: failed to import sketch %s", argv[0], argv[3]);
4163  return GED_ERROR;
4164  }
4165 
4166  i = gdpsp->gdps_polygons.gp_num_polygons;
4167  ++gdpsp->gdps_polygons.gp_num_polygons;
4169  gdpsp->gdps_polygons.gp_num_polygons * sizeof(bview_polygon),
4170  "realloc gp_polygon");
4171 
4172  gdpsp->gdps_polygons.gp_polygon[i] = *gpp; /* struct copy */
4173  VMOVE(gdpsp->gdps_polygons.gp_polygon[i].gp_color, gdpsp->gdps_color);
4176 
4177  to_refresh_view(gdvp);
4178  return GED_OK;
4179  }
4180 
4181  /* Usage: area i
4182  *
4183  * Find area of polygon i
4184  */
4185  if (BU_STR_EQUAL(argv[2], "area")) {
4186  size_t i;
4187  double area;
4188 
4189  if (argc != 4)
4190  goto bad;
4191 
4192  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4193  i >= gdpsp->gdps_polygons.gp_num_polygons)
4194  goto bad;
4195 
4197  gdpsp->gdps_model2view, gdpsp->gdps_scale);
4198  bu_vls_printf(gedp->ged_result_str, "%lf", area);
4199 
4200  return GED_OK;
4201  }
4202 
4203  /* Usage: polygons_overlap i j
4204  *
4205  * Do polygons i and j overlap?
4206  */
4207  if (BU_STR_EQUAL(argv[2], "polygons_overlap")) {
4208  size_t i, j;
4209  int ret;
4210 
4211  if (argc != 5)
4212  goto bad;
4213 
4214  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4215  i >= gdpsp->gdps_polygons.gp_num_polygons)
4216  goto bad;
4217 
4218  if (bu_sscanf(argv[4], "%zu", &j) != 1 ||
4219  j >= gdpsp->gdps_polygons.gp_num_polygons)
4220  goto bad;
4221 
4222  ret = ged_polygons_overlap(gedp, &gdpsp->gdps_polygons.gp_polygon[i], &gdpsp->gdps_polygons.gp_polygon[j]);
4223  bu_vls_printf(gedp->ged_result_str, "%d", ret);
4224 
4225  return GED_OK;
4226  }
4227 
4228  /* Usage: [v]polygons [poly_list]
4229  *
4230  * Set/get the polygon list. If vpolygons is specified then
4231  * the polygon list is in view coordinates.
4232  */
4233  if (BU_STR_EQUAL(argv[2], "polygons") || BU_STR_EQUAL(argv[2], "vpolygons")) {
4234  register size_t i, j, k;
4235  int ac;
4236  int vflag;
4237 
4238  if (BU_STR_EQUAL(argv[2], "polygons"))
4239  vflag = 0;
4240  else
4241  vflag = 1;
4242 
4243  if (argc == 3) {
4244  for (i = 0; i < gdpsp->gdps_polygons.gp_num_polygons; ++i) {
4245  bu_vls_printf(gedp->ged_result_str, " {");
4246 
4247  for (j = 0; j < gdpsp->gdps_polygons.gp_polygon[i].gp_num_contours; ++j) {
4248  bu_vls_printf(gedp->ged_result_str, " {%d ", gdpsp->gdps_polygons.gp_polygon[i].gp_hole[j]);
4249 
4250  for (k = 0; k < gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_num_points; ++k) {
4251  point_t pt;
4252 
4253  if (vflag) {
4254  MAT4X3PNT(pt, gdvp->gdv_view->gv_model2view, gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k]);
4255  } else {
4256  VMOVE(pt, gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k]);
4257  }
4258 
4259  bu_vls_printf(gedp->ged_result_str, " {%lf %lf %lf} ", V3ARGS(pt));
4260  }
4261 
4262  bu_vls_printf(gedp->ged_result_str, "} ");
4263  }
4264 
4265  bu_vls_printf(gedp->ged_result_str, "} ");
4266  }
4267 
4268  return GED_OK;
4269  }
4270 
4271  if (argc == 4) {
4272  size_t polygon_ac;
4273  const char **polygon_av;
4274 
4275  /* Split into polygons */
4276  if (Tcl_SplitList(current_top->to_interp, argv[3], &ac, &polygon_av) != TCL_OK) {
4277  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
4278  return GED_ERROR;
4279  }
4280  polygon_ac = ac;
4281 
4283  gdpsp->gdps_target_polygon_i = 0;
4284 
4285  if (polygon_ac < 1) {
4286  to_refresh_view(gdvp);
4287  return GED_OK;
4288  }
4289 
4290  if (to_extract_polygons_av(gedp, gdvp, &gdpsp->gdps_polygons, polygon_ac, polygon_av, gdvp->gdv_view->gv_mode, vflag) != GED_OK) {
4291  Tcl_Free((char *)polygon_av);
4292  return GED_ERROR;
4293  }
4294 
4295  Tcl_Free((char *)polygon_av);
4296  to_refresh_view(gdvp);
4297  return GED_OK;
4298  }
4299  }
4300 
4301  /* Usage: replace_poly i plist
4302  *
4303  * Replace polygon i with plist.
4304  */
4305  if (BU_STR_EQUAL(argv[2], "replace_poly")) {
4306  size_t i;
4307  int ac;
4308  size_t contour_ac;
4309  const char **contour_av;
4310  bview_polygon gp;
4311 
4312  if (argc != 5)
4313  goto bad;
4314 
4315  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4316  i >= gdpsp->gdps_polygons.gp_num_polygons)
4317  goto bad;
4318 
4319  /* Split the polygon in argv[4] into contours */
4320  if (Tcl_SplitList(current_top->to_interp, argv[4], &ac, &contour_av) != TCL_OK ||
4321  ac < 1) {
4322  bu_vls_printf(gedp->ged_result_str, "%s", Tcl_GetStringResult(current_top->to_interp));
4323  return GED_ERROR;
4324  }
4325  contour_ac = ac;
4326 
4327  if (to_extract_contours_av(gedp, gdvp, &gp, contour_ac, contour_av, gdvp->gdv_view->gv_mode, 0) != GED_OK) {
4328  Tcl_Free((char *)contour_av);
4329  return GED_ERROR;
4330  }
4331 
4333 
4334  /* Not doing a struct copy to avoid overwriting the color, line width and line style. */
4336  gdpsp->gdps_polygons.gp_polygon[i].gp_hole = gp.gp_hole;
4338 
4339  to_refresh_view(gdvp);
4340  return GED_OK;
4341  }
4342 
4343  /* Usage: append_point i j pt
4344  *
4345  * Append pt to polygon_i/contour_j
4346  */
4347  if (BU_STR_EQUAL(argv[2], "append_point")) {
4348  size_t i, j, k;
4349  double pt[ELEMENTS_PER_POINT]; /* must be double for scan */
4350 
4351  if (argc != 6)
4352  goto bad;
4353 
4354  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4355  i >= gdpsp->gdps_polygons.gp_num_polygons)
4356  goto bad;
4357 
4358  if (bu_sscanf(argv[4], "%zu", &j) != 1 ||
4359  j >= gdpsp->gdps_polygons.gp_polygon[i].gp_num_contours)
4360  goto bad;
4361 
4362  if (bu_sscanf(argv[5], "%lf %lf %lf", &pt[X], &pt[Y], &pt[Z]) != 3)
4363  goto bad;
4364 
4368  gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_num_points * sizeof(point_t),
4369  "realloc gpc_point");
4370  VMOVE(gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k], pt);
4371  to_refresh_view(gdvp);
4372  return GED_OK;
4373  }
4374 
4375  /* Usage: get_point i j k
4376  *
4377  * Get polygon_i/contour_j/point_k
4378  */
4379  if (BU_STR_EQUAL(argv[2], "get_point")) {
4380  size_t i, j, k;
4381 
4382  if (argc != 6)
4383  goto bad;
4384 
4385  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4386  i >= gdpsp->gdps_polygons.gp_num_polygons)
4387  goto bad;
4388 
4389  if (bu_sscanf(argv[4], "%zu", &j) != 1 ||
4390  j >= gdpsp->gdps_polygons.gp_polygon[i].gp_num_contours)
4391  goto bad;
4392 
4393  if (bu_sscanf(argv[5], "%zu", &k) != 1 ||
4395  goto bad;
4396 
4397  bu_vls_printf(gedp->ged_result_str, "%lf %lf %lf", V3ARGS(gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k]));
4398  return GED_OK;
4399  }
4400 
4401  /* Usage: replace_point i j k pt
4402  *
4403  * Replace polygon_i/contour_j/point_k with pt
4404  */
4405  if (BU_STR_EQUAL(argv[2], "replace_point")) {
4406  size_t i, j, k;
4407  double pt[ELEMENTS_PER_POINT];
4408 
4409  if (argc != 7)
4410  goto bad;
4411 
4412  if (bu_sscanf(argv[3], "%zu", &i) != 1 ||
4413  i >= gdpsp->gdps_polygons.gp_num_polygons)
4414  goto bad;
4415 
4416  if (bu_sscanf(argv[4], "%zu", &j) != 1 ||
4417  j >= gdpsp->gdps_polygons.gp_polygon[i].gp_num_contours)
4418  goto bad;
4419 
4420  if (bu_sscanf(argv[5], "%zu", &k) != 1 ||
4422  goto bad;
4423 
4424  if (bu_sscanf(argv[6], "%lf %lf %lf", &pt[X], &pt[Y], &pt[Z]) != 3)
4425  goto bad;
4426 
4427  VMOVE(gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k], pt);
4428  to_refresh_view(gdvp);
4429  return GED_OK;
4430  }
4431 
4432 bad:
4433  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
4434  return GED_ERROR;
4435 }
4436 
4437 
4438 /*
4439  * Usage: data_move vname dtype dindex mx my
4440  */
4441 HIDDEN int
4442 to_data_move(struct ged *gedp,
4443  int argc,
4444  const char *argv[],
4445  ged_func_ptr UNUSED(func),
4446  const char *usage,
4447  int UNUSED(maxargs))
4448 {
4449  int mx, my;
4450  int width, height;
4451  int dindex;
4452  fastf_t cx, cy;
4453  fastf_t vx, vy;
4454  fastf_t sf;
4455  point_t mpoint, vpoint;
4456  struct ged_dm_view *gdvp;
4457 
4458  /* initialize result */
4459  bu_vls_trunc(gedp->ged_result_str, 0);
4460 
4461  /* must be wanting help */
4462  if (argc == 1) {
4463  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
4464  return GED_HELP;
4465  }
4466 
4467  if (argc < 5 || 6 < argc) {
4468  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
4469  return GED_ERROR;
4470  }
4471 
4472  for (BU_LIST_FOR(gdvp, ged_dm_view, &current_top->to_gop->go_head_views.l)) {
4473  if (BU_STR_EQUAL(bu_vls_addr(&gdvp->gdv_name), argv[1]))
4474  break;
4475  }
4476 
4477  if (BU_LIST_IS_HEAD(&gdvp->l, &current_top->to_gop->go_head_views.l)) {
4478  bu_vls_printf(gedp->ged_result_str, "View not found - %s", argv[1]);
4479  return GED_ERROR;
4480  }
4481 
4482  if (bu_sscanf(argv[3], "%d", &dindex) != 1 || dindex < 0)
4483  goto bad;
4484 
4485  if (argc == 5) {
4486  if (bu_sscanf(argv[4], "%d %d", &mx, &my) != 2)
4487  goto bad;
4488  } else {
4489  if (bu_sscanf(argv[4], "%d", &mx) != 1)
4490  goto bad;
4491 
4492  if (bu_sscanf(argv[5], "%d", &my) != 1)
4493  goto bad;
4494  }
4495 
4496  width = dm_get_width(gdvp->gdv_dmp);
4497  cx = 0.5 * (fastf_t)width;
4498  height = dm_get_height(gdvp->gdv_dmp);
4499  cy = 0.5 * (fastf_t)height;
4500  sf = 2.0 / width;
4501  vx = (mx - cx) * sf;
4502  vy = (cy - my) * sf;
4503 
4504  if (BU_STR_EQUAL(argv[2], "data_polygons")) {
4505  size_t i, j, k;
4507 
4508  if (bu_sscanf(argv[3], "%zu %zu %zu", &i, &j, &k) != 3)
4509  goto bad;
4510 
4511  /* Silently ignore */
4512  if (i >= gdpsp->gdps_polygons.gp_num_polygons ||
4513  j >= gdpsp->gdps_polygons.gp_polygon[i].gp_num_contours ||
4515  return GED_OK;
4516 
4517  /* This section is for moving the entire contour */
4519  point_t old_mpoint, new_mpoint;
4520  vect_t diff;
4521 
4522  VMOVE(old_mpoint, gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k]);
4523 
4524  MAT4X3PNT(vpoint, gdvp->gdv_view->gv_model2view, gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k]);
4525  vpoint[X] = vx;
4526  vpoint[Y] = vy;
4527  MAT4X3PNT(new_mpoint, gdvp->gdv_view->gv_view2model, vpoint);
4528  VSUB2(diff, new_mpoint, old_mpoint);
4529 
4530  for (k = 0; k < gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_num_points; ++k) {
4531  VADD2(gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k],
4532  gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k],
4533  diff);
4534  }
4535  } else {
4536  /* This section is for moving a single point in the contour */
4537  MAT4X3PNT(vpoint, gdvp->gdv_view->gv_model2view, gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k]);
4538  vpoint[X] = vx;
4539  vpoint[Y] = vy;
4540  MAT4X3PNT(gdpsp->gdps_polygons.gp_polygon[i].gp_contour[j].gpc_point[k], gdvp->gdv_view->gv_view2model, vpoint);
4541  }
4542 
4543  to_refresh_view(gdvp);
4544  return GED_OK;
4545  }
4546 
4547  if (BU_STR_EQUAL(argv[2], "data_arrows")) {
4548  struct bview_data_arrow_state *gdasp = &gdvp->gdv_view->gv_data_arrows;
4549 
4550  /* Silently ignore */
4551  if (dindex >= gdvp->gdv_view->gv_data_arrows.gdas_num_points)
4552  return GED_OK;
4553 
4554  /* This section is for moving the entire arrow */