BRL-CAD
joint.c
Go to the documentation of this file.
1 /* J O I N T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-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 /** @file libged/joint.c
21  *
22  * Process all animation edit commands.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <math.h>
32 
33 
34 #include "bu/getopt.h"
35 
36 #include "raytrace.h"
37 
38 #include "./joint.h"
39 #include "./ged_private.h"
40 
41 static unsigned int J_DEBUG = 0;
42 #define DEBUG_J_MESH 0x00000001
43 #define DEBUG_J_LOAD 0x00000002
44 #define DEBUG_J_MOVE 0x00000004
45 #define DEBUG_J_SOLVE 0x00000008
46 #define DEBUG_J_EVAL 0x00000010
47 #define DEBUG_J_SYSTEM 0x00000020
48 #define DEBUG_J_PARSE 0x00000040
49 #define DEBUG_J_LEX 0x00000080
50 #define J_DEBUG_FORMAT \
51  "\020\10LEX\7PARSE\6SYSTEM\5EVAL\4SOLVE\3MOVE\2LOAD\1MESH"
52 
53 /* max object name length we expect to encounter for each arc node */
54 #define MAX_OBJ_NAME 255
55 
56 extern struct funtab joint_tab[];
57 
58 
59 struct artic_grips {
60  struct bu_list l;
61  vect_t vert;
62  struct directory *dir;
63 };
64 #define MAGIC_A_GRIP 0x414752aa
65 struct artic_joints {
66  struct bu_list l;
67  struct bu_list head;
68  struct joint *joint;
69 };
70 #define MAGIC_A_JOINT 0x414A4F55
71 
72 struct bu_list artic_head = {
74  &artic_head, &artic_head
75 };
76 
77 
78 struct bu_list joint_head = {
80  &joint_head, &joint_head
81 };
82 
83 
84 struct bu_list hold_head = {
86  &hold_head, &hold_head
87 };
88 
89 
90 struct joint *
91 findjoint(struct ged *gedp, const struct db_full_path *pathp)
92 {
93  size_t i, j;
94  struct joint *jp;
95  int best;
96  struct joint *bestjp = NULL;
97 
98  if (J_DEBUG & DEBUG_J_MESH) {
99  char *sofar = db_path_to_string(pathp);
100 
101  bu_vls_printf(gedp->ged_result_str, "joint mesh: PATH = '%s'\n", sofar);
102  bu_free(sofar, "path string");
103  }
104 
105  best = -1;
106  for (BU_LIST_FOR(jp, joint, &joint_head)) {
107  for (i=0; i< pathp->fp_len; i++) {
108  int good=1;
109  if (jp->path.arc_last+i >= pathp->fp_len)
110  break;
111  for (j=0; j<=(size_t)jp->path.arc_last;j++) {
112  const char *name = DB_FULL_PATH_GET(pathp, i+j)->d_namep;
113  if ((*name != *jp->path.arc[j]) ||
114  (!BU_STR_EQUAL(name, jp->path.arc[j]))) {
115  good=0;
116  break;
117  }
118  }
119 
120  if (good && (long)j>best) {
121  best = j;
122  bestjp = jp;
123  }
124  }
125  }
126  if (best > 0) {
127  if (J_DEBUG & DEBUG_J_MESH) {
128  bu_vls_printf(gedp->ged_result_str, "joint mesh: returning joint '%s'\n", bestjp->name);
129  }
130  return bestjp;
131  }
132 
133  if (J_DEBUG & DEBUG_J_MESH) {
134  bu_vls_printf(gedp->ged_result_str, "joint mesh: returning joint 'NULL'\n");
135  }
136  return (struct joint *) 0;
137 }
138 
139 
140 HIDDEN union tree *
141 mesh_leaf(struct db_tree_state *UNUSED(tsp), const struct db_full_path *pathp, struct rt_db_internal *ip, void *client_data)
142 {
143  struct ged *gedp = (struct ged *)client_data;
144  struct rt_grip_internal *gip;
145  struct artic_joints *newJoint;
146  struct artic_grips *newGrip;
147  struct joint *jp;
148  union tree *curtree;
149  struct directory *dp;
150 
151  RT_CK_FULL_PATH(pathp);
152  RT_CK_DB_INTERNAL(ip);
153 
154  if (ip->idb_type != ID_GRIP) {
155  return TREE_NULL;
156  }
157 
158  BU_ALLOC(curtree, union tree);
159  RT_TREE_INIT(curtree);
160  curtree->tr_op = OP_SOLID;
161  curtree->tr_op = OP_NOP;
162  dp = DB_FULL_PATH_CUR_DIR(pathp);
163 
164  /* get the grip information. */
165  gip = (struct rt_grip_internal *) ip->idb_ptr;
166 
167  /* find the joint that this grip belongs to. */
168  jp = findjoint(gedp, pathp);
169 
170  /* Get the grip structure. */
171  BU_ALLOC(newGrip, struct artic_grips);
172  newGrip->l.magic = MAGIC_A_GRIP;
173  VMOVE(newGrip->vert, gip->center);
174  newGrip->dir = dp;
175 
176  for (BU_LIST_FOR(newJoint, artic_joints, &artic_head)) {
177  if (newJoint->joint == jp) {
178  BU_LIST_APPEND(&newJoint->head, &(newGrip->l));
179  return curtree;
180  }
181  }
182 
183  /* we need a new joint thingie. */
184  BU_ALLOC(newJoint, struct artic_joints);
185  newJoint->l.magic = MAGIC_A_JOINT;
186  newJoint->joint = jp;
187 
188  BU_LIST_INIT(&newJoint->head);
189  BU_LIST_APPEND(&artic_head, &(newJoint->l));
190  BU_LIST_APPEND(&newJoint->head, &(newGrip->l));
191 
192  return curtree;
193 }
194 
195 
196 HIDDEN union tree *
197 mesh_end_region (struct db_tree_state *UNUSED(tsp), const struct db_full_path *UNUSED(pathp), union tree *curtree, void *UNUSED(client_data))
198 {
199  return curtree;
200 }
201 static struct db_tree_state mesh_initial_tree_state = {
202  RT_DBTS_MAGIC, /* magic */
203  0, /* ts_dbip */
204  0, /* ts_sofar */
205  0, 0, 0, /* region, air, gmater */
206  100, /* GIFT los */
207  {
208  /* struct mater_info ts_mater */
209  {1.0, 0.0, 0.0},/* color, RGB */
210  -1.0, /* Temperature */
211  0, /* override */
212  0, /* color inherit */
213  0, /* mater inherit */
214  (char *)NULL /* shader */
215  },
216  MAT_INIT_IDN,
217  REGION_NON_FASTGEN, /* ts_is_fastgen */
218  {
219  /* attribute value set */
220  BU_AVS_MAGIC,
221  0,
222  0,
223  NULL,
224  NULL,
225  NULL
226  }
227  ,
228  0, /* ts_stop_at_regions */
229  NULL, /* ts_region_start_func */
230  NULL, /* ts_region_end_func */
231  NULL, /* ts_leaf_func */
232  NULL, /* ts_ttol */
233  NULL, /* ts_tol */
234  NULL, /* ts_m */
235  NULL, /* ts_rtip */
236  NULL /* ts_resp */
237 };
238 
239 
240 static int
241 joint_mesh(struct ged *gedp, int argc, const char *argv[])
242 {
243  const char *name;
244  struct bn_vlblock*vbp;
245  struct bu_list *vhead;
246  struct artic_joints *jp;
247  struct artic_grips *gp, *gpp;
248  int i;
249  char *topv[2000];
250  int topc;
251 
252  if (gedp->ged_wdbp->dbip == DBI_NULL)
253  return GED_OK;
254 
255  if (argc <= 2) {
256  name = "_ANIM_";
257  } else {
258  name = argv[2];
259  }
260 
261  topc = ged_build_tops(gedp, topv, topv+2000);
263 
264  i = db_walk_tree(gedp->ged_wdbp->dbip, topc, (const char **)topv,
265  1, /* Number of cpus */
266  &mesh_initial_tree_state,
267  0, /* Begin region */
268  mesh_end_region, /* End region */
269  mesh_leaf, /* node */
270  (void *)gedp);
271 
272  /*
273  * Now we draw the overlays. We do this by building a mesh from
274  * each grip to every other grip in that list.
275  */
276  vbp = rt_vlblock_init();
277  vhead = rt_vlblock_find(vbp, 0x00, 0xff, 0xff);
278 
279  for (BU_LIST_FOR(jp, artic_joints, &artic_head)) {
280  i=0;
281  for (BU_LIST_FOR(gp, artic_grips, &jp->head)) {
282  i++;
283  for (gpp=BU_LIST_NEXT(artic_grips, &(gp->l));
284  BU_LIST_NOT_HEAD(gpp, &(jp->head));
285  gpp=BU_LIST_NEXT(artic_grips, &(gpp->l))) {
286  RT_ADD_VLIST(vhead, gp->vert, BN_VLIST_LINE_MOVE);
287  RT_ADD_VLIST(vhead, gpp->vert, BN_VLIST_LINE_DRAW);
288  }
289  }
290  if (J_DEBUG & DEBUG_J_MESH) {
291  bu_vls_printf(gedp->ged_result_str, "joint mesh: %s has %d grips.\n",
292  (jp->joint) ? jp->joint->name: "UNGROUPED", i);
293  }
294  }
295 
296  _ged_cvt_vlblock_to_solids(gedp, vbp, name, 0);
297 
298  rt_vlblock_free(vbp);
299  while (BU_LIST_WHILE(jp, artic_joints, &artic_head)) {
300  while (BU_LIST_WHILE(gp, artic_grips, &jp->head)) {
301  BU_LIST_DEQUEUE(&gp->l);
302  bu_free((void *)gp, "artic_grip");
303  }
304  BU_LIST_DEQUEUE(&jp->l);
305  bu_free((void *)jp, "Artic Joint");
306  }
307  return GED_OK;
308 }
309 
310 
311 static int
312 joint_debug(struct ged *gedp,
313  int argc,
314  const char *argv[])
315 {
316  if (argc >= 2) {
317  sscanf(argv[1], "%x", &J_DEBUG);
318  } else {
319  bu_vls_printb(gedp->ged_result_str, "possible flags", 0xffffffffL, J_DEBUG_FORMAT);
320  bu_vls_printf(gedp->ged_result_str, "\n");
321  }
322  bu_vls_printb(gedp->ged_result_str, "J_DEBUG", J_DEBUG, J_DEBUG_FORMAT);
323  bu_vls_printf(gedp->ged_result_str, "\n");
324 
325  return GED_OK;
326 }
327 
328 
329 /**
330  * Common code for help commands
331  */
332 HIDDEN int
333 helpcomm(struct ged *gedp, int argc, const char *argv[], struct funtab *functions)
334 {
335  struct funtab *ftp;
336  int i, bad;
337 
338  bad = 0;
339 
340  /* Help command(s) */
341  for (i=1; i<argc; i++) {
342  for (ftp = functions+1; ftp->ft_name; ftp++) {
343  if (!BU_STR_EQUAL(ftp->ft_name, argv[i]))
344  continue;
345 
346  bu_vls_printf(gedp->ged_result_str, "Usage: %s%s %s\n\t(%s)\n", functions->ft_name, ftp->ft_name, ftp->ft_parms, ftp->ft_comment);
347  break;
348  }
349  if (!ftp->ft_name) {
350  bu_vls_printf(gedp->ged_result_str, "%s%s : no such command, type '%s?' for help\n", functions->ft_name, argv[i], functions->ft_name);
351  bad = 1;
352  }
353  }
354 
355  return bad ? GED_ERROR : GED_OK;
356 }
357 
358 
359 /**
360  * Print a help message, two lines for each command. Or, help with
361  * the indicated commands.
362  */
363 static int
364 joint_usage(struct ged *gedp, int argc, const char *argv[], struct funtab *functions)
365 {
366  struct funtab *ftp;
367 
368  if (argc <= 1) {
369  bu_vls_printf(gedp->ged_result_str, "The following commands are available:\n");
370  for (ftp = functions+1; ftp->ft_name; ftp++) {
371  bu_vls_printf(gedp->ged_result_str, "%s%s %s\n\t (%s)\n", functions->ft_name, ftp->ft_name, ftp->ft_parms, ftp->ft_comment);
372  }
373  return GED_OK;
374  }
375  return helpcomm(gedp, argc, argv, functions);
376 }
377 
378 
379 static int
380 joint_command_tab(struct ged *gedp, int argc, const char *argv[], struct funtab *functions)
381 {
382  struct funtab *ftp;
383 
384  if (argc <= 1) {
385  bu_vls_printf(gedp->ged_result_str, "The following %s subcommands are available:\n", functions->ft_name);
386  for (ftp = functions+1; ftp->ft_name; ftp++) {
387  vls_col_item(gedp->ged_result_str, ftp->ft_name);
388  }
390  bu_vls_printf(gedp->ged_result_str, "\n");
391  return GED_OK;
392  }
393  return helpcomm(gedp, argc, argv, functions);
394 }
395 
396 
397 static int
398 joint_help_commands(struct ged *gedp, int argc, const char *argv[])
399 {
400  int status;
401 
402  status = joint_command_tab(gedp, argc, argv, &joint_tab[0]);
403 
404  if (status == GED_OK)
405  return GED_OK;
406  else
407  return GED_ERROR;
408 }
409 
410 
411 static int
412 joint_help(struct ged *gedp, int argc, const char *argv[])
413 {
414  int status;
415 
416  status = joint_usage(gedp, argc, argv, &joint_tab[0]);
417 
418  if (status == GED_OK)
419  return GED_OK;
420  else
421  return GED_ERROR;
422 }
423 
424 
425 static struct joint *
426 joint_lookup(const char *name)
427 {
428  struct joint *jp;
429 
430  for (BU_LIST_FOR(jp, joint, &joint_head)) {
431  if (BU_STR_EQUAL(jp->name, name)) {
432  return jp;
433  }
434  }
435  return (struct joint *) 0;
436 }
437 
438 
439 static void
440 free_arc(struct arc *ap)
441 {
442  int i;
443 
444  if (!ap || ap->type == ARC_UNSET)
445  return;
446  for (i=0; i<=ap->arc_last; i++) {
447  bu_free((void *)ap->arc[i], "arc entry");
448  }
449  bu_free((void *)ap->arc, "arc table");
450  ap->arc = (char **)0;
451  if (ap->type & ARC_BOTH) {
452  for (i=0; i<=ap->arc_last; i++) {
453  bu_free((void *)ap->original[i], "arc entry");
454  }
455  bu_free((void *)ap->original, "arc table");
456  }
457  ap->type=ARC_UNSET;
458 }
459 
460 
461 static void
462 free_joint(struct joint *jp)
463 {
464  free_arc(&jp->path);
465  if (jp->name)
466  bu_free((void *)jp->name, "joint name");
467  BU_PUT(jp, struct joint);
468 }
469 
470 
471 static void
472 free_hold(struct hold *hp)
473 {
474  struct jointH *jh;
475 
476  if (!hp || hp->l.magic != MAGIC_HOLD_STRUCT)
477  return;
478  if (hp->objective.type != ID_FIXED) {
479  if (hp->objective.path.fp_len) {
481  }
482  free_arc(&hp->objective.arc);
483  }
484  if (hp->effector.type != ID_FIXED) {
485  if (hp->effector.path.fp_len) {
487  }
488  free_arc(&hp->effector.arc);
489  }
490  while (BU_LIST_WHILE(jh, jointH, &hp->j_head)) {
491  jh->p->uses--;
492  BU_LIST_DEQUEUE(&jh->l);
493  BU_PUT(jh, struct jointH);
494  }
495  if (hp->joint)
496  bu_free((void *)hp->joint, "hold joint name");
497  if (hp->name)
498  bu_free((void *)hp->name, "hold name");
499  BU_PUT(hp, struct hold);
500 }
501 
502 
503 static int
504 hold_point_location(struct ged *gedp, fastf_t *loc, struct hold_point *hp)
505 {
506  mat_t mat;
507  struct joint *jp;
508  struct rt_grip_internal *gip;
509  struct rt_db_internal intern;
510 
511  if (gedp->ged_wdbp->dbip == DBI_NULL)
512  return 1;
513 
514  /* default is the origin. */
515  VSETALL(loc, 0.0);
516 
517  switch (hp->type) {
518  case ID_FIXED:
519  VMOVE(loc, hp->point);
520  return 1;
521  case ID_GRIP:
522  if (hp->flag & HOLD_PT_GOOD) {
523  db_path_to_mat(gedp->ged_wdbp->dbip, &hp->path, mat, hp->path.fp_len-2, &rt_uniresource);
524  MAT4X3PNT(loc, mat, hp->point);
525  return 1;
526  }
527  if (!hp->path.fp_names) {
528  bu_vls_printf(gedp->ged_result_str, "hold_point_location: null pointer! '%s' not found!\n", "hp->path.fp_names");
529  bu_bomb("this shouldn't happen\n");
530  }
531  if (rt_db_get_internal(&intern, hp->path.fp_names[hp->path.fp_len-1], gedp->ged_wdbp->dbip, NULL, &rt_uniresource) < 0)
532  return 0;
533 
534  RT_CK_DB_INTERNAL(&intern);
535  if (intern.idb_type != ID_GRIP)
536  return 0;
537  gip = (struct rt_grip_internal *)intern.idb_ptr;
538  VMOVE(hp->point, gip->center);
539  hp->flag |= HOLD_PT_GOOD;
540  rt_db_free_internal(&intern);
541 
542  db_path_to_mat(gedp->ged_wdbp->dbip, &hp->path, mat, hp->path.fp_len-2, &rt_uniresource);
543  MAT4X3PNT(loc, mat, hp->point);
544  return 1;
545  case ID_JOINT:
546  db_path_to_mat(gedp->ged_wdbp->dbip, &hp->path, mat, hp->path.fp_len-3, &rt_uniresource);
547  if (hp->flag & HOLD_PT_GOOD) {
548  MAT4X3VEC(loc, mat, hp->point);
549  return 1;
550  }
551  jp = joint_lookup(hp->arc.arc[hp->arc.arc_last]);
552  if (!jp) {
553  bu_vls_printf(gedp->ged_result_str, "hold_point_location: Lost joint! %s not found!\n",
554  hp->arc.arc[hp->arc.arc_last]);
555  return 0;
556  }
557  VMOVE(hp->point, jp->location);
558  hp->flag |= HOLD_PT_GOOD;
559  MAT4X3VEC(loc, mat, hp->point);
560  return 1;
561  }
562  /* NEVER REACHED */
563  return 1; /* For the picky compilers */
564 }
565 
566 
567 static char *
568 hold_point_to_string(struct ged *gedp, struct hold_point *hp)
569 {
570 #define HOLD_POINT_TO_STRING_LEN 1024
571  char *text = (char *)bu_malloc(HOLD_POINT_TO_STRING_LEN, "hold_point_to_string");
572  char *path;
573  vect_t loc = VINIT_ZERO;
574 
575  switch (hp->type) {
576  case ID_FIXED:
577  sprintf(text, "(%g %g %g)", hp->point[X],
578  hp->point[Y], hp->point[Z]);
579  break;
580  case ID_GRIP:
581  case ID_JOINT:
582  (void)hold_point_location(gedp, loc, hp);
583  path = db_path_to_string(&hp->path);
584  snprintf(text, HOLD_POINT_TO_STRING_LEN, "%s (%g %g %g)", path, loc[X], loc[Y], loc[Z]);
585  bu_free(path, "full path");
586  break;
587  }
588  return text;
589 }
590 
591 
592 static double
593 hold_eval(struct ged *gedp, struct hold *hp)
594 {
595  vect_t e_loc = VINIT_ZERO;
596  vect_t o_loc = VINIT_ZERO;
597  double value;
598 
599  /* get the current location of the effector. */
600  if (!hold_point_location(gedp, e_loc, &hp->effector)) {
601  if (J_DEBUG & DEBUG_J_EVAL) {
602  bu_vls_printf(gedp->ged_result_str, "hold_eval: unable to find location of effector for %s.\n",
603  hp->name);
604  }
605  return 0.0;
606  }
607  if (!hold_point_location(gedp, o_loc, &hp->objective)) {
608  if (J_DEBUG & DEBUG_J_EVAL) {
609  bu_vls_printf(gedp->ged_result_str, "hold_eval: unable to find location of objective for %s.\n",
610  hp->name);
611  }
612  return 0.0;
613  }
614  value = hp->weight * DIST_PT_PT(e_loc, o_loc);
615  if (J_DEBUG & DEBUG_J_EVAL) {
616  bu_vls_printf(gedp->ged_result_str, "hold_eval: PT->PT of %s is %g\n", hp->name, value);
617  }
618  return value;
619 }
620 
621 
622 static void
623 print_hold(struct ged *gedp, struct hold *hp)
624 {
625  char *t1, *t2;
626 
627  t1 = hold_point_to_string(gedp, &hp->effector);
628  t2 = hold_point_to_string(gedp, &hp->objective);
629 
630  bu_vls_printf(gedp->ged_result_str, "holds:\t%s with %s\n\tfrom:%s\n\tto:%s\n", (hp->name) ? hp->name : "UNNAMED", hp->joint, t1, t2);
631  bu_free(t1, "hold_point_to_string");
632  bu_free(t2, "hold_point_to_string");
633 
634  {
635  bu_vls_printf(gedp->ged_result_str, "\n\twith a weight: %g, pull %g\n",
636  hp->weight, hold_eval(gedp, hp));
637  }
638 }
639 
640 
641 static void
642 hold_clear_flags(struct hold *hp)
643 {
644  hp->effector.flag = hp->objective.flag = 0;
645 }
646 
647 
648 static int
649 joint_unload(struct ged *gedp, int argc, const char *argv[])
650 {
651  struct joint *jp;
652  struct hold *hp;
653  int joints, holds;
654 
655  if (gedp->ged_wdbp->dbip == DBI_NULL) {
656  bu_vls_printf(gedp->ged_result_str, "A database is not open!\n");
657  return GED_ERROR;
658  }
659 
660  if (argc > 1) {
661  bu_vls_printf(gedp->ged_result_str, "Unexpected parameter [%s]\n", argv[1]);
662  }
663 
664  db_free_anim(gedp->ged_wdbp->dbip);
665  holds = 0;
666  while (BU_LIST_WHILE(hp, hold, &hold_head)) {
667  holds++;
668  BU_LIST_DEQUEUE(&hp->l);
669  if (J_DEBUG & DEBUG_J_LOAD) {
670  bu_vls_printf(gedp->ged_result_str, "joint: unloading '%s' constraint\n", hp->name);
671  bu_vls_printf(gedp->ged_result_str, "===begin %s===\n", hp->name);
672  print_hold(gedp, hp);
673  bu_vls_printf(gedp->ged_result_str, "===end %s===\n", hp->name);
674  }
675  free_hold(hp);
676  }
677  joints = 0;
678  while (BU_LIST_WHILE(jp, joint, &joint_head)) {
679  joints++;
680  BU_LIST_DEQUEUE(&(jp->l));
681  if (J_DEBUG & DEBUG_J_LOAD) {
682  bu_vls_printf(gedp->ged_result_str, "joint: unloading '%s' joint\n", jp->name);
683  }
684  free_joint(jp);
685  }
686  if (J_DEBUG & DEBUG_J_LOAD) {
687  bu_vls_printf(gedp->ged_result_str, "joint: unloaded %d joints, %d constraints.\n",
688  joints, holds);
689  }
690 
691  return GED_OK;
692 }
693 
694 
695 #define KEY_JOINT 1
696 #define KEY_CON 2
697 #define KEY_ARC 3
698 #define KEY_LOC 4
699 #define KEY_TRANS 5
700 #define KEY_ROT 6
701 #define KEY_LIMIT 7
702 #define KEY_UP 8
703 #define KEY_LOW 9
704 #define KEY_CUR 10
705 #define KEY_ACC 11
706 #define KEY_DIR 12
707 #define KEY_UNITS 13
708 #define KEY_JOINTS 14
709 #define KEY_START 15
710 #define KEY_PATH 16
711 #define KEY_WEIGHT 17
712 #define KEY_PRI 18
713 #define KEY_EFF 19
714 #define KEY_POINT 20
715 #define KEY_EXCEPT 21
716 #define KEY_INF 22
717 #define KEY_VERTEX 23
718 
719 static struct bu_lex_key animkeys[] = {
720  {KEY_JOINT, "joint"},
721  {KEY_CON, "constraint"},
722  {KEY_ARC, "arc"},
723  {KEY_LOC, "location"},
724  {KEY_TRANS, "translate"},
725  {KEY_ROT, "rotate"},
726  {KEY_LIMIT, "limits"},
727  {KEY_UP, "upper"},
728  {KEY_LOW, "lower"},
729  {KEY_CUR, "current"},
730  {KEY_ACC, "accepted"},
731  {KEY_DIR, "direction"},
732  {KEY_UNITS, "units"},
733  {KEY_JOINTS, "joints"},
734  {KEY_START, "start"},
735  {KEY_PATH, "path"},
736  {KEY_WEIGHT, "weight"},
737  {KEY_PRI, "priority"},
738  {KEY_EFF, "effector"},
739  {KEY_POINT, "point"},
740  {KEY_EXCEPT, "except"},
741  {KEY_INF, "INF"},
742  {KEY_VERTEX, "vertex"},
743  {0, 0}};
744 
745 #define UNIT_INCH 1
746 #define UNIT_METER 2
747 #define UNIT_FEET 3
748 #define UNIT_CM 4
749 #define UNIT_MM 5
750 
751 static struct bu_lex_key units[] = {
752  {UNIT_INCH, "inches"},
753  {UNIT_INCH, "in"},
754  {UNIT_METER, "m"},
755  {UNIT_METER, "meters"},
756  {UNIT_FEET, "ft"},
757  {UNIT_FEET, "feet"},
758  {UNIT_CM, "cm"},
759  {UNIT_MM, "mm"},
760  {0, 0}};
761 
762 #define ID_FIXED -1
763 static struct bu_lex_key lex_solids[] = {
764  {ID_FIXED, "fixed"},
765  {ID_GRIP, "grip"},
766  {ID_SPH, "sphere"},
767  {ID_JOINT, "joint"},
768  {0, 0}};
769 
770 #define SYM_OP_GROUP 1
771 #define SYM_CL_GROUP 2
772 #define SYM_OP_PT 3
773 #define SYM_CL_PT 4
774 #define SYM_EQ 5
775 #define SYM_ARC 6
776 #define SYM_END 7
777 #define SYM_COMMA 8
778 #define SYM_MINUS 9
779 #define SYM_PLUS 10
780 
781 static struct bu_lex_key animsyms[] = {
782  {SYM_OP_GROUP, "{"},
783  {SYM_CL_GROUP, "}"},
784  {SYM_OP_PT, "("},
785  {SYM_CL_PT, ")"},
786  {SYM_EQ, "="},
787  {SYM_ARC, "/"},
788  {SYM_END, ";"},
789  {SYM_COMMA, ", "},
790  {SYM_MINUS, "-"},
791  {SYM_PLUS, "+"},
792  {0, 0}};
793 
794 static int lex_line;
795 static const char *lex_name;
796 static double mm2base, base2mm;
797 
798 static void
799 parse_error(struct ged *gedp, struct bu_vls *vlsp, char *error)
800 {
801  char *text;
802  size_t i;
803  size_t len;
804  const char *str = bu_vls_addr(vlsp);
805 
806  len = bu_vls_strlen(vlsp);
807  if (!len) {
808  bu_vls_printf(gedp->ged_result_str, "%s:%d %s\n", lex_name, lex_line, error);
809  return;
810  }
811  text = (char *)bu_malloc(len+2, "error pointer");
812  for (i=0; i<len; i++) {
813  text[i]=(str[i] == '\t')? '\t' : '-';
814  }
815  text[len] = '^';
816  text[len+1] = '\0';
817 
818  {
819  bu_vls_printf(gedp->ged_result_str, "%s:%d %s\n%s\n%s\n", lex_name, lex_line, error, str, text);
820  }
821 
822  bu_free(text, "error pointer");
823 }
824 
825 
826 int
827 get_token(struct ged *gedp, union bu_lex_token *token, FILE *fip, struct bu_vls *str, struct bu_lex_key *keys, struct bu_lex_key *syms)
828 {
829  int used;
830  for (;;) {
831  used = bu_lex(token, str, keys, syms);
832  if (used)
833  break;
834  bu_vls_free(str);
835  lex_line++;
836  used = bu_vls_gets(str, fip);
837  if (used == EOF)
838  return used;
839  }
840 
841  bu_vls_nibble(str, used);
842 
843  {
844  if (J_DEBUG & DEBUG_J_LEX) {
845  int i;
846  switch (token->type) {
847  case BU_LEX_KEYWORD:
848  for (i=0; keys[i].tok_val != token->t_key.value; i++)
849  /* skip */;
850  bu_vls_printf(gedp->ged_result_str, "lex: key(%d)='%s'\n", token->t_key.value,
851  keys[i].string);
852  break;
853  case BU_LEX_SYMBOL:
854  for (i=0; syms[i].tok_val != token->t_key.value; i++)
855  /* skip */;
856  bu_vls_printf(gedp->ged_result_str, "lex: symbol(%d)='%c'\n", token->t_key.value,
857  *(syms[i].string));
858  break;
859  case BU_LEX_DOUBLE:
860  bu_vls_printf(gedp->ged_result_str, "lex: double(%g)\n", token->t_dbl.value);
861  break;
862  case BU_LEX_INT:
863  bu_vls_printf(gedp->ged_result_str, "lex: int(%d)\n", token->t_int.value);
864  break;
865  case BU_LEX_IDENT:
866  bu_vls_printf(gedp->ged_result_str, "lex: id(%s)\n", token->t_id.value);
867  break;
868  }
869  }
870  }
871  return used;
872 }
873 
874 
875 static int
876 gobble_token(struct ged *gedp, int type_wanted, int value_wanted, FILE *fip, struct bu_vls *str)
877 {
878  static char *types[] = {
879  "any",
880  "integer",
881  "double",
882  "symbol",
883  "keyword",
884  "identifier",
885  "number"};
886  union bu_lex_token token;
887  char error[160];
888 
889  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
890  snprintf(error, 160, "parse: Unexpected EOF while getting %s",
891  types[type_wanted]);
892  parse_error(gedp, str, error);
893  return 0;
894  }
895 
896  if (token.type == BU_LEX_IDENT)
897  bu_free(token.t_id.value, "unit token");
898 
899  switch (type_wanted) {
900  case BU_LEX_ANY:
901  return 1;
902  case BU_LEX_INT:
903  return token.type == BU_LEX_INT;
904  case BU_LEX_DOUBLE:
905  return token.type == BU_LEX_DOUBLE;
906  case BU_LEX_NUMBER:
907  return token.type == BU_LEX_INT || token.type == BU_LEX_DOUBLE;
908  case BU_LEX_SYMBOL:
909  return (token.type == BU_LEX_SYMBOL &&
910  value_wanted == token.t_key.value);
911  case BU_LEX_KEYWORD:
912  return (token.type == BU_LEX_KEYWORD &&
913  value_wanted == token.t_key.value);
914  case BU_LEX_IDENT:
915  return token.type == BU_LEX_IDENT;
916  }
917  return 0;
918 }
919 
920 
921 static void
922 skip_group(struct ged *gedp, FILE *fip, struct bu_vls *str)
923 {
924  union bu_lex_token tok;
925  int count = 1;
926 
927  if (J_DEBUG & DEBUG_J_PARSE) {
928  bu_vls_printf(gedp->ged_result_str, "skip_group: Skipping....\n");
929  }
930 
931  while (count) {
932  if (get_token(gedp, &tok, fip, str, animkeys, animsyms) == EOF) {
933  parse_error(gedp, str, "skip_group: Unexpected EOF while searching for group end.");
934  return;
935  }
936  if (tok.type == BU_LEX_IDENT) {
937  bu_free(tok.t_id.value, "unit token");
938  }
939  if (tok.type != BU_LEX_SYMBOL) {
940  continue;
941  }
942  if (tok.t_key.value == SYM_OP_GROUP) {
943  count++;
944  } else if (tok.t_key.value == SYM_CL_GROUP) {
945  count--;
946  }
947  }
948  if (J_DEBUG & DEBUG_J_PARSE) {
949  bu_vls_printf(gedp->ged_result_str, "skip_group: Done....\n");
950  }
951 
952 }
953 
954 
955 static int
956 parse_units(struct ged *gedp, FILE *fip, struct bu_vls *str)
957 {
958  union bu_lex_token token;
959 
960  if (get_token(gedp, &token, fip, str, units, animsyms) == EOF) {
961  parse_error(gedp, str, "parse_units: Unexpected EOF reading units.");
962  return 0;
963  }
964  if (token.type == BU_LEX_IDENT)
965  bu_free(token.t_id.value, "unit token");
966  if (token.type != BU_LEX_KEYWORD) {
967  parse_error(gedp, str, "parse_units: syntax error getting unit type.");
968  return 0;
969  }
970 
971  switch (token.t_key.value) {
972  case UNIT_INCH:
973  base2mm = 25.4; break;
974  case UNIT_METER:
975  base2mm = 1000.0; break;
976  case UNIT_FEET:
977  base2mm = 304.8; break;
978  case UNIT_CM:
979  base2mm = 10.0; break;
980  case UNIT_MM:
981  base2mm = 1; break;
982  }
983  mm2base = 1.0 / base2mm;
984  (void) gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str);
985  return 1;
986 }
987 
988 
989 static int
990 parse_path(struct ged *gedp, struct arc *ap, FILE *fip, struct bu_vls *str)
991 {
992  union bu_lex_token token;
993  int max;
994 
995  if (J_DEBUG & DEBUG_J_PARSE) {
996  bu_vls_printf(gedp->ged_result_str, "parse_path: open.\n");
997  }
998 
999  /* clear the arc if there is anything there. */
1000  free_arc(ap);
1001  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str))
1002  return 0;
1003 
1004  max = MAX_OBJ_NAME;
1005  ap->arc = (char **)bu_malloc(sizeof(char *)*max, "arc table");
1006  ap->arc_last = -1;
1007  ap->type = ARC_PATH;
1008  for (;;) {
1009  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
1010  parse_error(gedp, str, "parse_path: Unexpected EOF.");
1011  free_arc(ap);
1012  return 0;
1013  }
1014  if (token.type != BU_LEX_IDENT) {
1015  parse_error(gedp, str, "parse_path: syntax error. Missing identifier.");
1016  free_arc(ap);
1017  return 0;
1018  }
1019  if (++ap->arc_last >= max) {
1020  max += MAX_OBJ_NAME + 1;
1021  ap->arc = (char **) bu_realloc((char *) ap->arc, sizeof(char *)*max, "arc table");
1022  }
1023  ap->arc[ap->arc_last] = token.t_id.value;
1024  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
1025  parse_error(gedp, str, "parse_path: Unexpected EOF while getting '/' or '-'");
1026  free_arc(ap);
1027  return 0;
1028  }
1029  if (token.type == BU_LEX_IDENT)
1030  bu_free(token.t_id.value, "unit token");
1031  if (token.type != BU_LEX_SYMBOL) {
1032  parse_error(gedp, str, "parse_path: syntax error.");
1033  free_arc(ap);
1034  return 0;
1035  }
1036  if (token.t_key.value == SYM_ARC) {
1037  continue;
1038  } else if (token.t_key.value == SYM_MINUS) {
1039  break;
1040  } else {
1041  parse_error(gedp, str, "parse_path: syntax error.");
1042  free_arc(ap);
1043  return 0;
1044  }
1045  }
1046 
1047  /* Just got the '-' so this is the "destination" part. */
1048  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
1049  parse_error(gedp, str, "parse_path: Unexpected EOF while getting destination.");
1050  free_arc(ap);
1051  return 0;
1052  }
1053  if (token.type != BU_LEX_IDENT) {
1054  parse_error(gedp, str, "parse_path: syntax error, expecting destination.");
1055  free_arc(ap);
1056  return 0;
1057  }
1058  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str)) {
1059  free_arc(ap);
1060  return 0;
1061  }
1062  return 1;
1063 }
1064 
1065 
1066 static int
1067 parse_list(struct ged *gedp, struct arc *ap, FILE *fip, struct bu_vls *str)
1068 {
1069  union bu_lex_token token;
1070  int max;
1071 
1072  if (J_DEBUG & DEBUG_J_PARSE) {
1073  bu_vls_printf(gedp->ged_result_str, "parse_path: open.\n");
1074  }
1075 
1076  /* clear the arc if there is anything there. */
1077  free_arc(ap);
1078 
1079  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str))
1080  return 0;
1081  max = MAX_OBJ_NAME;
1082  ap->arc = (char **)bu_malloc(sizeof(char *)*max, "arc table");
1083  ap->arc_last = -1;
1084  ap->type = ARC_LIST;
1085  for (;;) {
1086  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
1087  parse_error(gedp, str, "parse_path: Unexpected EOF.");
1088  free_arc(ap);
1089  return 0;
1090  }
1091  if (token.type != BU_LEX_IDENT) {
1092  parse_error(gedp, str, "parse_path: syntax error. Missing identifier.");
1093  free_arc(ap);
1094  return 0;
1095  }
1096  if (++ap->arc_last >= max) {
1097  max += MAX_OBJ_NAME + 1;
1098  ap->arc = (char **) bu_realloc((char *) ap->arc, sizeof(char *)*max, "arc table");
1099  }
1100  ap->arc[ap->arc_last] = token.t_id.value;
1101  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
1102  parse_error(gedp, str, "parse_path: Unexpected EOF while getting ', ' or ';'");
1103  free_arc(ap);
1104  return 0;
1105  }
1106  if (token.type == BU_LEX_IDENT)
1107  bu_free(token.t_id.value, "unit token");
1108  if (token.type != BU_LEX_SYMBOL) {
1109  parse_error(gedp, str, "parse_path: syntax error.");
1110  free_arc(ap);
1111  return 0;
1112  }
1113  if (token.t_key.value == SYM_COMMA) {
1114  continue;
1115  } else if (token.t_key.value == SYM_END) {
1116  break;
1117  } else {
1118  parse_error(gedp, str, "parse_path: syntax error.");
1119  free_arc(ap);
1120  return 0;
1121  }
1122  }
1123  return 1;
1124 }
1125 
1126 
1127 static int
1128 parse_ARC(struct ged *gedp, struct arc *ap, FILE *fip, struct bu_vls *str)
1129 {
1130  union bu_lex_token token;
1131  int max;
1132  char *error;
1133 
1134  if (J_DEBUG & DEBUG_J_PARSE) {
1135  bu_vls_printf(gedp->ged_result_str, "parse_ARC: open.\n");
1136  }
1137 
1138  free_arc(ap);
1139  max = MAX_OBJ_NAME;
1140  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str))
1141  return 0;
1142 
1143  ap->arc = (char **) bu_malloc(sizeof(char *)*max, "arc table");
1144  ap->arc_last = -1;
1145 
1146  error = "parse_ARC: Unexpected EOF while getting arc.";
1147  while (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) != EOF) {
1148  if (token.type != BU_LEX_IDENT) {
1149  error = "parse_ARC: syntax error. Missing identifier.";
1150  break;
1151  }
1152  if (++ap->arc_last >= max) {
1153  max += MAX_OBJ_NAME + 1;
1154  ap->arc = (char **) bu_realloc((char *)ap->arc, sizeof(char *)*max, "arc table");
1155  }
1156  ap->arc[ap->arc_last] = token.t_id.value;
1157  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
1158  error = "parse_ARC: Unexpected EOF while getting '/' or ';'.";
1159  break;
1160  }
1161  if (token.type != BU_LEX_SYMBOL) {
1162  if (token.type == BU_LEX_IDENT) {
1163  bu_free(token.t_id.value, "unit token");
1164  }
1165  error = "parse_ARC: syntax error. Expected '/' or ';'";
1166  break;
1167  }
1168  if (token.t_key.value == SYM_END) {
1169  if (J_DEBUG & DEBUG_J_PARSE) {
1170  bu_vls_printf(gedp->ged_result_str, "parse_ARC: close.\n");
1171  }
1172 
1173  return 1;
1174  }
1175  if (token.t_key.value != SYM_ARC) {
1176  error = "parse_ARC: Syntax error. Expecting ';' or '/'";
1177  break;
1178  }
1179  error = "parse_ARC: Unexpected EOF while getting arc.";
1180  }
1181  parse_error(gedp, str, error);
1182  free_arc(ap);
1183  return 0;
1184 }
1185 
1186 
1187 static int
1188 parse_double(struct ged *gedp, double *dbl, FILE *fip, struct bu_vls *str)
1189 {
1190  union bu_lex_token token;
1191  double sign;
1192  sign = 1.0;
1193 
1194  if (J_DEBUG & DEBUG_J_PARSE) {
1195  bu_vls_printf(gedp->ged_result_str, "parse_double: open\n");
1196  }
1197 
1198  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
1199  parse_error(gedp, str, "parse_double: Unexpected EOF while getting number.");
1200  return 0;
1201  }
1202  if (token.type == BU_LEX_SYMBOL && token.t_key.value == SYM_MINUS) {
1203  sign = -1;
1204  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
1205  parse_error(gedp, str, "parse_double: Unexpected EOF while getting number.");
1206  return 0;
1207  }
1208  }
1209  if (token.type == BU_LEX_IDENT)
1210  bu_free(token.t_id.value, "unit token");
1211 
1212  if (token.type == BU_LEX_INT) {
1213  *dbl = token.t_int.value * sign;
1214  } else if (token.type == BU_LEX_DOUBLE) {
1215  *dbl = token.t_dbl.value * sign;
1216  } else if (token.type == BU_LEX_KEYWORD && token.t_key.value == KEY_INF) {
1217  *dbl = MAX_FASTF * sign;
1218  } else {
1219  parse_error(gedp, str, "parse_double: syntax error. Expecting number.");
1220  return 0;
1221  }
1222 
1223  if (J_DEBUG & DEBUG_J_PARSE)
1224  bu_vls_printf(gedp->ged_result_str, "parse_double: %lf\n", *dbl);
1225 
1226  return 1;
1227 }
1228 
1229 
1230 static int
1231 parse_assign(struct ged *gedp, double *dbl, FILE *fip, struct bu_vls *str)
1232 {
1233  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
1234  skip_group(gedp, fip, str);
1235  return 0;
1236  }
1237  if (!parse_double(gedp, dbl, fip, str)) {
1238  skip_group(gedp, fip, str);
1239  return 0;
1240  }
1241  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str)) {
1242  skip_group(gedp, fip, str);
1243  return 0;
1244  }
1245  return 1;
1246 }
1247 
1248 
1249 static int
1250 parse_vect(struct ged *gedp, fastf_t *vect, FILE *fip, struct bu_vls *str)
1251 {
1252  int i;
1253  double scan[3];
1254 
1255  if (J_DEBUG & DEBUG_J_PARSE) {
1256  bu_vls_printf(gedp->ged_result_str, "parse_vect: open.\n");
1257  }
1258 
1259  /* convert to double for parsing */
1260  VMOVE(scan, vect);
1261 
1262  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_PT, fip, str)) {
1263  return 0;
1264  }
1265 
1266  for (i=0; i < 3; i++) {
1267  if (!parse_double(gedp, &scan[i], fip, str)) {
1268  return 0;
1269  }
1270  if (i < 2) {
1271  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_COMMA, fip, str)) {
1272  return 0;
1273  }
1274  } else {
1275  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_CL_PT, fip, str)) {
1276  return 0;
1277  }
1278  }
1279  }
1280 
1281  /* convert from double back to fastf_t for return */
1282  VMOVE(vect, scan);
1283 
1284  return 1;
1285 }
1286 
1287 
1288 static int
1289 parse_trans(struct ged *gedp, struct joint *jp, int idx, FILE *fip, struct bu_vls *str)
1290 {
1291  union bu_lex_token token;
1292  int dirfound, upfound, lowfound, curfound;
1293 
1294  if (J_DEBUG & DEBUG_J_PARSE) {
1295  bu_vls_printf(gedp->ged_result_str, "parse_trans: open\n");
1296  }
1297 
1298  if (idx >= 3) {
1299  parse_error(gedp, str, "parse_trans: Too many translations for this joint.");
1300  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_GROUP, fip, str))
1301  return 0;
1302  skip_group(gedp, fip, str);
1303  return 0;
1304  }
1305  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_GROUP, fip, str))
1306  return 0;
1307 
1308  dirfound = upfound = lowfound = curfound = 0;
1309  while (get_token(gedp, &token, fip, str, animkeys, animsyms) != EOF) {
1310  if (token.type == BU_LEX_IDENT) {
1311  bu_free(token.t_id.value, "unit token");
1312  }
1313  if (token.type == BU_LEX_SYMBOL && token.t_key.value == SYM_CL_GROUP) {
1314  if (J_DEBUG & DEBUG_J_PARSE) {
1315  bu_vls_printf(gedp->ged_result_str, "parse_trans: closing.\n");
1316  }
1317 
1318  if (!dirfound) {
1319  parse_error(gedp, str, "parse_trans: Direction vector not given.");
1320  return 0;
1321  }
1322  VUNITIZE(jp->dirs[idx].unitvec);
1323  if (!lowfound) {
1324  parse_error(gedp, str, "parse_trans: lower bound not given.");
1325  return 0;
1326  }
1327  if (!upfound) {
1328  parse_error(gedp, str, "parse_trans: upper bound not given.");
1329  return 0;
1330  }
1331  if (jp->dirs[idx].lower > jp->dirs[idx].upper) {
1332  double tmp;
1333  tmp = jp->dirs[idx].lower;
1334  jp->dirs[idx].lower = jp->dirs[idx].upper;
1335  jp->dirs[idx].upper = tmp;
1336  parse_error(gedp, str, "parse_trans: lower > upper, exchanging.");
1337  }
1338  jp->dirs[idx].accepted = 0.0;
1339  if (!curfound)
1340  jp->dirs[idx].current = 0.0;
1341  jp->dirs[idx].lower *= base2mm;
1342  jp->dirs[idx].upper *= base2mm;
1343  jp->dirs[idx].current *= base2mm;
1344  jp->dirs[idx].accepted *= base2mm;
1345 
1346  if (jp->dirs[idx].accepted < jp->dirs[idx].lower) {
1347  jp->dirs[idx].accepted = jp->dirs[idx].lower;
1348  }
1349  if (jp->dirs[idx].accepted > jp->dirs[idx].upper) {
1350  jp->dirs[idx].accepted = jp->dirs[idx].upper;
1351  }
1352  if (jp->dirs[idx].current < jp->dirs[idx].lower) {
1353  jp->dirs[idx].current = jp->dirs[idx].lower;
1354  }
1355  if (jp->dirs[idx].current > jp->dirs[idx].upper) {
1356  jp->dirs[idx].current = jp->dirs[idx].upper;
1357  }
1358  return 1;
1359  }
1360 
1361  if (token.type != BU_LEX_KEYWORD) {
1362  parse_error(gedp, str, "parse_trans: Syntax error.");
1363  skip_group(gedp, fip, str);
1364  return 0;
1365  }
1366  switch (token.t_key.value) {
1367  case KEY_LIMIT:
1368  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
1369  skip_group(gedp, fip, str);
1370  return 0;
1371  }
1372  if (!parse_double(gedp, &jp->dirs[idx].lower, fip, str)) {
1373  skip_group(gedp, fip, str);
1374  return 0;
1375  }
1376  lowfound = 1;
1377  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_COMMA, fip, str)) {
1378  skip_group(gedp, fip, str);
1379  return 0;
1380  }
1381  if (!parse_double(gedp, &jp->dirs[idx].upper, fip, str)) {
1382  skip_group(gedp, fip, str);
1383  return 0;
1384  }
1385  upfound = 1;
1386  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_COMMA, fip, str)) {
1387  skip_group(gedp, fip, str);
1388  return 0;
1389  }
1390  if (!parse_double(gedp, &jp->dirs[idx].current, fip, str)) {
1391  skip_group(gedp, fip, str);
1392  return 0;
1393  }
1394  curfound = 1;
1395  (void) gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str);
1396  break;
1397  case KEY_UP:
1398  if (!parse_assign(gedp, &jp->dirs[idx].upper, fip, str)) {
1399  skip_group(gedp, fip, str);
1400  return 0;
1401  }
1402  upfound = 1;
1403  break;
1404  case KEY_LOW:
1405  if (!parse_assign(gedp, &jp->dirs[idx].lower, fip, str)) {
1406  skip_group(gedp, fip, str);
1407  return 0;
1408  }
1409  lowfound = 1;
1410  break;
1411  case KEY_CUR:
1412  if (!parse_assign(gedp, &jp->dirs[idx].current, fip, str)) {
1413  skip_group(gedp, fip, str);
1414  return 0;
1415  }
1416  curfound = 1;
1417  break;
1418  case KEY_ACC:
1419  if (!parse_assign(gedp, &jp->dirs[idx].accepted, fip, str)) {
1420  skip_group(gedp, fip, str);
1421  return 0;
1422  }
1423  curfound = 1;
1424  break;
1425  case KEY_DIR:
1426  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
1427  skip_group(gedp, fip, str);
1428  return 0;
1429  }
1430  if (!parse_vect(gedp, jp->dirs[idx].unitvec, fip, str)) {
1431  skip_group(gedp, fip, str);
1432  return 0;
1433  }
1434  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str)) {
1435  skip_group(gedp, fip, str);
1436  return 0;
1437  }
1438  dirfound = 1;
1439  break;
1440  default:
1441  parse_error(gedp, str, "parse_trans: syntax error.");
1442  skip_group(gedp, fip, str);
1443  return 0;
1444  }
1445  }
1446  parse_error(gedp, str, "parse_trans:Unexpected EOF.");
1447  return 0;
1448 }
1449 
1450 
1451 static int
1452 parse_rots(struct ged *gedp, struct joint *jp, int idx, FILE *fip, struct bu_vls *str)
1453 {
1454  union bu_lex_token token;
1455  int dirfound, upfound, lowfound, curfound;
1456 
1457  if (J_DEBUG & DEBUG_J_PARSE) {
1458  bu_vls_printf(gedp->ged_result_str, "parse_rots: open\n");
1459  }
1460 
1461  if (idx >= 3) {
1462  parse_error(gedp, str, "parse_rot: To many rotations for this joint.");
1463  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_GROUP, fip, str))
1464  return 0;
1465  skip_group(gedp, fip, str);
1466  return 0;
1467  }
1468  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_GROUP, fip, str))
1469  return 0;
1470 
1471  dirfound = upfound = lowfound = curfound = 0;
1472  while (get_token(gedp, &token, fip, str, animkeys, animsyms) != EOF) {
1473  if (token.type == BU_LEX_IDENT) {
1474  bu_free(token.t_id.value, "unit token");
1475  }
1476  if (token.type == BU_LEX_SYMBOL && token.t_key.value == SYM_CL_GROUP) {
1477  if (J_DEBUG & DEBUG_J_PARSE) {
1478  bu_vls_printf(gedp->ged_result_str, "parse_rots: closing.\n");
1479  }
1480 
1481  if (!dirfound) {
1482  parse_error(gedp, str, "parse_rots: Direction vector not given.");
1483  return 0;
1484  }
1485  VUNITIZE(jp->rots[idx].quat);
1486  jp->rots[idx].quat[W] = 0.0;
1487  if (!lowfound) {
1488  parse_error(gedp, str, "parse_rots: lower bound not given.");
1489  return 0;
1490  }
1491  if (!upfound) {
1492  parse_error(gedp, str, "parse_rots: upper bound not given.");
1493  return 0;
1494  }
1495  if (jp->rots[idx].lower > jp->rots[idx].upper) {
1496  double tmp;
1497  tmp = jp->rots[idx].lower;
1498  jp->rots[idx].lower = jp->rots[idx].upper;
1499  jp->rots[idx].upper = tmp;
1500  parse_error(gedp, str, "parse_rots: lower > upper, exchanging.");
1501  }
1502 
1503  jp->rots[idx].accepted = 0.0;
1504  if (jp->rots[idx].accepted < jp->rots[idx].lower) {
1505  jp->rots[idx].accepted = jp->rots[idx].lower;
1506  }
1507  if (jp->rots[idx].accepted > jp->rots[idx].upper) {
1508  jp->rots[idx].accepted = jp->rots[idx].upper;
1509  }
1510  if (!curfound) {
1511  jp->rots[idx].current = 0.0;
1512  }
1513  if (jp->rots[idx].current < jp->rots[idx].lower) {
1514  jp->rots[idx].current = jp->rots[idx].lower;
1515  }
1516  if (jp->rots[idx].current > jp->rots[idx].upper) {
1517  jp->rots[idx].current = jp->rots[idx].upper;
1518  }
1519  return 1;
1520  }
1521 
1522  if (token.type != BU_LEX_KEYWORD) {
1523  parse_error(gedp, str, "parse_rots: Syntax error.");
1524  skip_group(gedp, fip, str);
1525  return 0;
1526  }
1527  switch (token.t_key.value) {
1528  case KEY_LIMIT:
1529  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
1530  skip_group(gedp, fip, str);
1531  return 0;
1532  }
1533  if (!parse_double(gedp, &jp->rots[idx].lower, fip, str)) {
1534  skip_group(gedp, fip, str);
1535  return 0;
1536  }
1537  lowfound = 1;
1538  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_COMMA, fip, str)) {
1539  skip_group(gedp, fip, str);
1540  return 0;
1541  }
1542  if (!parse_double(gedp, &jp->rots[idx].upper, fip, str)) {
1543  skip_group(gedp, fip, str);
1544  return 0;
1545  }
1546  upfound = 1;
1547  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_COMMA, fip, str)) {
1548  skip_group(gedp, fip, str);
1549  return 0;
1550  }
1551  if (!parse_double(gedp, &jp->rots[idx].current, fip, str)) {
1552  skip_group(gedp, fip, str);
1553  return 0;
1554  }
1555  curfound = 1;
1556  (void) gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str);
1557  break;
1558  case KEY_UP:
1559  if (!parse_assign(gedp, &jp->rots[idx].upper, fip, str)) {
1560  skip_group(gedp, fip, str);
1561  return 0;
1562  }
1563  upfound = 1;
1564  break;
1565  case KEY_LOW:
1566  if (!parse_assign(gedp, &jp->rots[idx].lower, fip, str)) {
1567  skip_group(gedp, fip, str);
1568  return 0;
1569  }
1570  lowfound = 1;
1571  break;
1572  case KEY_CUR:
1573  if (!parse_assign(gedp, &jp->rots[idx].current, fip, str)) {
1574  skip_group(gedp, fip, str);
1575  return 0;
1576  }
1577  curfound = 1;
1578  break;
1579  case KEY_ACC:
1580  if (!parse_assign(gedp, &jp->rots[idx].accepted, fip, str)) {
1581  skip_group(gedp, fip, str);
1582  return 0;
1583  }
1584  curfound = 1;
1585  break;
1586  case KEY_DIR:
1587  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
1588  skip_group(gedp, fip, str);
1589  return 0;
1590  }
1591  if (!parse_vect(gedp, jp->rots[idx].quat, fip, str)) {
1592  skip_group(gedp, fip, str);
1593  return 0;
1594  }
1595  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str)) {
1596  skip_group(gedp, fip, str);
1597  return 0;
1598  }
1599  dirfound = 1;
1600  break;
1601  default:
1602  parse_error(gedp, str, "parse_rots: syntax error.");
1603  skip_group(gedp, fip, str);
1604  return 0;
1605  }
1606  }
1607  parse_error(gedp, str, "parse_rots:Unexpected EOF.");
1608  return 0;
1609 }
1610 
1611 
1612 static int
1613 parse_joint(struct ged *gedp, FILE *fip, struct bu_vls *str)
1614 {
1615  union bu_lex_token token;
1616  struct joint *jp;
1617  int trans;
1618  int rots;
1619  int arcfound, locfound;
1620 
1621  if (J_DEBUG & DEBUG_J_PARSE) {
1622  bu_vls_printf(gedp->ged_result_str, "parse_joint: reading joint.\n");
1623  }
1624 
1625  BU_GET(jp, struct joint);
1626  jp->l.magic = MAGIC_JOINT_STRUCT;
1627  jp->anim = (struct animate *) 0;
1628  jp->path.type = ARC_UNSET;
1629  jp->name = NULL;
1630 
1631  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
1632  parse_error(gedp, str, "parse_joint: Unexpected EOF getting name.");
1633  free_joint(jp);
1634  return 0;
1635  }
1636  jp->name = token.t_id.value; /* Name */
1637  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_GROUP, fip, str)) {
1638  free_joint(jp);
1639  return 0;
1640  }
1641 
1642  /* With in the group, we need at least one rotate or translate, a
1643  * location and an arc or path.
1644  */
1645  arcfound = 0;
1646  locfound = 0;
1647  rots = trans = 0;
1648  for (;;) {
1649  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
1650  parse_error(gedp, str, "parse_joint: Unexpected EOF getting joint contents.");
1651  skip_group(gedp, fip, str);
1652  free_joint(jp);
1653  return 0;
1654  }
1655  if (token.type == BU_LEX_SYMBOL && token.t_key.value == SYM_CL_GROUP) {
1656  if (J_DEBUG & DEBUG_J_PARSE) {
1657  bu_vls_printf(gedp->ged_result_str, "parse_joint: closing.\n");
1658  }
1659  if (!arcfound) {
1660  parse_error(gedp, str, "parse_joint: Arc not defined.");
1661  free_joint(jp);
1662  return 0;
1663  }
1664  if (!locfound) {
1665  parse_error(gedp, str, "parse_joint: location not defined.");
1666  free_joint(jp);
1667  return 0;
1668  }
1669  if (trans + rots == 0) {
1670  parse_error(gedp, str, "parse_joint: no translations or rotations defined.");
1671  free_joint(jp);
1672  return 0;
1673  }
1674  for (;trans<3;trans++) {
1675  jp->dirs[trans].lower = -1.0;
1676  jp->dirs[trans].upper = -2.0;
1677  jp->dirs[trans].current = 0.0;
1678  }
1679  for (;rots<3;rots++) {
1680  jp->rots[rots].lower = -1.0;
1681  jp->rots[rots].upper = -2.0;
1682  jp->rots[rots].current = 0.0;
1683  }
1684  jp->location[X] *= base2mm;
1685  jp->location[Y] *= base2mm;
1686  jp->location[Z] *= base2mm;
1687 
1688  BU_LIST_INSERT(&joint_head, &(jp->l));
1689  gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str);
1690  return 1;
1691  }
1692  if (token.type == BU_LEX_IDENT)
1693  bu_free(token.t_id.value, "unit token");
1694 
1695  if (token.type != BU_LEX_KEYWORD) {
1696  parse_error(gedp, str, "parse_joint: syntax error.");
1697  skip_group(gedp, fip, str);
1698  free_joint(jp);
1699  return 0;
1700  }
1701  switch (token.t_key.value) {
1702  case KEY_ARC:
1703  if (arcfound) {
1704  parse_error(gedp, str, "parse_joint: more than one arc or path given");
1705  }
1706  if (!parse_ARC(gedp, &jp->path, fip, str)) {
1707  skip_group(gedp, fip, str);
1708  free_joint(jp);
1709  return 0;
1710  }
1711  arcfound = 1;
1712  break;
1713  case KEY_PATH:
1714  if (arcfound) {
1715  parse_error(gedp, str, "parse_joint: more than one arc or path given.");
1716  }
1717  if (!parse_path(gedp, &jp->path, fip, str)) {
1718  skip_group(gedp, fip, str);
1719  free_joint(jp);
1720  return 0;
1721  }
1722  arcfound = 1;
1723  break;
1724  case KEY_LOC:
1725  if (locfound) {
1726  parse_error(gedp, str, "parse_joint: more than one location given.");
1727  }
1728  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
1729  skip_group(gedp, fip, str);
1730  free_joint(jp);
1731  return 0;
1732  }
1733  if (!parse_vect(gedp, &jp->location[0], fip, str)) {
1734  skip_group(gedp, fip, str);
1735  free_joint(jp);
1736  return 0;
1737  }
1738  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str)) {
1739  skip_group(gedp, fip, str);
1740  free_joint(jp);
1741  return 0;
1742  }
1743  locfound=1;
1744  break;
1745  case KEY_TRANS:
1746  if (!parse_trans(gedp, jp, trans, fip, str)) {
1747  skip_group(gedp, fip, str);
1748  free_joint(jp);
1749  return 0;
1750  }
1751  trans++;
1752  break;
1753  case KEY_ROT:
1754  if (!parse_rots(gedp, jp, rots, fip, str)) {
1755  skip_group(gedp, fip, str);
1756  free_joint(jp);
1757  return 0;
1758  }
1759  rots++;
1760  break;
1761  default:
1762  parse_error(gedp, str, "parse_joint: syntax error.");
1763  skip_group(gedp, fip, str);
1764  free_joint(jp);
1765  return 0;
1766  }
1767  }
1768  /* NOTREACHED */
1769 }
1770 
1771 
1772 static int
1773 parse_jset(struct ged *gedp, struct hold *hp, FILE *fip, struct bu_vls *str)
1774 {
1775  union bu_lex_token token;
1776  int jointfound, listfound, arcfound, pathfound;
1777 
1778  if (J_DEBUG & DEBUG_J_PARSE) {
1779  bu_vls_printf(gedp->ged_result_str, "parse_jset: open\n");
1780  }
1781 
1782  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_GROUP, fip, str))
1783  return 0;
1784 
1785  jointfound = listfound = arcfound = pathfound = 0;
1786  for (;;) {
1787  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
1788  parse_error(gedp, str, "parse_jset: Unexpected EOF getting contents of joint set");
1789  return 0;
1790  }
1791  if (token.type == BU_LEX_IDENT)
1792  bu_free(token.t_id.value, "unit token");
1793  if (token.type == BU_LEX_SYMBOL && token.t_key.value == SYM_CL_GROUP) {
1794  if (!jointfound) hp->j_set.joint = 0;
1795  if (!listfound && !arcfound && !pathfound) {
1796  parse_error(gedp, str, "parse_jset: no list/arc/path given.");
1797  return 0;
1798  }
1799  if (J_DEBUG & DEBUG_J_PARSE) {
1800  bu_vls_printf(gedp->ged_result_str, "parse_jset: close\n");
1801  }
1802  return 1;
1803  }
1804  if (token.type != BU_LEX_KEYWORD) {
1805  parse_error(gedp, str, "parse_jset: syntax error.");
1806  return 0;
1807  }
1808  switch (token.t_key.value) {
1809  case KEY_START:
1810  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
1811  skip_group(gedp, fip, str);
1812  return 0;
1813  }
1814  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
1815  parse_error(gedp, str, "parse_jset: Unexpected EOF getting '='");
1816  return 0;
1817  }
1818  if (token.type != BU_LEX_IDENT) {
1819  parse_error(gedp, str, "parse_jset: syntax error, expecting joint name.");
1820  skip_group(gedp, fip, str);
1821  return 0;
1822  }
1823  hp->j_set.joint = hp->joint = token.t_id.value;
1824  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str)) {
1825  skip_group(gedp, fip, str);
1826  return 0;
1827  }
1828  jointfound = 1;
1829  break;
1830  case KEY_ARC:
1831  if (!parse_ARC(gedp, &hp->j_set.path, fip, str)) {
1832  skip_group(gedp, fip, str);
1833  return 0;
1834  }
1835  arcfound = 1;
1836  break;
1837  case KEY_PATH:
1838  if (!parse_path(gedp, &hp->j_set.path, fip, str)) {
1839  skip_group(gedp, fip, str);
1840  return 0;
1841  }
1842  pathfound = 1;
1843  break;
1844  case KEY_JOINTS:
1845  if (!parse_list(gedp, &hp->j_set.path, fip, str)) {
1846  skip_group(gedp, fip, str);
1847  return 0;
1848  }
1849  listfound=1;
1850  break;
1851  case KEY_EXCEPT:
1852  if (!parse_list(gedp, &hp->j_set.exclude, fip, str)) {
1853  skip_group(gedp, fip, str);
1854  return 0;
1855  }
1856  break;
1857  default:
1858  parse_error(gedp, str, "parse_jset: syntax error.");
1859  skip_group(gedp, fip, str);
1860  return 0;
1861  }
1862  }
1863 }
1864 
1865 
1866 static int
1867 parse_solid(struct ged *gedp, struct hold_point *pp, FILE *fip, struct bu_vls *str)
1868 {
1869  union bu_lex_token token;
1870  int vertexfound = 0, arcfound = 0;
1871  double vertex;
1872 
1873  if (J_DEBUG & DEBUG_J_PARSE) {
1874  bu_vls_printf(gedp->ged_result_str, "parse_solid: open\n");
1875  }
1876 
1877  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_OP_GROUP, fip, str))
1878  return 0;
1879 
1880  for (;;) {
1881  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
1882  parse_error(gedp, str, "parse_solid: Unexpected EOF.");
1883  return 0;
1884  }
1885  if (token.type == BU_LEX_IDENT)
1886  bu_free(token.t_id.value, "unit token");
1887  if (token.type == BU_LEX_SYMBOL && token.t_key.value == SYM_CL_GROUP) {
1888  if (!arcfound) {
1889  parse_error(gedp, str, "parse_solid: path/arc missing.");
1890  return 0;
1891  }
1892  if (!vertexfound)
1893  pp->vertex_number = 1;
1894 
1895  if (J_DEBUG & DEBUG_J_PARSE) {
1896  bu_vls_printf(gedp->ged_result_str, "parse_solid: close\n");
1897  }
1898 
1899  return 1;
1900  }
1901  if (token.type != BU_LEX_KEYWORD) {
1902  parse_error(gedp, str, "parse_solid: syntax error getting solid information.");
1903  skip_group(gedp, fip, str);
1904  return 0;
1905  }
1906  switch (token.t_key.value) {
1907  case KEY_VERTEX:
1908  if (!parse_assign(gedp, &vertex, fip, str)) {
1909  skip_group(gedp, fip, str);
1910  return 0;
1911  }
1912  pp->vertex_number = vertex; /* double to int */
1913  vertexfound = 1;
1914  break;
1915  case KEY_PATH:
1916  if (!parse_path(gedp, &pp->arc, fip, str)) {
1917  skip_group(gedp, fip, str);
1918  return 0;
1919  }
1920  arcfound = 1;
1921  break;
1922  case KEY_ARC:
1923  if (!parse_ARC(gedp, &pp->arc, fip, str)) {
1924  skip_group(gedp, fip, str);
1925  return 0;
1926  }
1927  arcfound =1;
1928  break;
1929  default:
1930  parse_error(gedp, str, "parse_solid: syntax error.");
1931  }
1932  }
1933 }
1934 
1935 
1936 static int
1937 parse_point(struct ged *gedp, struct hold_point *pp, FILE *fip, struct bu_vls *str)
1938 {
1939  union bu_lex_token token;
1940 
1941  if (get_token(gedp, &token, fip, str, lex_solids, animsyms) == EOF) {
1942  parse_error(gedp, str, "parse_point: Unexpected EOF getting solid type.");
1943  return 0;
1944  }
1945  if (token.type == BU_LEX_IDENT)
1946  bu_free(token.t_id.value, "unit token");
1947  if (token.type != BU_LEX_KEYWORD) {
1948  parse_error(gedp, str, "parse_point: syntax error getting solid type.");
1949  return 0;
1950  }
1951  switch (token.t_key.value) {
1952  case ID_FIXED:
1953  pp->type = ID_FIXED;
1954  if (!parse_vect(gedp, &pp->point[0], fip, str))
1955  return 0;
1956  return gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str);
1957  case ID_SPH:
1958  pp->type = ID_SPH;
1959  break;
1960  case ID_GRIP:
1961  pp->type = ID_GRIP;
1962  break;
1963  case ID_JOINT:
1964  pp->type = ID_JOINT;
1965  break;
1966  default:
1967  parse_error(gedp, str, "parse_point: Syntax error-XXX.");
1968  skip_group(gedp, fip, str);
1969  return 0;
1970  }
1971  if (!parse_solid(gedp, pp, fip, str)) {
1972  skip_group(gedp, fip, str);
1973  return 0;
1974  }
1975  if (J_DEBUG & DEBUG_J_PARSE) {
1976  bu_vls_printf(gedp->ged_result_str, "parse_point: close.\n");
1977  }
1978  return 1;
1979 }
1980 
1981 
1982 static int
1983 parse_hold(struct ged *gedp, FILE *fip, struct bu_vls *str)
1984 {
1985  struct hold *hp;
1986  union bu_lex_token token;
1987  int jsetfound = 0, efffound=0, goalfound=0, weightfound=0, prifound=0;
1988 
1989  if (J_DEBUG & DEBUG_J_PARSE) {
1990  bu_vls_printf(gedp->ged_result_str, "parse_hold: reading constraint\n");
1991  }
1992 
1993  BU_GET(hp, struct hold);
1994  hp->l.magic = MAGIC_HOLD_STRUCT;
1995  hp->name = NULL;
1996  hp->joint = NULL;
1997  BU_LIST_INIT(&hp->j_head);
1998  hp->effector.type = ID_FIXED;
1999  hp->effector.arc.type = ARC_UNSET;
2001  hp->effector.flag = 0;
2002  hp->objective.type = ID_FIXED;
2003  hp->objective.arc.type = ARC_UNSET;
2005  hp->objective.flag = 0;
2006  hp->j_set.joint = NULL;
2007  hp->j_set.path.type = ARC_UNSET;
2008  hp->j_set.exclude.type = ARC_UNSET;
2009 
2010  /* read constraint name */
2011  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
2012  parse_error(gedp, str, "parse_hold: Unexpected EOF getting name.");
2013  free_hold(hp);
2014  return 0;
2015  }
2016  /* read constraint group label */
2017  if (token.type == BU_LEX_IDENT) {
2018  hp->name = token.t_id.value;
2019  if (get_token(gedp, &token, fip, str, (struct bu_lex_key *)NULL, animsyms) == EOF) {
2020  parse_error(gedp, str, "parse_hold: Unexpected EOF getting open group.");
2021  free_hold(hp);
2022  return 0;
2023  }
2024  }
2025 
2026  /* sanity */
2027  if (token.type == BU_LEX_IDENT)
2028  bu_free(token.t_id.value, "unit token");
2029  if (token.type != BU_LEX_SYMBOL || token.t_key.value != SYM_OP_GROUP) {
2030  parse_error(gedp, str, "parse_hold: syntax error, expecting open group.");
2031  free_hold(hp);
2032  return 0;
2033  }
2034 
2035  /* read in the constraint details */
2036  for (;;) {
2037  if (get_token(gedp, &token, fip, str, animkeys, animsyms) == EOF) {
2038  parse_error(gedp, str, "parse_hold: Unexpected EOF getting constraint contents.");
2039  skip_group(gedp, fip, str);
2040  free_hold(hp);
2041  }
2042  if (token.type == BU_LEX_IDENT)
2043  bu_free(token.t_id.value, "unit token");
2044 
2045  if (token.type == BU_LEX_SYMBOL && token.t_key.value == SYM_CL_GROUP) {
2046  int i;
2047  struct directory *dp;
2048 
2049  if (J_DEBUG & DEBUG_J_PARSE) {
2050  bu_vls_printf(gedp->ged_result_str, "parse_hold: closing.\n");
2051  }
2052 
2053  /* done loading our arc, look up our object names */
2054  if (!hp->effector.path.fp_names) {
2055  db_free_full_path(&hp->effector.path); /* sanity */
2056  for (i=0; i<= hp->effector.arc.arc_last; i++) {
2057  dp = db_lookup(gedp->ged_wdbp->dbip, hp->effector.arc.arc[i], LOOKUP_NOISY);
2058  if (!dp) {
2059  continue;
2060  }
2062  }
2063  }
2064  if (!hp->objective.path.fp_names) {
2065  db_free_full_path(&hp->objective.path); /* sanity */
2066  for (i=0; i<= hp->objective.arc.arc_last; i++) {
2067  dp = db_lookup(gedp->ged_wdbp->dbip, hp->objective.arc.arc[i], LOOKUP_NOISY);
2068  if (!dp) {
2069  continue;
2070  }
2072  }
2073  }
2074 
2075  if (!jsetfound) {
2076  parse_error(gedp, str, "parse_hold: no joint set given.");
2077  free_hold(hp);
2078  skip_group(gedp, fip, str);
2079  return 0;
2080  }
2081  if (!efffound) {
2082  parse_error(gedp, str, "parse_hold: no effector given.");
2083  free_hold(hp);
2084  skip_group(gedp, fip, str);
2085  return 0;
2086  }
2087  if (!goalfound) {
2088  parse_error(gedp, str, "parse_hold: no goal given.");
2089  free_hold(hp);
2090  skip_group(gedp, fip, str);
2091  return 0;
2092  }
2093  if (!weightfound) {
2094  hp->weight = 1.0;
2095  }
2096  if (!prifound) {
2097  hp->priority = 50;
2098  }
2099  BU_LIST_INSERT(&hold_head, &(hp->l));
2100 
2101  gobble_token(gedp, BU_LEX_SYMBOL, SYM_END, fip, str);
2102  return 1;
2103  }
2104  if (token.type != BU_LEX_KEYWORD) {
2105  parse_error(gedp, str, "parse_hold: syntax error");
2106  skip_group(gedp, fip, str);
2107  free_hold(hp);
2108  return 0;
2109  }
2110 
2111  switch (token.t_key.value) {
2112  /* effector, goal */
2113  case KEY_WEIGHT:
2114  if (!parse_assign(gedp, &hp->weight, fip, str)) {
2115  free_hold(hp);
2116  skip_group(gedp, fip, str);
2117  return 0;
2118  }
2119  weightfound = 1;
2120  break;
2121  case KEY_PRI:
2122  if (!parse_assign(gedp, (double *)&hp->priority, fip, str)) {
2123  free_hold(hp);
2124  skip_group(gedp, fip, str);
2125  return 0;
2126  }
2127  prifound=1;
2128  break;
2129  case KEY_JOINTS:
2130  if (jsetfound) {
2131  parse_error(gedp, str, "parse_hold: joint set redefined.");
2132  free_hold(hp);
2133  skip_group(gedp, fip, str);
2134  return 0;
2135  }
2136  if (!parse_jset(gedp, hp, fip, str)) {
2137  free_hold(hp);
2138  skip_group(gedp, fip, str);
2139  return 0;
2140  }
2141  jsetfound = 1;
2142  break;
2143  case KEY_EFF:
2144  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
2145  skip_group(gedp, fip, str);
2146  free_hold(hp);
2147  return 0;
2148  }
2149  if (!parse_point(gedp, &hp->effector, fip, str)) {
2150  skip_group(gedp, fip, str);
2151  free_hold(hp);
2152  return 0;
2153  }
2154  efffound = 1;
2155  break;
2156  case KEY_POINT:
2157  if (!gobble_token(gedp, BU_LEX_SYMBOL, SYM_EQ, fip, str)) {
2158  skip_group(gedp, fip, str);
2159  free_hold(hp);
2160  return 0;
2161  }
2162  if (!parse_point(gedp, &hp->objective, fip, str)) {
2163  skip_group(gedp, fip, str);
2164  free_hold(hp);
2165  return 0;
2166  }
2167  goalfound=1;
2168  break;
2169  default:
2170  parse_error(gedp, str, "parse_hold: syntax error.");
2171  break;
2172  }
2173  }
2174  /* NOTREACHED */
2175 }
2176 
2177 
2178 static void
2179 joint_adjust(struct ged *gedp, struct joint *jp)
2180 {
2181  struct animate *anp;
2182  double tmp;
2183  mat_t m1, m2;
2184  quat_t q1;
2185  int i;
2186 
2187  if (gedp->ged_wdbp->dbip == DBI_NULL)
2188  return;
2189 
2190  /*
2191  * If no animate structure, cons one up.
2192  */
2193  anp=jp->anim;
2194  if (!anp || anp->magic != ANIMATE_MAGIC) {
2195  char *sofar;
2196  struct directory *dp = NULL;
2197  BU_ALLOC(anp, struct animate); /* may be free'd by librt */
2198  anp->magic = ANIMATE_MAGIC;
2199  db_full_path_init(&anp->an_path);
2200 
2201  for (i=0; i<= jp->path.arc_last; i++) {
2202  dp = db_lookup(gedp->ged_wdbp->dbip, jp->path.arc[i], LOOKUP_NOISY);
2203  if (!dp) {
2204  continue;
2205  }
2206  db_add_node_to_full_path(&anp->an_path, dp);
2207  }
2208  jp->anim=anp;
2209  db_add_anim(gedp->ged_wdbp->dbip, anp, 0);
2210 
2211  if (J_DEBUG & DEBUG_J_MOVE) {
2212  sofar = db_path_to_string(&jp->anim->an_path);
2213  bu_vls_printf(gedp->ged_result_str, "joint move: %s added animate %s to %s(%p)\n",
2214  jp->name, sofar, dp->d_namep, (void *)dp);
2215  }
2216  }
2217 
2218 
2219 #define ANIM_MAT (anp->an_u.anu_m.anm_mat)
2220 
2221  anp->an_type = RT_AN_MATRIX;
2222  anp->an_u.anu_m.anm_op = ANM_RMUL;
2223 
2224  /* Build the base matrix. Ident with translate back to origin. */
2225  MAT_IDN(ANIM_MAT);
2226  MAT_DELTAS_VEC_NEG(ANIM_MAT, jp->location);
2227 
2228  /* Do rotations. */
2229  for (i=0; i<3; i++) {
2230  if (jp->rots[i].upper < jp->rots[i].lower)
2231  break;
2232 
2233  /* Build a quat from that. */
2234  tmp = (jp->rots[i].current * DEG2RAD)/2.0;
2235  VMOVE(q1, jp->rots[i].quat);
2236  if (J_DEBUG & DEBUG_J_MOVE) {
2237  bu_vls_printf(gedp->ged_result_str, "joint move: rotating %g around (%g %g %g)\n",
2238  tmp*2*RAD2DEG, q1[X], q1[Y], q1[Z]);
2239  }
2240  {double srot = sin(tmp);
2241  q1[X] *= srot;
2242  q1[Y] *= srot;
2243  q1[Z] *= srot;
2244  }
2245  q1[W] = cos(tmp);
2246 
2247  /* Build matrix. */
2248  quat_quat2mat(m2, q1);
2249  MAT_COPY(m1, ANIM_MAT);
2250  bn_mat_mul(ANIM_MAT, m2, m1);
2251  /* rmult matrix into the mat we are building. */
2252  }
2253 
2254  /* do the translations. */
2255  for (i=0; i<3; i++) {
2256  if (jp->dirs[i].upper < jp->dirs[i].lower)
2257  break;
2258 
2259  /* build matrix. */
2260  tmp = jp->dirs[i].current;
2261  MAT_IDN(m2);
2262  MAT_DELTAS(m2, jp->dirs[i].unitvec[X]*tmp,
2263  jp->dirs[i].unitvec[Y]*tmp,
2264  jp->dirs[i].unitvec[Z]*tmp);
2265 
2266  if (J_DEBUG & DEBUG_J_MOVE) {
2267  bu_vls_printf(gedp->ged_result_str, "joint move: moving %g along (%g %g %g)\n",
2268  tmp*gedp->ged_wdbp->dbip->dbi_base2local, m2[3], m2[7], m2[11]);
2269  }
2270  MAT_COPY(m1, ANIM_MAT);
2271  bn_mat_mul(ANIM_MAT, m2, m1);
2272  }
2273 
2274  /* Now move the whole thing back to original location. */
2275  MAT_IDN(m2);
2276  MAT_DELTAS_VEC(m2, jp->location);
2277  MAT_COPY(m1, ANIM_MAT);
2278  bn_mat_mul(ANIM_MAT, m2, m1);
2279  if (J_DEBUG & DEBUG_J_MOVE) {
2280  bn_mat_print("joint move: ANIM_MAT", ANIM_MAT);
2281  }
2282 }
2283 
2284 
2285 static int
2286 joint_load(struct ged *gedp, int argc, const char *argv[])
2287 {
2288  static struct bu_list path_head;
2289 
2290  FILE *fip;
2291  struct bu_vls instring = BU_VLS_INIT_ZERO;
2292  union bu_lex_token token;
2293  int no_unload = 0, no_apply=0, no_mesh=0;
2294  int c;
2295  struct joint *jp;
2296  struct hold *hp;
2297 
2298  if (gedp->ged_wdbp->dbip == DBI_NULL) {
2299  bu_vls_printf(gedp->ged_result_str, "A database is not open!\n");
2300  return GED_ERROR;
2301  }
2302 
2303  bu_optind = 1;
2304  while ((c=bu_getopt(argc, (char * const *)argv, "uam")) != -1) {
2305  switch (c) {
2306  case 'u': no_unload = 1;break;
2307  case 'a': no_apply = 1; break;
2308  case 'm': no_mesh = 1; break;
2309  default:
2310  bu_vls_printf(gedp->ged_result_str, "Usage: joint load [-uam] file_name [files]\n");
2311  break;
2312  }
2313  }
2314  argv += bu_optind;
2315  argc -= bu_optind;
2316  if (!no_unload) joint_unload(gedp, 0, NULL);
2317 
2318  base2mm = gedp->ged_wdbp->dbip->dbi_base2local;
2319  mm2base = gedp->ged_wdbp->dbip->dbi_local2base;
2320 
2321  while (argc) {
2322  fip = fopen(*argv, "rb");
2323  if (fip == NULL) {
2324  bu_vls_printf(gedp->ged_result_str, "joint load: unable to open '%s'.\n", *argv);
2325  ++argv;
2326  --argc;
2327  continue;
2328  }
2329  if (J_DEBUG & DEBUG_J_LOAD) {
2330  bu_vls_printf(gedp->ged_result_str, "joint load: loading from '%s'", *argv);
2331  }
2332  lex_line = 0;
2333  lex_name = *argv;
2334 
2335  while (get_token(gedp, &token, fip, &instring, animkeys, animsyms) != EOF) {
2336  if (token.type == BU_LEX_KEYWORD) {
2337  if (token.t_key.value == KEY_JOINT) {
2338  if (parse_joint(gedp, fip, &instring)) {
2339  jp = BU_LIST_LAST(joint, &joint_head);
2340  if (!no_apply) joint_adjust(gedp, jp);
2341  }
2342  } else if (token.t_key.value == KEY_CON) {
2343  (void)parse_hold(gedp, fip, &instring);
2344  } else if (token.t_key.value == KEY_UNITS) {
2345  (void)parse_units(gedp, fip, &instring);
2346  } else {
2347  parse_error(gedp, &instring, "joint load: syntax error.");
2348  }
2349  } else {
2350  parse_error(gedp, &instring, "joint load: syntax error.");
2351  }
2352  if (token.type == BU_LEX_IDENT) {
2353  bu_free(token.t_id.value, "unit token");
2354  }
2355  }
2356  fclose(fip);
2357  argc--;
2358  argv++;
2359  }
2360 
2361  /* For each "struct arc" in joints or constraints, build a linked
2362  * list of all ARC_PATHs and a control list of all unique tops.
2363  */
2364  BU_LIST_INIT(&path_head);
2365  for (BU_LIST_FOR(jp, joint, &joint_head)) {
2366  if (jp->path.type == ARC_PATH) {
2367  BU_LIST_INSERT(&path_head, &(jp->path.l));
2368  }
2369  }
2370  for (BU_LIST_FOR(hp, hold, &hold_head)) {
2371  if (hp->j_set.path.type == ARC_PATH) {
2372  BU_LIST_INSERT(&path_head, &(hp->j_set.path.l));
2373  }
2374  if (hp->effector.arc.type == ARC_PATH) {
2375  BU_LIST_INSERT(&path_head, &(hp->effector.arc.l));
2376  }
2377  if (hp->objective.arc.type == ARC_PATH) {
2378  BU_LIST_INSERT(&path_head, &(hp->objective.arc.l));
2379  }
2380  }
2381 
2382  /*
2383  * All ARC_PATHS have been translated into ARC_ARC.
2384  *
2385  * Constraints need to have ARC_ARCs translated to ARC_LISTS, this
2386  * can be done at a latter time, such as when the constraint is
2387  * evaluated. ???
2388  */
2389  for (BU_LIST_FOR(hp, hold, &hold_head)) {
2390  struct directory *dp;
2391  int i;
2392 
2393  if (hp->effector.arc.type == ARC_ARC) {
2395 
2396  /* search for these paths. */
2397  for (i=0; i<= hp->effector.arc.arc_last; i++) {
2398  dp = db_lookup(gedp->ged_wdbp->dbip, hp->effector.arc.arc[i], LOOKUP_NOISY);
2399  if (!dp) {
2400  continue;
2401  }
2403  }
2404  }
2405  if (hp->objective.arc.type == ARC_ARC) {
2407 
2408  for (i=0; i<= hp->objective.arc.arc_last; i++) {
2409  dp = db_lookup(gedp->ged_wdbp->dbip, hp->objective.arc.arc[i], LOOKUP_NOISY);
2410  if (!dp) {
2411  break;
2412  }
2414  }
2415  }
2416  }
2417  if (!no_mesh) (void) joint_mesh(gedp, 0, 0);
2418  return GED_OK;
2419 }
2420 
2421 
2422 static int
2423 joint_save(struct ged *gedp, int argc, const char *argv[])
2424 {
2425  struct joint *jp;
2426  int i;
2427  FILE *fop;
2428 
2429  if (gedp->ged_wdbp->dbip == DBI_NULL) {
2430  bu_vls_printf(gedp->ged_result_str, "A database is not open!\n");
2431  return GED_ERROR;
2432  }
2433 
2434  --argc;
2435  ++argv;
2436 
2437  if (argc <1) {
2438  bu_vls_printf(gedp->ged_result_str, "joint save: missing file name");
2439  return GED_ERROR;
2440  }
2441  fop = fopen(*argv, "wb");
2442  if (!fop) {
2443  bu_vls_printf(gedp->ged_result_str, "joint save: unable to open '%s' for writing.\n", *argv);
2444  return GED_ERROR;
2445  }
2446  fprintf(fop, "# joints and constraints for '%s'\n",
2447  gedp->ged_wdbp->dbip->dbi_title);
2448 
2449  /* Output the current editing units */
2450  fprintf(fop, "units %gmm;\n", gedp->ged_wdbp->dbip->dbi_local2base);
2451 
2452  mm2base = gedp->ged_wdbp->dbip->dbi_local2base;
2453  base2mm = gedp->ged_wdbp->dbip->dbi_base2local;
2454 
2455  for (BU_LIST_FOR(jp, joint, &joint_head)) {
2456  fprintf(fop, "joint %s {\n", jp->name);
2457  if (jp->path.type == ARC_PATH) {
2458  fprintf(fop, "\tpath = %s", jp->path.arc[0]);
2459  for (i=1;i<jp->path.arc_last;i++) {
2460  fprintf(fop, "/%s", jp->path.arc[i]);
2461  }
2462  fprintf(fop, "-%s;\n", jp->path.arc[i]);
2463  } else if (jp->path.type & ARC_BOTH) {
2464  fprintf(fop, "\tpath = %s", jp->path.original[0]);
2465  for (i=1; i < jp->path.org_last; i++) {
2466  fprintf(fop, "/%s", jp->path.original[i]);
2467  }
2468  fprintf(fop, "-%s;\n", jp->path.original[i]);
2469  } else {
2470  /* ARC_ARC */
2471  fprintf(fop, "\tarc = %s", jp->path.arc[0]);
2472  for (i=1;i<jp->path.arc_last;i++) {
2473  fprintf(fop, "/%s", jp->path.arc[i]);
2474  }
2475  fprintf(fop, "/%s;\n", jp->path.arc[i]);
2476  }
2477  fprintf(fop, "\tlocation = (%.15e, %.15e, %.15e);\n",
2478  jp->location[X]*mm2base, jp->location[Y]*mm2base,
2479  jp->location[Z]*mm2base);
2480 
2481  for (i=0;i<3;i++) {
2482  if (jp->rots[i].upper < jp->rots[i].lower)
2483  break;
2484  fprintf(fop,
2485  "\trotate {\n\t\tdirection = (%.15e, %.15e, %.15e);\n\t\tlimits = %.15e, %.15e, %.15e;\n\t}\n",
2486  jp->rots[i].quat[X], jp->rots[i].quat[Y],
2487  jp->rots[i].quat[Z],
2488  jp->rots[i].lower, jp->rots[i].upper,
2489  jp->rots[i].current);
2490  }
2491  for (i=0;i<3;i++) {
2492  if (jp->dirs[i].upper < jp->dirs[i].lower)
2493  break;
2494  fprintf(fop,
2495  "\ttranslate {\n\t\tdirection = (%.15e, %.15e, %.15e);\n\t\tlimits = %.15e, %.15e, %.15e;\n\t}\n",
2496  jp->dirs[i].unitvec[X], jp->dirs[i].unitvec[Y],
2497  jp->dirs[i].unitvec[Z], jp->dirs[i].lower*mm2base,
2498  jp->dirs[i].upper*mm2base, jp->dirs[i].current*mm2base);
2499  }
2500  fprintf(fop, "};\n");
2501  }
2502  fclose(fop);
2503  return GED_OK;
2504 }
2505 
2506 
2507 static int
2508 joint_accept(struct ged *gedp, int argc, const char *argv[])
2509 {
2510  struct joint *jp;
2511  int i;
2512  int c;
2513  int no_mesh = 0;
2514 
2515  bu_optind=1;
2516  while ((c=bu_getopt(argc, (char * const *)argv, "m")) != -1) {
2517  switch (c) {
2518  case 'm': no_mesh=1;break;
2519  default:
2520  bu_vls_printf(gedp->ged_result_str, "Usage: joint accept [-m] [joint_names]\n");
2521  break;
2522  }
2523  }
2524  argc -= bu_optind;
2525  argv += bu_optind;
2526 
2527  for (BU_LIST_FOR(jp, joint, &joint_head)) {
2528  if (argc) {
2529  for (i=0; i<argc; i++) {
2530  if (BU_STR_EQUAL(argv[i], jp->name))
2531  break;
2532  }
2533  if (i>=argc)
2534  continue;
2535  }
2536  for (i=0; i<3; i++) {
2537  jp->dirs[i].accepted = jp->dirs[i].current;
2538  jp->rots[i].accepted = jp->rots[i].current;
2539  }
2540  }
2541  if (!no_mesh) joint_mesh(gedp, 0, 0);
2542  return GED_OK;
2543 }
2544 
2545 
2546 static int
2547 joint_reject(struct ged *gedp, int argc, const char *argv[])
2548 {
2549  struct joint *jp;
2550  int i;
2551  int c;
2552  int no_mesh = 0;
2553 
2554  bu_optind=1;
2555  while ((c=bu_getopt(argc, (char * const *)argv, "m")) != -1) {
2556  switch (c) {
2557  case 'm': no_mesh=1;break;
2558  default:
2559  bu_vls_printf(gedp->ged_result_str, "Usage: joint accept [-m] [joint_names]\n");
2560  break;
2561  }
2562  }
2563  argc -= bu_optind;
2564  argv += bu_optind;
2565 
2566  for (BU_LIST_FOR(jp, joint, &joint_head)) {
2567  if (argc) {
2568  for (i=0; i<argc; i++) {
2569  if (BU_STR_EQUAL(argv[i], jp->name))
2570  break;
2571  }
2572  if (i>=argc)
2573  continue;
2574  }
2575 
2576  for (i=0; i<3; i++) {
2577  jp->rots[i].current = jp->rots[i].accepted;
2578  jp->dirs[i].current = jp->dirs[i].accepted;
2579  }
2580  joint_adjust(gedp, jp);
2581  }
2582  if (!no_mesh) joint_mesh(gedp, 0, 0);
2583  return GED_OK;
2584 }
2585 
2586 
2587 struct solve_stack {
2588  struct bu_list l;
2589  struct joint *jp;
2590  int freedom;
2591  double oldval;
2592  double newval;
2593 };
2594 #define SOLVE_STACK_MAGIC 0x76766767
2597  &solve_head,
2598  &solve_head
2599 };
2600 
2601 
2602 static void
2603 joint_clear(void)
2604 {
2605  struct stack_solve *ssp;
2606  BU_LIST_POP(stack_solve, &solve_head, ssp);
2607  while (ssp) {
2608  bu_free((void *)ssp, "struct stack_solve");
2609  BU_LIST_POP(stack_solve, &solve_head, ssp);
2610  }
2611 }
2612 
2613 
2614 static int
2615 part_solve(struct ged *gedp, struct hold *hp, double limits, double tol)
2616 {
2617  struct joint *jp;
2618  double f0, f1, f2;
2619  double ax, bx, cx;
2620  double x0, x1, x2, x3;
2621  double besteval, bestvalue = 0, origvalue;
2622  int bestfreedom = -1;
2623  struct joint *bestjoint;
2624  struct jointH *jh;
2625 
2626  if (J_DEBUG & DEBUG_J_SOLVE) {
2627  bu_vls_printf(gedp->ged_result_str, "part_solve: solving for %s.\n", hp->name);
2628  }
2629 
2630  if (BU_LIST_IS_EMPTY(&hp->j_head)) {
2631  size_t i, j;
2632  int startjoint;
2633  startjoint = -1;
2634  if (J_DEBUG & DEBUG_J_SOLVE) {
2635  bu_vls_printf(gedp->ged_result_str, "part_solve: looking for joints on arc.\n");
2636  }
2637  for (BU_LIST_FOR(jp, joint, &joint_head)) {
2638  if (hp->j_set.path.type == ARC_LIST) {
2639  for (i=0; i <= (size_t)hp->j_set.path.arc_last; i++) {
2640  if (BU_STR_EQUAL(jp->name, hp->j_set.path.arc[i])) {
2641  BU_GET(jh, struct jointH);
2642  jh->l.magic = MAGIC_JOINT_HANDLE;
2643  jh->p = jp;
2644  jp->uses++;
2645  jh->arc_loc = -1;
2646  jh->flag = 0;
2647  BU_LIST_APPEND(&hp->j_head, &jh->l);
2648  break;
2649  }
2650  }
2651  continue;
2652  }
2653  for (i=0;i<hp->effector.path.fp_len; i++) {
2654  if (!BU_STR_EQUAL(jp->path.arc[0],
2655  hp->effector.path.fp_names[i]->d_namep)==0)
2656  break;
2657  }
2658  if (i+jp->path.arc_last >= hp->effector.path.fp_len)
2659  continue;
2660  for (j=1; j <= (size_t)jp->path.arc_last;j++) {
2661  if (!BU_STR_EQUAL(jp->path.arc[j],
2662  hp->effector.path.fp_names[i+j]->d_namep)
2663  != 0)
2664  break;
2665  }
2666  if (j>(size_t)jp->path.arc_last) {
2667  if (J_DEBUG & DEBUG_J_SOLVE) {
2668  bu_vls_printf(gedp->ged_result_str, "part_solve: found %s\n", jp->name);
2669  }
2670  BU_GET(jh, struct jointH);
2671  jh->l.magic = MAGIC_JOINT_HANDLE;
2672  jh->p = jp;
2673  jp->uses++;
2674  jh->arc_loc = i+j-1;
2675  jh->flag = 0;
2676  BU_LIST_APPEND(&hp->j_head, &jh->l);
2677  if (BU_STR_EQUAL(hp->joint, jp->name)) {
2678  startjoint = jh->arc_loc;
2679  }
2680  }
2681  }
2682  if (startjoint < 0) {
2683  bu_vls_printf(gedp->ged_result_str, "part_solve: %s, joint %s not on arc.\n", hp->name, hp->joint);
2684  }
2685  for (BU_LIST_FOR(jh, jointH, &hp->j_head)) {
2686  /*
2687  * XXX - Coming to a source module near you RSN. Not only
2688  * joint location, but drop joints that are "locked"
2689  */
2690  if (jh->arc_loc < startjoint) {
2691  struct jointH *hold;
2692  if (J_DEBUG & DEBUG_J_SOLVE) {
2693  bu_vls_printf(gedp->ged_result_str, "part_solve: dequeuing %s from %s", jh->p->name, hp->name);
2694  }
2695  hold=(struct jointH *)jh->l.back;
2696  BU_LIST_DEQUEUE(&jh->l);
2697  jh->p->uses--;
2698  jh=hold;
2699  }
2700  }
2701  }
2702  origvalue = besteval = hold_eval(gedp, hp);
2703  if (fabs(origvalue) < tol) {
2704  if (J_DEBUG & DEBUG_J_SOLVE) {
2705  bu_vls_printf(gedp->ged_result_str, "part_solve: solved, original(%g) < tol(%g)\n",
2706  origvalue, tol);
2707  }
2708  return 0;
2709  }
2710  bestjoint = (struct joint *)0;
2711 
2712  /* From here, we try each joint to try and find the best movement
2713  * if any.
2714  */
2715  for (BU_LIST_FOR(jh, jointH, &hp->j_head)) {
2716  int i;
2717  double hold;
2718  jp= jh->p;
2719  for (i=0;i<3;i++) {
2720  if ((jh->flag & (1<<i)) ||
2721  jp->rots[i].upper < jp->rots[i].lower) {
2722  jh->flag |= (1<<i);
2723  continue;
2724  }
2725  hold = bx =jp->rots[i].current;
2726 
2727 #define EPSI 1e-6
2728 #define R 0.61803399
2729 #define C (1.0-R)
2730 
2731  /* find the min in the range ax-bx-cx where ax is
2732  * bx-limits-0.001 or lower and cx = bx+limits+0.001 or
2733  * upper.
2734  */
2735  ax=bx-limits-EPSI;
2736  if (ax < jp->rots[i].lower)
2737  ax=jp->rots[i].lower;
2738  cx=bx+limits+EPSI;
2739  if (cx > jp->rots[i].upper)
2740  cx=jp->rots[i].upper;
2741  x0=ax;
2742  x3=cx;
2743  if (fabs(cx-bx) > fabs(bx-ax)) {
2744  x1=bx;
2745  x2=bx+C*(cx-bx);
2746  } else {
2747  x2=bx;
2748  x1=bx-C*(bx-ax);
2749  }
2750  jp->rots[i].current = x1;
2751  joint_adjust(gedp, jp);
2752  f1=hold_eval(gedp, hp);
2753  jp->rots[i].current = x2;
2754  joint_adjust(gedp, jp);
2755  f2=hold_eval(gedp, hp);
2756  while (fabs(x3-x0) > EPSI*(fabs(x1)+fabs(x2))) {
2757  if (f2 < f1) {
2758  x0 = x1;
2759  x1 = x2;
2760  x2 = R*x1+C*x3;
2761  f1=f2;
2762  jp->rots[i].current = x2;
2763  joint_adjust(gedp, jp);
2764  f2=hold_eval(gedp, hp);
2765  } else {
2766  x3=x2;
2767  x2=x1;
2768  x1=R*x2+C*x0;
2769  f2=f1;
2770  jp->rots[i].current = x1;
2771  joint_adjust(gedp, jp);
2772  f1=hold_eval(gedp, hp);
2773  }
2774  }
2775  if (f1 < f2) {
2776  x0=x1;
2777  f0=f1;
2778  } else {
2779  x0=x2;
2780  f0=f2;
2781  }
2782  jp->rots[i].current = hold;
2783  joint_adjust(gedp, jp);
2784  if (f0 < besteval) {
2785  if (J_DEBUG & DEBUG_J_SOLVE) {
2786  bu_vls_printf(gedp->ged_result_str, "part_solve: NEW min %s(%d, %g) %g <%g\n",
2787  jp->name, i, x0, f0, besteval);
2788  }
2789  besteval = f0;
2790  bestjoint = jp;
2791  bestfreedom = i;
2792  bestvalue = x0;
2793  } else if (J_DEBUG & DEBUG_J_SOLVE) {
2794  bu_vls_printf(gedp->ged_result_str, "part_solve: OLD min %s(%d, %g)%g >= %g\n",
2795  jp->name, i, x0, f0, besteval);
2796  }
2797  }
2798 
2799  /* Now we do the same thing but for directional movements. */
2800  for (i=0;i<3;i++) {
2801  if ((jh->flag & (1<<(i+3))) ||
2802  (jp->dirs[i].upper < jp->dirs[i].lower)) {
2803  jh->flag |= (1<<(i+3));
2804  continue;
2805  }
2806  hold = bx =jp->dirs[i].current;
2807 
2808  /* find the min in the range ax-bx-cx where ax is
2809  * bx-limits-0.001 or lower and cx = bx+limits+0.001 or
2810  * upper.
2811  */
2812  ax=bx-limits-EPSI;
2813  if (ax < jp->dirs[i].lower) ax=jp->dirs[i].lower;
2814  cx=bx+limits+EPSI;
2815  if (cx > jp->dirs[i].upper) cx=jp->dirs[i].upper;
2816  x0=ax;
2817  x3=cx;
2818  if (fabs(cx-bx) > fabs(bx-ax)) {
2819  x1=bx;
2820  x2=bx+C*(cx-bx);
2821  } else {
2822  x2=bx;
2823  x1=bx-C*(bx-ax);
2824  }
2825  jp->dirs[i].current = x1;
2826  joint_adjust(gedp, jp);
2827  f1=hold_eval(gedp, hp);
2828  jp->dirs[i].current = x2;
2829  joint_adjust(gedp, jp);
2830  f2=hold_eval(gedp, hp);
2831  while (fabs(x3-x0) > EPSI*(fabs(x1)+fabs(x2))) {
2832  if (f2 < f1) {
2833  x0 = x1;
2834  x1 = x2;
2835  x2 = R*x1+C*x3;
2836  f1=f2;
2837  jp->dirs[i].current = x2;
2838  joint_adjust(gedp, jp);
2839  f2=hold_eval(gedp, hp);
2840  } else {
2841  x3=x2;
2842  x2=x1;
2843  x1=R*x2+C*x0;
2844  f2=f1;
2845  jp->dirs[i].current = x1;
2846  joint_adjust(gedp, jp);
2847  f1=hold_eval(gedp, hp);
2848  }
2849  }
2850  if (f1 < f2) {
2851  x0=x1;
2852  f0=f1;
2853  } else {
2854  x0=x2;
2855  f0=f2;
2856  }
2857  jp->dirs[i].current = hold;
2858  joint_adjust(gedp, jp);
2859  if (f0 < besteval-SQRT_SMALL_FASTF) {
2860  if (J_DEBUG & DEBUG_J_SOLVE) {
2861  bu_vls_printf(gedp->ged_result_str, "part_solve: NEW min %s(%d, %g) %g <%g delta=%g\n",
2862  jp->name, i+3, x0, f0, besteval, besteval-f0);
2863  }
2864  besteval = f0;
2865  bestjoint = jp;
2866  bestfreedom = i + 3;
2867  bestvalue = x0;
2868  } else if (J_DEBUG & DEBUG_J_SOLVE) {
2869  bu_vls_printf(gedp->ged_result_str, "part_solve: OLD min %s(%d, %g)%g >= %g\n",
2870  jp->name, i, x0, f0, besteval);
2871  }
2872 
2873  }
2874  }
2875 
2876  /* Did we find a better joint? */
2877  if (!bestjoint) {
2878  if (J_DEBUG & DEBUG_J_SOLVE) {
2879  bu_vls_printf(gedp->ged_result_str, "part_solve: No joint configuration found to be better.\n");
2880  }
2881  return 0;
2882  }
2883  if (origvalue - besteval < (tol/100.0)) {
2884  if (J_DEBUG & DEBUG_J_SOLVE) {
2885  bu_vls_printf(gedp->ged_result_str, "part_solve: No reasonable improvement found.\n");
2886  }
2887  return 0;
2888  }
2889  {
2890  struct solve_stack *ssp;
2891  BU_GET(ssp, struct solve_stack);
2892  ssp->jp = bestjoint;
2893  ssp->freedom = bestfreedom;
2894  ssp->oldval = (bestfreedom<3) ? bestjoint->rots[bestfreedom].current :
2895  bestjoint->dirs[bestfreedom-3].current;
2896  ssp->newval = bestvalue;
2897  BU_LIST_PUSH(&solve_head, ssp);
2898  }
2899  if (bestfreedom < 3) {
2900  bestjoint->rots[bestfreedom].current = bestvalue;
2901  } else {
2902  bestjoint->dirs[bestfreedom-3].current = bestvalue;
2903  }
2904  joint_adjust(gedp, bestjoint);
2905  return 1;
2906 }
2907 
2908 
2909 static void
2910 reject_move(struct ged *gedp)
2911 {
2912  struct solve_stack *ssp;
2913  BU_LIST_POP(solve_stack, &solve_head, ssp);
2914  if (!ssp)
2915  return;
2916 
2917  if (J_DEBUG & DEBUG_J_SYSTEM) {
2918  bu_vls_printf(gedp->ged_result_str, "reject_move: rejecting %s(%d, %g)->%g\n", ssp->jp->name,
2919  ssp->freedom, ssp->newval, ssp->oldval);
2920  }
2921  if (ssp->freedom<3) {
2922  ssp->jp->rots[ssp->freedom].current = ssp->oldval;
2923  } else {
2924  ssp->jp->dirs[ssp->freedom-3].current = ssp->oldval;
2925  }
2926  joint_adjust(gedp, ssp->jp);
2927  BU_PUT(ssp, struct solve_stack);
2928 }
2929 
2930 
2931 /* Constraint system solver.
2932  *
2933  * The basic idea is that we are called with some priority level. We
2934  * will attempt to solve all constraints nodes at that level without
2935  * breaking a joint solution for a node of a higher priority.
2936  *
2937  * Returns:
2938  *
2939  * -1: This system could not be made better without worsening a higher
2940  * priority node.
2941  *
2942  * 0: All nodes at a higher priority stayed stable or got better and
2943  * this priority level got better.
2944  *
2945  * 1: All systems at a higher priority stayed stable or got better and
2946  * this system is at at min.
2947  *
2948  * Method:
2949  * while all constraints at this level are not solved:
2950  * try to solve the selected constraint
2951  * if joint changed and this priority level got better then
2952  * result = system_solve(current_priority - 1);
2953  * else if (result == worse) then
2954  * reject this joint change
2955  * else
2956  * mark this constraint as "solved"
2957  * fi
2958  * endwhile
2959  */
2960 static int
2961 system_solve(struct ged *gedp, int pri, double delta, double epsilon)
2962 {
2963 #define SOLVE_MAX_PRIORITY 100
2964  double pri_weights[SOLVE_MAX_PRIORITY+1];
2965  double new_weights[SOLVE_MAX_PRIORITY+1];
2966  double new_eval;
2967  int i;
2968  int j;
2969  struct hold *hp;
2970  struct jointH *jh;
2971  struct solve_stack *ssp;
2972  struct hold *test_hold = NULL;
2973 
2974  if (pri < 0)
2975  return 1;
2976 
2977  for (i=0; i<=pri; i++)
2978  pri_weights[i]=0.0;
2979 
2980  for (BU_LIST_FOR(hp, hold, &hold_head)) {
2981  hp->eval = hold_eval(gedp, hp);
2982  pri_weights[hp->priority] += hp->eval;
2983  }
2984 
2985  if (J_DEBUG & DEBUG_J_SYSTEM) {
2986  for (i=0; i <= pri; i++) {
2987  if (pri_weights[i] > 0.0) {
2988  bu_vls_printf(gedp->ged_result_str, "system_solve: priority %d has system weight of %g.\n",
2989  i, pri_weights[i]);
2990  }
2991  }
2992  }
2993 
2994  /* sort constraints by priority then weight from the evaluation
2995  * we just did.
2996  */
2997  for (hp=(struct hold *)hold_head.forw; hp->l.forw != &hold_head;) {
2998  struct hold *tmp;
2999  tmp = (struct hold *)hp->l.forw;
3000 
3001  if ((tmp->priority < hp->priority) ||
3002  ((tmp->priority == hp->priority) &&
3003  (tmp->eval > hp->eval))) {
3004  BU_LIST_DEQUEUE(&tmp->l);
3005  BU_LIST_INSERT(&hp->l, &tmp->l);
3006  if (tmp->l.back != &hold_head) {
3007  hp = (struct hold*)tmp->l.back;
3008  }
3009  } else {
3010  hp = (struct hold*)hp->l.forw;
3011  }
3012  }
3013 Middle:
3014  /* now we find the constraint(s) we will be working with. */
3015  for (; pri>=0 && pri_weights[pri] < epsilon; pri--)
3016  ;
3017  if (pri <0) {
3018  if (J_DEBUG & DEBUG_J_SYSTEM) {
3019  bu_vls_printf(gedp->ged_result_str, "system_solve: returning 1\n");
3020  }
3021  return 1; /* solved */
3022  }
3023  for (BU_LIST_FOR(hp, hold, &hold_head)) {
3024  if (hp->priority != pri)
3025  continue;
3026  if (hp->flag & HOLD_FLAG_TRIED)
3027  continue;
3028  if (part_solve(gedp, hp, delta, epsilon)==0)
3029  continue;
3030  test_hold = hp;
3031  break;
3032  }
3033 
3034  /* Now check to see if a) anything happened, b) that it was good
3035  * for the entire system.
3036  */
3037  if (hp==(struct hold*)&hold_head) {
3038 
3039  /* There was nothing we could do at this level. Try again at
3040  * a higher level.
3041  */
3042  pri--;
3043  goto Middle;
3044  }
3045 
3046  /* We did something so lets re-evaluated and see if it got any
3047  * better at THIS level only. breaking things of lower priority
3048  * does not bother us. If things got worse at a lower priority
3049  * we'll know that in a little bit.
3050  */
3051  new_eval = 0.0;
3052  for (BU_LIST_FOR(hp, hold, &hold_head)) {
3053  if (hp->priority != pri)
3054  continue;
3055  new_eval += hold_eval(gedp, hp);
3056  }
3057  if (J_DEBUG & DEBUG_J_SYSTEM) {
3058  bu_vls_printf(gedp->ged_result_str, "system_solve: old eval = %g, new eval = %g\n",
3059  pri_weights[pri], new_eval);
3060  }
3061 
3062  /* if the new evaluation is worse than the original, back off this
3063  * modification, set the constraint such that this freedom of this
3064  * joint won't be used next time through part_solve.
3065  */
3066  if (new_eval > pri_weights[pri]+epsilon) {
3067 
3068  /* now we see if there is anything we can do with this
3069  * constraint.
3070  */
3071  ssp = (struct solve_stack *) solve_head.forw;
3072 
3073  i = (2<<6) - 1; /* Six degrees of freedom */
3074  if (test_hold) {
3075  /* make sure we've got test_hold */
3076  for (BU_LIST_FOR(jh, jointH, &test_hold->j_head)) {
3077  if (ssp->jp != jh->p) {
3078  i &= jh->flag;
3079  continue;
3080  }
3081  jh->flag |= (1 << ssp->freedom);
3082  i &= jh->flag;
3083  }
3084  if (i == ((2<<6)-1)) {
3085  /* All joints, all freedoms */
3086  test_hold->flag |= HOLD_FLAG_TRIED;
3087  }
3088  }
3089  reject_move(gedp);
3090  goto Middle;
3091  }
3092 
3093  /*
3094  * OK, we've got a constraint that makes this priority system
3095  * better, now we've got to make sure all the constraints below
3096  * this are better or solve also.
3097  */
3098  ssp = (struct solve_stack *) solve_head.forw;
3099  for (j=0; (i = system_solve(gedp, pri-1, delta, epsilon)) == 0; j++)
3100  ;
3101 
3102  /*
3103  * All constraints at a higher priority are stabilized.
3104  *
3105  * If system_solve returns "1" then every thing higher is happy
3106  * and we only have to worry about his one. If -1 was returned
3107  * then all higher priorities have to be check to make sure they
3108  * did not get any worse.
3109  */
3110  for (j=0; j<=pri; j++)
3111  new_weights[j] = 0.0;
3112  for (BU_LIST_FOR(hp, hold, &hold_head)) {
3113  new_weights[hp->priority] += hold_eval(gedp, hp);
3114  }
3115  for (j=0; j<=pri; j++) {
3116  if (new_weights[j] > pri_weights[j] + epsilon) {
3117  break;
3118  }
3119  }
3120 
3121  /* if j <= pri, then that priority got worse. Since it is worse,
3122  * we need to clean up what's been done before and exit out of
3123  * here.
3124  */
3125  if (j <= pri) {
3126  while (ssp != (struct solve_stack *) solve_head.forw) {
3127  reject_move(gedp);
3128  }
3129  i = (2 << 6) - 1;
3130  if (test_hold) {
3131  /* again, make sure we've got test_hold */
3132  for (BU_LIST_FOR(jh, jointH, &test_hold->j_head)) {
3133  if (ssp->jp != jh->p) {
3134  i &= jh->flag;
3135  continue;
3136  }
3137  jh->flag |= (1 << ssp->freedom);
3138  i &= jh->flag;
3139  }
3140  if (i == ((2<<6) - 1)) {
3141  test_hold->flag |= HOLD_FLAG_TRIED;
3142  }
3143  }
3144  reject_move(gedp);
3145  if (J_DEBUG & DEBUG_J_SYSTEM) {
3146  bu_vls_printf(gedp->ged_result_str, "system_solve: returning -1\n");
3147  }
3148  return -1;
3149  }
3150  if (J_DEBUG & DEBUG_J_SYSTEM) {
3151  bu_vls_printf(gedp->ged_result_str, "system_solve: new_weights[%d] = %g, returning ", pri,
3152  new_weights[pri]);
3153  }
3154  if (new_weights[pri] < epsilon) {
3155  if (J_DEBUG & DEBUG_J_SYSTEM) {
3156  bu_vls_printf(gedp->ged_result_str, "1\n");
3157  }
3158  return 1;
3159  }
3160  if (J_DEBUG & DEBUG_J_SYSTEM) {
3161  bu_vls_printf(gedp->ged_result_str, "0\n"); }
3162  return 0;
3163 
3164 }
3165 
3166 
3167 static int
3168 joint_solve(struct ged *gedp, int argc, char *argv[])
3169 {
3170  struct hold *hp;
3171  int loops, count;
3172  double delta, epsilon;
3173  int domesh;
3174  int found;
3175  char **myargv;
3176  int myargc;
3177  int result = 0;
3178 
3179  /* because this routine calls "mesh" in the middle, the command
3180  * arguments can be reused. We cons up a new argv vector and copy
3181  * all of the arguments before we do any processing.
3182  */
3183  myargc = argc;
3184  myargv = (char **)bu_malloc(sizeof(char *)*argc, "param pointers");
3185 
3186  for (count=0; count<myargc; count++) {
3187  myargv[count] = (char *)bu_malloc(strlen(argv[count])+1, "param");
3188  bu_strlcpy(myargv[count], argv[count], strlen(argv[count])+1);
3189  }
3190 
3191  argv=myargv;
3192  /* argc = myargc; */
3193 
3194  /* these are the defaults. Domesh will change to not at a later
3195  * time.
3196  */
3197  loops = 1000;
3198  delta = 16.0;
3199  epsilon = 0.1;
3200  domesh = 1;
3201 
3202  /* reset bu_getopt. */
3203  bu_optind=1;
3204  while ((count=bu_getopt(argc, (char * const *)argv, "l:e:d:m")) != -1) {
3205  switch (count) {
3206  case 'l': loops = atoi(bu_optarg);break;
3207  case 'e': epsilon = atof(bu_optarg);break;
3208  case 'd': delta = atof(bu_optarg);break;
3209  case 'm': domesh = 1-domesh;
3210  }
3211  }
3212 
3213  /* skip the command and any options that bu_getopt ate. */
3214  argc -= bu_optind;
3215  argv += bu_optind;
3216 
3217  for (BU_LIST_FOR(hp, hold, &hold_head))
3218  hold_clear_flags(hp);
3219 
3220  found = -1;
3221  while (argc) {
3222  found = 0;
3223  for (BU_LIST_FOR(hp, hold, &hold_head)) {
3224  if (BU_STR_EQUAL(*argv, hp->name)) {
3225  found = 1;
3226  for (count=0; count<loops; count++) {
3227  if (!part_solve(gedp, hp, delta, epsilon))
3228  break;
3229  if (domesh) {
3230  joint_mesh(gedp, 0, 0);
3231  /* refreshing the screen */
3234  }
3235  joint_clear();
3236  }
3237 
3238  {
3239  bu_vls_printf(gedp->ged_result_str, "joint solve: finished %d loops of %s.\n",
3240  count, hp->name);
3241  }
3242 
3243  continue;
3244  }
3245  }
3246  if (!found) {
3247  bu_vls_printf(gedp->ged_result_str, "joint solve: constraint %s not found.\n", *argv);
3248  }
3249  --argc;
3250  ++argv;
3251  }
3252 
3253  for (count=0; count<myargc; count++) {
3254  bu_free(myargv[count], "params");
3255  }
3256  bu_free((void *)myargv, "param pointers");
3257 
3258  if (found >= 0)
3259  return GED_ERROR;
3260 
3261  /* solve the whole system of constraints. */
3262 
3263  joint_clear(); /* make sure the system is empty. */
3264 
3265  for (count=0; count < loops; count++) {
3266 
3267  /* Clear all constraint flags. */
3268  for (BU_LIST_FOR(hp, hold, &hold_head)) {
3269  struct jointH *jh;
3270  hp->flag &= ~HOLD_FLAG_TRIED;
3271  hp->eval = hold_eval(gedp, hp);
3272  for (BU_LIST_FOR(jh, jointH, &hp->j_head)) {
3273  jh->flag = 0;
3274  }
3275  }
3276  result = system_solve(gedp, 0, delta, epsilon);
3277  if (result == 1) {
3278  break;
3279  } else if (result == -1) {
3280  delta /= 2.0;
3281  if (J_DEBUG & DEBUG_J_SYSTEM) {
3282  bu_vls_printf(gedp->ged_result_str, "joint solve: splitting delta (%g)\n",
3283  delta);
3284  }
3285  if (delta < epsilon)
3286  break;
3287  }
3288  joint_clear();
3289  if (domesh) {
3290  joint_mesh(gedp, 0, 0);
3291 
3292  /* refreshing the screen */
3295  }
3296  }
3297  if (count < loops) {
3298  for (count = 0; count < loops; count++) {
3299 
3300  /* Clear all constraint flags. */
3301  for (BU_LIST_FOR(hp, hold, &hold_head)) {
3302  struct jointH *jh;
3303  hp->flag &= ~HOLD_FLAG_TRIED;
3304  hp->eval = hold_eval(gedp, hp);
3305  for (BU_LIST_FOR(jh, jointH, &hp->j_head)) {
3306  jh->flag = 0;
3307  }
3308  }
3309  result = system_solve(gedp, SOLVE_MAX_PRIORITY, delta, epsilon);
3310  if (result == 1) {
3311  break;
3312  } else if (result == -1) {
3313  delta /= 2.0;
3314  if (J_DEBUG & DEBUG_J_SYSTEM) {
3315  bu_vls_printf(gedp->ged_result_str, "joint solve: splitting delta (%g)\n",
3316  delta);
3317  }
3318  if (delta < epsilon)
3319  break;
3320  }
3321  joint_clear();
3322  if (domesh) {
3323  joint_mesh(gedp, 0, 0);
3324 
3325  /* refreshing the screen */
3328  }
3329  }
3330  }
3331  if (result == 1) {
3332  bu_vls_printf(gedp->ged_result_str, "joint solve: system has converged to a result (after %d iterations).\n", count+1);
3333  } else if (result == 0) {
3334  bu_vls_printf(gedp->ged_result_str, "joint solve: system has not converged after %d iterations.\n", count+1);
3335  } else {
3336  bu_vls_printf(gedp->ged_result_str, "joint solve: system will not converge.\n");
3337  }
3338  joint_clear();
3339  if (domesh) {
3340  joint_mesh(gedp, 0, 0);
3341 
3342  /* refreshing the screen */
3345  }
3346  return GED_OK;
3347 }
3348 
3349 
3350 static int
3351 joint_hold(struct ged *gedp, int argc, const char *argv[])
3352 {
3353  struct hold *hp;
3354  ++argv;
3355  --argc;
3356  for (BU_LIST_FOR(hp, hold, &hold_head)) {
3357  if (argc) {
3358  int i;
3359  for (i=0; i<argc; i++) {
3360  if (BU_STR_EQUAL(argv[i], hp->name))
3361  break;
3362  }
3363  if (i>=argc)
3364  continue;
3365  }
3366  hold_clear_flags(hp);
3367  print_hold(gedp, hp);
3368  }
3369  return GED_OK;
3370 }
3371 
3372 
3373 static int
3374 joint_list(struct ged *gedp, int UNUSED(argc), const char *UNUSED(argv[]))
3375 {
3376  struct joint *jp;
3377 
3378  for (BU_LIST_FOR(jp, joint, &joint_head)) {
3379  vls_col_item(gedp->ged_result_str, jp->name);
3380  }
3381  vls_col_eol(gedp->ged_result_str);
3382 
3383  return GED_OK;
3384 }
3385 
3386 
3387 static int
3388 joint_move(struct ged *gedp, int argc, const char *argv[])
3389 {
3390  struct joint *jp;
3391  int i;
3392  double tmp;
3393 
3394  if (gedp->ged_wdbp->dbip == DBI_NULL)
3395  return GED_OK;
3396 
3397  /* find the joint. */
3398 
3399  argv++;
3400  argc--;
3401 
3402  jp = joint_lookup(*argv);
3403  if (!jp) {
3404  bu_vls_printf(gedp->ged_result_str, "joint move: %s not found\n", *argv);
3405  return GED_ERROR;
3406  }
3407 
3408  argv++;
3409  argc--;
3410  for (i=0; i<3 && argc; i++) {
3411  if (jp->rots[i].upper < jp->rots[i].lower)
3412  break;
3413 
3414  /* Eat a parameter, translate it from degrees to rads. */
3415 
3416  if ((*argv)[0] == '-' && (*argv)[1] == '\0') {
3417  ++argv;
3418  --argc;
3419  continue;
3420  }
3421  tmp = atof(*argv);
3422  if (J_DEBUG & DEBUG_J_MOVE) {
3423  bu_vls_printf(gedp->ged_result_str, "joint move: %s rotate (%g %g %g) %g degrees.\n",
3424  jp->name, jp->rots[i].quat[X],
3425  jp->rots[i].quat[Y], jp->rots[i].quat[Z],
3426  tmp);
3427  bu_vls_printf(gedp->ged_result_str, "joint move: %s lower=%g, upper=%g\n",
3428  jp->name, jp->rots[i].lower, jp->rots[i].upper);
3429  }
3430  if (tmp <= jp->rots[i].upper && tmp >= jp->rots[i].lower) {
3431  jp->rots[i].current = tmp;
3432  } else {
3433  bu_vls_printf(gedp->ged_result_str, "joint move: %s, rotation %d, %s out of range.\n",
3434  jp->name, i, *argv);
3435  }
3436  argv++;
3437  argc--;
3438  }
3439  for (i=0; i<3 && argc; i++) {
3440  if (jp->dirs[i].upper < jp->dirs[i].lower)
3441  break;
3442 
3443  /* eat a parameter. */
3444 
3445  if ((*argv)[0] == '-' && (*argv)[1] == '\0') {
3446  ++argv;
3447  --argc;
3448  continue;
3449  }
3450  tmp = atof(*argv) * gedp->ged_wdbp->dbip->dbi_local2base;
3451  if (tmp <= jp->dirs[i].upper &&
3452  tmp >= jp->dirs[i].lower) {
3453  jp->dirs[i].current = tmp;
3454  } else {
3455  bu_vls_printf(gedp->ged_result_str, "joint move: %s, vector %d, %s out of range.\n",
3456  jp->name, i, *argv);
3457  }
3458  }
3459  joint_adjust(gedp, jp);
3460  joint_mesh(gedp, 0, 0);
3461 
3462  /* refreshing the screen */
3465 
3466  return GED_OK;
3467 }
3468 
3469 
3470 /**
3471  * Check a table for the command, check for the correct minimum and
3472  * maximum number of arguments, and pass control to the proper
3473  * function. If the number of arguments is incorrect, print out a
3474  * short help message.
3475  */
3476 static int
3477 joint_cmd(struct ged *gedp,
3478  int argc,
3479  const char *argv[],
3480  struct funtab functions[])
3481 {
3482  struct funtab *ftp;
3483 
3484  if (argc == 0) {
3485  bu_vls_printf(gedp->ged_result_str, "Usage: joint {command} [command_options]\n\n");
3486  (void)joint_usage(gedp, argc, argv, functions);
3487  return GED_HELP; /* No command entered */
3488  }
3489 
3490  for (ftp = &functions[1]; ftp->ft_name; ftp++) {
3491  if (!BU_STR_EQUAL(ftp->ft_name, argv[0]))
3492  continue;
3493  /* We have a match */
3494  if ((ftp->ft_min <= argc) && (ftp->ft_max < 0 || argc <= ftp->ft_max)) {
3495  /* Input has the right number of args. Call function
3496  * listed in table, with main(argc, argv) style args
3497  */
3498 
3499  switch (ftp->ft_func(gedp, argc, argv)) {
3500  case GED_OK:
3501  return GED_OK;
3502  case GED_ERROR:
3503  return GED_ERROR;
3504  default:
3505  bu_vls_printf(gedp->ged_result_str, "joint_cmd: Invalid return from %s\n", ftp->ft_name);
3506  return GED_ERROR;
3507  }
3508  }
3509 
3510  bu_vls_printf(gedp->ged_result_str, "Usage: %s%s %s\n\t(%s)\n", functions[0].ft_name, ftp->ft_name, ftp->ft_parms, ftp->ft_comment);
3511  return GED_ERROR;
3512  }
3513 
3514  bu_vls_printf(gedp->ged_result_str, "%s%s : no such command, type '%s?' for help\n", functions[0].ft_name, argv[0], functions[0].ft_name);
3515  return GED_ERROR;
3516 }
3517 
3518 
3519 int
3520 ged_joint(struct ged *gedp, int argc, const char *argv[])
3521 {
3522  int status;
3523 
3525  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
3526 
3527  /* initialize result */
3528  bu_vls_trunc(gedp->ged_result_str, 0);
3529 
3530  /* Skip the command name */
3531  argc--;
3532  argv++;
3533 
3534  status = joint_cmd(gedp, argc, argv, &joint_tab[0]);
3535 
3536  if (status == GED_OK)
3537  return GED_OK;
3538 
3539  return GED_ERROR;
3540 }
3541 
3542 
3543 struct funtab joint_tab[] = {
3544  {"joint ", "", "Joint command table",
3545  0, 0, 0, FALSE},
3546  {"?", "[commands]", "summary of available joint commands",
3547  joint_help_commands, 0, FUNTAB_UNLIMITED, FALSE},
3548  {"accept", "[joints]", "accept a series of moves",
3549  joint_accept, 1, FUNTAB_UNLIMITED, FALSE},
3550  {"debug", "[hex code]", "Show/set debugging bit vector for joints",
3551  joint_debug, 1, 2, FALSE},
3552  {"help", "[commands]", "give usage message for given joint commands",
3553  joint_help, 0, FUNTAB_UNLIMITED, FALSE},
3554  {"holds", "[names]", "list constraints",
3555  joint_hold, 1, FUNTAB_UNLIMITED, FALSE},
3556  {"list", "[names]", "list joints.",
3557  joint_list, 1, FUNTAB_UNLIMITED, FALSE},
3558  {"load", "file_name", "load a joint/constraint file",
3559  joint_load, 2, FUNTAB_UNLIMITED, FALSE},
3560  {"mesh", "", "Build the grip mesh",
3561  joint_mesh, 0, 1, FALSE},
3562  {"move", "joint_name p1 [p2...p6]", "Manual adjust a joint",
3563  joint_move, 3, 8, FALSE},
3564  {"reject", "[joint_names]", "reject joint motions",
3565  joint_reject, 1, FUNTAB_UNLIMITED, FALSE},
3566  {"save", "file_name", "Save joints and constraints to disk",
3567  joint_save, 2, 2, FALSE},
3568  {"solve", "constraint", "Solve a or all constraints",
3569  joint_solve, 1, FUNTAB_UNLIMITED, FALSE},
3570  {"unload", "", "Unload any joint/constraints that have been loaded",
3571  joint_unload, 1, 1, FALSE},
3572  {NULL, NULL, NULL,
3573  NULL, 0, 0, FALSE}
3574 };
3575 
3576 
3577 /*
3578  * Local Variables:
3579  * mode: C
3580  * tab-width: 8
3581  * indent-tabs-mode: t
3582  * c-file-style: "stroustrup"
3583  * End:
3584  * ex: shiftwidth=4 tabstop=8
3585  */
Definition: joint.h:118
void db_free_anim(struct db_i *dbip)
Definition: db_anim.c:223
HIDDEN int sign(double val)
Definition: brep.cpp:1145
quat_t quat
Definition: joint.h:101
int an_type
AN_MATRIX, AN_COLOR...
Definition: raytrace.h:1340
#define GED_OK
Definition: ged.h:55
char * d_namep
pointer to name string
Definition: raytrace.h:859
int arc_loc
Definition: joint.h:134
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
#define SYM_OP_GROUP
Definition: joint.c:770
#define FALSE
#define KEY_JOINT
Definition: joint.c:695
void db_add_node_to_full_path(struct db_full_path *pp, struct directory *dp)
Definition: db_fullpath.c:54
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
double upper
Definition: joint.h:103
int rt_db_get_internal(struct rt_db_internal *ip, const struct directory *dp, const struct db_i *dbip, const mat_t mat, struct resource *resp)
Definition: dir.c:76
#define BU_LEX_DOUBLE
Definition: log.h:505
HIDDEN union tree * mesh_end_region(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data)
Definition: joint.c:197
void rt_vlblock_free(struct bn_vlblock *vbp)
Definition: vlist.c:78
#define BU_AVS_MAGIC
Definition: magic.h:46
struct bu_list joint_head
Definition: joint.c:78
int tok_val
Definition: log.h:526
struct bu_list l
Definition: joint.h:164
int flag
Definition: joint.h:135
int vertex_number
Definition: joint.h:148
struct bu_lex_t_id t_id
Definition: log.h:523
Definition: list.h:118
#define ARC_ARC
Definition: joint.h:96
#define BU_LIST_LAST(structure, hp)
Definition: list.h:306
#define KEY_START
Definition: joint.c:709
size_t fp_len
Definition: db_fullpath.h:44
#define HOLD_PT_GOOD
Definition: joint.h:156
#define OP_NOP
Leaf with no effect.
Definition: raytrace.h:1132
struct arc path
Definition: joint.h:160
struct bu_lex_t_int t_int
Definition: log.h:520
char * value
Definition: log.h:514
Definition: ged.h:338
#define BU_LEX_NUMBER
Definition: log.h:517
int(* ft_func)()
Definition: joint.h:193
struct db_i * dbip
Definition: raytrace.h:1266
#define ID_FIXED
Definition: joint.c:762
Definition: clone.c:90
struct joint * p
Definition: joint.h:133
struct bu_list l
Definition: joint.c:2588
#define ID_GRIP
Pseudo Solid Grip.
Definition: raytrace.h:480
#define ANM_RMUL
Right (leaf side) mul.
Definition: raytrace.h:1319
#define VSETALL(a, s)
Definition: color.c:54
#define UNIT_FEET
Definition: joint.c:747
#define ID_JOINT
Pseudo Solid/Region Joint.
Definition: raytrace.h:481
double lower
Definition: joint.h:111
#define ANIM_MAT
double accepted
Definition: joint.h:105
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define BU_LIST_IS_EMPTY(hp)
Definition: list.h:295
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
void bu_vls_nibble(struct bu_vls *vp, off_t len)
Definition: vls.c:217
#define KEY_PATH
Definition: joint.c:710
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
void * ged_refresh_clientdata
client data passed to refresh handler
Definition: ged.h:366
#define KEY_CUR
Definition: joint.c:704
char * name
Definition: joint.h:165
#define UNIT_CM
Definition: joint.c:748
struct bu_list head
Definition: joint.c:67
struct bu_list l
Definition: joint.h:132
struct rt_wdb * ged_wdbp
Definition: ged.h:340
double current
Definition: joint.h:113
char * bu_optarg
Definition: globals.c:91
#define DEBUG_J_PARSE
Definition: joint.c:48
Header file for the BRL-CAD common definitions.
#define BU_LIST_POP(structure, hp, p)
Definition: list.h:249
int bu_optind
Definition: globals.c:89
#define DB_FULL_PATH_CUR_DIR(_pp)
Definition: db_fullpath.h:51
#define BU_LIST_APPEND(old, new)
Definition: list.h:197
int value
Definition: log.h:508
#define KEY_TRANS
Definition: joint.c:699
char * ft_parms
Definition: joint.h:191
struct bn_vlblock * rt_vlblock_init(void)
Definition: vlist.c:71
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
void db_full_path_init(struct db_full_path *pathp)
Definition: db_fullpath.c:40
#define MAX_FASTF
Definition: defines.h:340
struct bu_list l
Definition: joint.c:60
struct bu_list * gd_headDisplay
head of display list
Definition: ged.h:307
#define GED_ERROR
Definition: ged.h:61
#define HIDDEN
Definition: common.h:86
#define RT_TREE_INIT(_p)
Definition: raytrace.h:1189
struct f2 f2
token
Definition: exists.c:65
int org_last
Definition: joint.h:90
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
struct direct dirs[3]
Definition: joint.h:126
void bu_vls_printb(struct bu_vls *vls, const char *s, unsigned long v, const char *bits)
#define KEY_LIMIT
Definition: joint.c:701
#define MAGIC_A_JOINT
Definition: joint.c:70
struct arc arc
Definition: joint.h:150
#define MAGIC_A_GRIP
Definition: joint.c:64
#define KEY_POINT
Definition: joint.c:714
#define KEY_CON
Definition: joint.c:696
struct bu_list artic_head
Definition: joint.c:72
#define RT_AN_MATRIX
Matrix animation.
Definition: raytrace.h:1348
int flag
Definition: joint.h:174
if(share_geom)
Definition: nmg_mod.c:3829
char * name
Definition: joint.h:121
struct bu_list * rt_vlblock_find(struct bn_vlblock *vbp, int r, int g, int b)
Definition: vlist.c:98
#define DB_FULL_PATH_GET(_pp, _i)
Definition: db_fullpath.h:55
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
Definition: color.c:49
HIDDEN union tree * mesh_leaf(struct db_tree_state *tsp, const struct db_full_path *pathp, struct rt_db_internal *ip, void *client_data)
Definition: joint.c:141
#define SYM_EQ
Definition: joint.c:774
#define DEBUG_J_MESH
Definition: joint.c:42
int flag
Definition: joint.h:152
#define KEY_INF
Definition: joint.c:716
void vls_col_eol(struct bu_vls *str)
Definition: columns.c:73
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
char * dbi_title
title from IDENT rec
Definition: raytrace.h:809
int anm_op
ANM_RSTACK, ANM_RARC...
Definition: raytrace.h:1313
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
#define SYM_PLUS
Definition: joint.c:779
void bn_mat_print(const char *title, const mat_t m)
Definition: mat.c:81
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#define SYM_CL_PT
Definition: joint.c:773
#define C
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define ANIMATE_MAGIC
Definition: magic.h:196
struct anim_mat anu_m
Definition: raytrace.h:1342
#define RT_DBTS_MAGIC
Definition: magic.h:157
#define KEY_EXCEPT
Definition: joint.c:715
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
#define TREE_NULL
Definition: raytrace.h:1181
void db_free_full_path(struct db_full_path *pp)
Definition: db_fullpath.c:473
struct bu_list * back
"back", "last"
Definition: list.h:121
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
struct f1 f1
#define DEBUG_J_EVAL
Definition: joint.c:46
#define SQRT_SMALL_FASTF
Definition: defines.h:346
#define SYM_MINUS
Definition: joint.c:778
#define ARC_UNSET
Definition: joint.h:94
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
#define SYM_OP_PT
Definition: joint.c:772
HIDDEN int helpcomm(struct ged *gedp, int argc, const char *argv[], struct funtab *functions)
Definition: joint.c:333
void * bu_realloc(void *ptr, size_t siz, const char *str)
int freedom
Definition: joint.c:2590
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
struct hold_point effector
Definition: joint.h:170
Definition: joint.h:84
char ** original
Definition: joint.h:89
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
#define KEY_UP
Definition: joint.c:702
int ft_min
Definition: joint.h:194
#define ID_SPH
Sphere.
Definition: raytrace.h:468
#define BU_LEX_IDENT
Definition: log.h:516
#define DEBUG_J_SYSTEM
Definition: joint.c:47
struct directory ** fp_names
array of dir pointers
Definition: db_fullpath.h:46
char * db_path_to_string(const struct db_full_path *pp)
Definition: db_fullpath.c:191
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define SYM_CL_GROUP
Definition: joint.c:771
struct bu_vls * ged_result_str
Definition: ged.h:357
uint32_t magic
Magic # for mem id/check.
Definition: list.h:119
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
#define SOLVE_MAX_PRIORITY
double dbi_base2local
unit conversion factors
Definition: raytrace.h:808
#define UNIT_INCH
Definition: joint.c:745
struct bu_list l
Definition: joint.h:119
#define BU_LEX_KEYWORD
Definition: log.h:511
#define SYM_END
Definition: joint.c:776
int uses
Definition: joint.h:120
int db_add_anim(struct db_i *dbip, struct animate *anp, int root)
#define ARC_BOTH
Definition: joint.h:98
struct ged_drawable * ged_gdp
Definition: ged.h:360
Definition: joint.h:189
uint32_t magic
magic number
Definition: raytrace.h:1337
void(* ged_refresh_handler)(void *)
function for handling refresh requests
Definition: ged.h:367
char * ft_name
Definition: joint.h:190
int bu_vls_gets(struct bu_vls *vp, FILE *fp)
Definition: vls.c:621
struct arc path
Definition: joint.h:122
vect_t unitvec
Definition: joint.h:110
int ged_joint(struct ged *gedp, int argc, const char *argv[])
Definition: joint.c:3520
void _ged_cvt_vlblock_to_solids(struct ged *gedp, struct bn_vlblock *vbp, const char *name, int copy)
Definition: draw.c:554
struct db_full_path an_path
(sub)-path pattern
Definition: raytrace.h:1339
#define KEY_PRI
Definition: joint.c:712
#define BU_LIST_PUSH(hp, p)
Definition: list.h:246
struct joint * joint
Definition: joint.c:68
#define RT_CK_FULL_PATH(_p)
Definition: db_fullpath.h:59
int arc_last
Definition: joint.h:88
#define DEBUG_J_MOVE
Definition: joint.c:44
double accepted
Definition: joint.h:115
#define KEY_UNITS
Definition: joint.c:707
int type
Definition: joint.h:145
double value
Definition: log.h:503
double lower
Definition: joint.h:102
#define BU_LIST_INIT(_hp)
Definition: list.h:148
#define DEBUG_J_LOAD
Definition: joint.c:43
void * idb_ptr
Definition: raytrace.h:195
#define KEY_EFF
Definition: joint.c:713
#define DEBUG_J_LEX
Definition: joint.c:49
#define MAGIC_JOINT_STRUCT
Definition: joint.h:130
struct bu_list solve_head
Definition: joint.c:2595
#define KEY_DIR
Definition: joint.c:706
#define REGION_NON_FASTGEN
Definition: raytrace.h:553
int priority
Definition: joint.h:173
#define HOLD_FLAG_TRIED
Definition: joint.h:177
struct arc exclude
Definition: joint.h:161
struct bu_list l
Definition: joint.h:85
#define MAGIC_JOINT_HANDLE
Definition: joint.h:137
#define DBI_NULL
Definition: raytrace.h:827
#define UNIT_METER
Definition: joint.c:746
struct j_set_desc j_set
Definition: joint.h:167
char ** arc
Definition: joint.h:87
struct bu_list j_head
Definition: joint.h:169
struct hold_point objective
Definition: joint.h:171
#define ARC_LIST
Definition: joint.h:97
#define UNIT_MM
Definition: joint.c:749
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
HIDDEN void text(struct human_data_t *dude)
Definition: human.c:1882
#define LOOKUP_NOISY
Definition: raytrace.h:892
void dl_set_iflag(struct bu_list *hdlp, int iflag)
double eval
Definition: joint.h:175
char * joint
Definition: joint.h:168
#define KEY_LOW
Definition: joint.c:703
double oldval
Definition: joint.c:2591
struct joint * findjoint(struct ged *gedp, const struct db_full_path *pathp)
Definition: joint.c:91
#define GED_HELP
Definition: ged.h:62
void vls_col_item(struct bu_vls *str, const char *cp)
Definition: columns.c:45
#define DEBUG_J_SOLVE
Definition: joint.c:45
#define KEY_ARC
Definition: joint.c:697
int value
Definition: log.h:498
vect_t vert
Definition: joint.c:61
struct rotation rots[3]
Definition: joint.h:125
int ft_max
Definition: joint.h:195
#define KEY_VERTEX
Definition: joint.c:717
#define HOLD_POINT_TO_STRING_LEN
void quat_quat2mat(mat_t mat, const quat_t quat)
Convert Quaternion to Matrix.
struct bu_lex_t_dbl t_dbl
Definition: log.h:521
Definition: color.c:51
struct db_full_path path
Definition: joint.h:151
#define MAGIC_HOLD_STRUCT
Definition: joint.h:185
double weight
Definition: joint.h:172
struct directory * dir
Definition: joint.c:62
char * ft_comment
Definition: joint.h:192
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
vect_t point
Definition: joint.h:147
double newval
Definition: joint.c:2592
int type
Definition: log.h:519
double dbi_local2base
local2mm
Definition: raytrace.h:807
int type
Definition: joint.h:86
#define OP_SOLID
Leaf: tr_stp -> solid.
Definition: raytrace.h:1126
Definition: joint.h:131
#define KEY_WEIGHT
Definition: joint.c:711
#define KEY_ACC
Definition: joint.c:705
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
struct bu_list hold_head
Definition: joint.c:84
int db_walk_tree(struct db_i *dbip, int argc, const char **argv, int ncpu, const struct db_tree_state *init_state, int(*reg_start_func)(struct db_tree_state *, const struct db_full_path *, const struct rt_comb_internal *, void *client_data), union tree *(*reg_end_func)(struct db_tree_state *, const struct db_full_path *, union tree *, void *client_data), union tree *(*leaf_func)(struct db_tree_state *, const struct db_full_path *, struct rt_db_internal *, void *client_data), void *client_data)
struct bu_lex_t_key t_key
Definition: log.h:522
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
struct bu_list * forw
"forward", "next"
Definition: list.h:120
#define DOWN
Definition: bview.h:42
#define KEY_LOC
Definition: joint.c:698
#define BU_LIST_HEAD_MAGIC
Definition: magic.h:56
#define ARC_PATH
Definition: joint.h:95
#define EPSI
double current
Definition: joint.h:104
double upper
Definition: joint.h:112
Definition: vls.h:56
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
HIDDEN const point_t delta
Definition: sh_prj.c:618
int bu_lex(union bu_lex_token *token, struct bu_vls *rtstr, struct bu_lex_key *keywords, struct bu_lex_key *symbols)
Definition: lex.c:144
#define MAX_OBJ_NAME
Definition: joint.c:54
double fastf_t
Definition: defines.h:300
#define BU_LEX_INT
Definition: log.h:500
#define J_DEBUG_FORMAT
Definition: joint.c:50
int get_token(struct ged *gedp, union bu_lex_token *token, FILE *fip, struct bu_vls *str, struct bu_lex_key *keys, struct bu_lex_key *syms)
Definition: joint.c:827
#define BU_LEX_ANY
Definition: log.h:495
#define FUNTAB_UNLIMITED
Definition: joint.h:187
#define BU_LIST_NEXT(structure, hp)
Definition: list.h:316
union animate::animate_specific an_u
#define BU_LIST_NOT_HEAD(p, hp)
Definition: list.h:324
#define KEY_JOINTS
Definition: joint.c:708
int ged_build_tops(struct ged *gedp, char **start, char **end)
Definition: rt.c:424
#define R
struct bu_list l
Definition: joint.c:66
#define SYM_ARC
Definition: joint.c:775
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
Definition: joint.h:163
#define SYM_COMMA
Definition: joint.c:777
#define GED_REFRESH_CALLBACK_PTR_NULL
Definition: ged.h:81
#define BU_LEX_SYMBOL
Definition: log.h:510
Definition: color.c:50
struct animate * anim
Definition: joint.h:128
struct funtab joint_tab[]
Definition: joint.c:3543
struct joint * jp
Definition: joint.c:2589
int db_path_to_mat(struct db_i *dbip, struct db_full_path *pathp, mat_t mat, int depth, struct resource *resp)
Definition: db_fullpath.c:630
#define KEY_ROT
Definition: joint.c:700
vect_t location
Definition: joint.h:123
char * joint
Definition: joint.h:159
char * string
Definition: log.h:527
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126