BRL-CAD
putmat.c
Go to the documentation of this file.
1 /* P U T M A T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-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/putmat.c
21  *
22  * The putmat command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 
32 #include "./ged_private.h"
33 
34 
35 int
36 ged_getmat(struct ged *gedp, int argc, const char *argv[])
37 {
38  struct directory *dp;
39  struct rt_db_internal intern;
40  struct rt_comb_internal *comb;
41  union tree *tp;
42  struct bu_vls name1 = BU_VLS_INIT_ZERO;
43  struct bu_vls name2 = BU_VLS_INIT_ZERO;
44  static const char *usage = "a/b";
45 
48  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
49 
50  /* initialize result */
51  bu_vls_trunc(gedp->ged_result_str, 0);
52 
53  /* must be wanting help */
54  if (argc == 1) {
55  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
56  return GED_HELP;
57  }
58 
59  if (argc != 2) {
60  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
61  return GED_ERROR;
62  }
63 
64  {
65  const char *begin;
66  const char *first_fs;
67  const char *last_fs;
68  const char *end;
69 
70  /* skip leading slashes */
71  begin = argv[1];
72  while (*begin == '/')
73  ++begin;
74 
75  if (*begin == '\0' ||
76  !(first_fs = strchr(begin, '/')) ||
77  !(last_fs = strrchr(begin, '/')) ||
78  first_fs != last_fs) {
79  bu_vls_printf(gedp->ged_result_str, "%s: bad path specification '%s'", argv[0], argv[1]);
80  return GED_ERROR;
81  }
82 
83  /* Note: At this point first_fs == last_fs */
84 
85  end = strrchr(begin, '\0');
86  if (last_fs == end-1) {
87  bu_vls_printf(gedp->ged_result_str, "%s: bad path specification '%s'", argv[0], argv[1]);
88  return GED_ERROR;
89  }
90  bu_vls_strncpy(&name1, begin, (size_t)(last_fs-begin));
91  bu_vls_strncpy(&name2, last_fs+1, (size_t)(end-last_fs));
92  }
93 
94  if ((dp = db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&name1), LOOKUP_NOISY)) == RT_DIR_NULL) {
95  bu_vls_printf(gedp->ged_result_str, "%s: Warning - %s not found in database.\n", argv[0], bu_vls_addr(&name1));
96  bu_vls_free(&name1);
97  bu_vls_free(&name2);
98  return GED_ERROR;
99  }
100 
101  if (!(dp->d_flags & RT_DIR_COMB)) {
102  bu_vls_printf(gedp->ged_result_str, "%s: Warning - %s not a combination\n", argv[0], bu_vls_addr(&name1));
103  bu_vls_free(&name1);
104  bu_vls_free(&name2);
105  return GED_ERROR;
106  }
107 
108  if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (matp_t)NULL, &rt_uniresource) < 0) {
109  bu_vls_printf(gedp->ged_result_str, "Database read error, aborting");
110  bu_vls_free(&name1);
111  bu_vls_free(&name2);
112  return GED_ERROR;
113  }
114 
115  comb = (struct rt_comb_internal *)intern.idb_ptr;
116  RT_CK_COMB(comb);
117  if (!comb->tree) {
118  bu_vls_printf(gedp->ged_result_str, "%s: empty combination", dp->d_namep);
119  goto fail;
120  }
121 
122  /* Search for first mention of arc */
123  if ((tp = db_find_named_leaf(comb->tree, bu_vls_addr(&name2))) == TREE_NULL) {
125  "Unable to find instance of '%s' in combination '%s', error",
126  bu_vls_addr(&name2), bu_vls_addr(&name1));
127  goto fail;
128  }
129 
130  if (!tp->tr_l.tl_mat) {
131  bu_vls_printf(gedp->ged_result_str, "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1");
132  rt_db_free_internal(&intern);
133 
134  return GED_OK;
135  } else {
136  register int i;
137 
138  for (i = 0; i < 16; i++)
139  bu_vls_printf(gedp->ged_result_str, "%lf ", tp->tr_l.tl_mat[i]);
140 
141  rt_db_free_internal(&intern);
142 
143  return GED_OK;
144  }
145 
146 fail:
147  bu_vls_free(&name1);
148  bu_vls_free(&name2);
149  rt_db_free_internal(&intern);
150  return GED_ERROR;
151 }
152 
153 
154 /*
155  * Replace the matrix on an arc in the database from the command line,
156  * when NOT in an edit state. Used mostly to facilitate writing shell
157  * scripts. There are two valid syntaxes, each of which is
158  * implemented as an appropriate call to f_arced. Commands of the
159  * form:
160  *
161  * putmat a/b m0 m1 ... m15
162  *
163  * are converted to:
164  *
165  * arced a/b matrix rarc m0 m1 ... m15,
166  *
167  * while commands of the form:
168  *
169  * putmat a/b I
170  *
171  * are converted to:
172  *
173  * arced a/b matrix rarc 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1
174  *
175  */
176 int
177 ged_putmat(struct ged *gedp, int argc, const char *argv[])
178 {
179  int result = GED_OK; /* Return code */
180  char *newargv[20+2];
181  struct bu_vls *avp;
182  int got;
183  static const char *usage = "a/b I|m0 m1 ... m15";
184 
187  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
188 
189  /* initialize result */
190  bu_vls_trunc(gedp->ged_result_str, 0);
191 
192  /* must be wanting help */
193  if (argc == 1) {
194  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
195  return GED_HELP;
196  }
197 
198  if (argc == 2)
199  return ged_getmat(gedp, argc, argv);
200 
201  if (argc < 3 || 18 < argc) {
202  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
203  return GED_ERROR;
204  }
205 
206  if (!strchr(argv[1], '/')) {
207  bu_vls_printf(gedp->ged_result_str, "%s: bad path spec '%s'\n", argv[0], argv[1]);
208  return GED_ERROR;
209  }
210  switch (argc) {
211  case 18:
212  avp = bu_vls_vlsinit();
213  bu_vls_from_argv(avp, 16, (const char **)argv + 2);
214  break;
215  case 3:
216  if ((argv[2][0] == 'I') && (argv[2][1] == '\0')) {
217  avp = bu_vls_vlsinit();
218  bu_vls_printf(avp, "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ");
219  break;
220  }
221  /* Sometimes the matrix is sent through Tcl as one long string.
222  * Copy it so we can crack it, below.
223  */
224  avp = bu_vls_vlsinit();
225  bu_vls_strcat(avp, argv[2]);
226  break;
227  default:
228  bu_vls_printf(gedp->ged_result_str, "%s: error in matrix specification (wrong number of args)\n", argv[0]);
229  return GED_ERROR;
230  }
231  newargv[0] = "arced";
232  newargv[1] = (char *)argv[1];
233  newargv[2] = "matrix";
234  newargv[3] = "rarc";
235 
236  got = bu_argv_from_string(&newargv[4], 16, bu_vls_addr(avp));
237  if (got != 16) {
238  bu_vls_printf(gedp->ged_result_str, "%s: %s:%d: bad matrix, only got %d elements\n",
239  argv[0], __FILE__, __LINE__, got);
240  result = GED_ERROR;
241  }
242 
243  if (result != GED_ERROR)
244  result = ged_arced(gedp, 20, (const char **)newargv);
245 
246  bu_vls_vlsfree(avp);
247  return result;
248 }
249 
250 
251 /*
252  * Local Variables:
253  * tab-width: 8
254  * mode: C
255  * indent-tabs-mode: t
256  * c-file-style: "stroustrup"
257  * End:
258  * ex: shiftwidth=4 tabstop=8
259  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
char * d_namep
pointer to name string
Definition: raytrace.h:859
int ged_putmat(struct ged *gedp, int argc, const char *argv[])
Definition: putmat.c:177
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
union tree * db_find_named_leaf(union tree *tp, const char *cp)
Definition: db_tree.c:393
void bu_vls_vlsfree(struct bu_vls *vp)
Definition: vls.c:263
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
#define RT_CK_COMB(_p)
Definition: raytrace.h:955
void bu_vls_strncpy(struct bu_vls *vp, const char *s, size_t n)
Definition: vls.c:339
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
#define GED_ERROR
Definition: ged.h:61
char * strchr(const char *sp, int c)
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
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
void bu_vls_from_argv(struct bu_vls *vp, int argc, const char *argv[])
Definition: vls.c:532
#define TREE_NULL
Definition: raytrace.h:1181
matp_t tl_mat
xform matp, NULL ==> identity
Definition: raytrace.h:1173
struct bu_vls * bu_vls_vlsinit(void)
Definition: vls.c:91
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
int ged_arced(struct ged *gedp, int argc, const char *argv[])
Definition: arced.c:34
struct tree::tree_db_leaf tr_l
void * idb_ptr
Definition: raytrace.h:195
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define RT_DIR_NULL
Definition: raytrace.h:875
#define LOOKUP_NOISY
Definition: raytrace.h:892
#define GED_HELP
Definition: ged.h:62
size_t bu_argv_from_string(char *argv[], size_t lim, char *lp)
Definition: argv.c:32
int ged_getmat(struct ged *gedp, int argc, const char *argv[])
Definition: putmat.c:36
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int d_flags
flags
Definition: raytrace.h:869
Definition: vls.h:56
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216