BRL-CAD
mirror.c
Go to the documentation of this file.
1 /* M I R R O R . 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/mirror.c
21  *
22  * The mirror command.
23  *
24  */
25 
26 #include "bu/getopt.h"
27 #include "ged.h"
28 
29 
30 int
31 ged_mirror(struct ged *gedp, int argc, const char *argv[])
32 {
33  /* trailing x|y|z intentionally not documented */
34  static const char *usage = "[-h] [-p \"point\"] [-d \"dir\"] [-x|-y|-z] [-o offset] old new";
35 
36  int k;
37 
38  point_t mirror_pt = {0.0, 0.0, 0.0};
39  vect_t mirror_dir = {1.0, 0.0, 0.0};
40 
41  /* intentionally double for scanning */
42  double scanpt[3];
43  double scandir[3];
44  double mirror_offset = 0.0;
45 
46  int ret;
47  struct rt_db_internal *ip;
48  struct rt_db_internal internal;
49  struct directory *dp;
50 
53  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
54 
55  /* initialize result */
56  bu_vls_trunc(gedp->ged_result_str, 0);
57 
58  /* must be wanting help */
59  if (argc == 1) {
60  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
61  return GED_HELP;
62  }
63 
64  bu_optind = 1;
65  while ((k = bu_getopt(argc, (char * const *)argv, (const char *)"d:D:hHo:O:p:P:xXyYzZ?")) != -1) {
66  if (bu_optopt == '?') k='h';
67  switch (k) {
68  case 'p':
69  case 'P':
70  if (sscanf(bu_optarg, "%lf %lf %lf",
71  &scanpt[X],
72  &scanpt[Y],
73  &scanpt[Z]) != 3) {
74  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
75  return GED_ERROR;
76  }
77 
78  /* convert from double to fastf_t */
79  VMOVE(mirror_pt, scanpt);
80 
81  break;
82  case 'd':
83  case 'D':
84  if (sscanf(bu_optarg, "%lf %lf %lf",
85  &scandir[X],
86  &scandir[Y],
87  &scandir[Z]) != 3) {
88  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
89  return GED_ERROR;
90  }
91 
92  /* convert from double to fastf_t */
93  VMOVE(mirror_dir, scandir);
94 
95  break;
96  case 'o':
97  case 'O':
98  if (sscanf(bu_optarg, "%lf", &mirror_offset) != 1) {
99  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
100  return GED_ERROR;
101  }
102  break;
103  case 'x':
104  case 'X':
105  VSET(mirror_dir, 1.0, 0.0, 0.0);
106  break;
107  case 'y':
108  case 'Y':
109  VSET(mirror_dir, 0.0, 1.0, 0.0);
110  break;
111  case 'z':
112  case 'Z':
113  VSET(mirror_dir, 0.0, 0.0, 1.0);
114  break;
115  case 'h':
116  case 'H':
117  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
118  return GED_HELP;
119  default:
120  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
121  return GED_ERROR;
122  break;
123  }
124  }
125 
126  argc -= bu_optind;
127 
128  if (argc < 2 || argc > 4) {
129  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
130  return GED_ERROR;
131  } else if (argc == 3) {
132  /* support a trailing x|y|z option as classic command
133  * behavior. THIS IS INTENTIONALLY UNDOCUMENTED. if users
134  * have to read the usage, they can learn the new form.
135  */
136  switch (argv[bu_optind+2][0]) {
137  case 'x':
138  case 'X':
139  VSET(mirror_dir, 1.0, 0.0, 0.0);
140  break;
141  case 'y':
142  case 'Y':
143  VSET(mirror_dir, 0.0, 1.0, 0.0);
144  break;
145  case 'z':
146  case 'Z':
147  VSET(mirror_dir, 0.0, 0.0, 1.0);
148  break;
149  default:
150  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
151  return GED_ERROR;
152  break;
153  }
154  }
155 
156  /* make sure object mirroring to does not already exist */
157  if (db_lookup(gedp->ged_wdbp->dbip, argv[bu_optind+1], LOOKUP_QUIET) != RT_DIR_NULL) {
158  bu_vls_printf(gedp->ged_result_str, "%s already exists\n", argv[bu_optind+1]);
159  return GED_ERROR;
160  }
161 
162  /* look up the object being mirrored */
163  if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[bu_optind], LOOKUP_NOISY)) == RT_DIR_NULL) {
164  bu_vls_printf(gedp->ged_result_str, "Unable to find solid [%s]\n", argv[bu_optind]);
165  return GED_ERROR;
166  }
167 
168  /* get object being mirrored */
169  ret = rt_db_get_internal(&internal, dp, gedp->ged_wdbp->dbip, NULL, gedp->ged_wdbp->wdb_resp);
170  if (ret < 0) {
171  bu_vls_printf(gedp->ged_result_str, "Unable to load solid [%s]\n", argv[bu_optind]);
172  return GED_ERROR;
173  }
174 
175  mirror_offset *= gedp->ged_wdbp->dbip->dbi_local2base;
176  VUNITIZE(mirror_dir);
177  VJOIN1(mirror_pt, mirror_pt, mirror_offset, mirror_dir);
178 
179  /* mirror the object */
180  ip = rt_mirror(gedp->ged_wdbp->dbip,
181  &internal,
182  mirror_pt,
183  mirror_dir,
184  gedp->ged_wdbp->wdb_resp);
185  if (ip == NULL) {
186  bu_vls_printf(gedp->ged_result_str, "Unable to mirror [%s]", argv[bu_optind]);
187  return GED_ERROR;
188  }
189 
190  /* add the mirrored object to the directory */
191  dp = db_diradd(gedp->ged_wdbp->dbip, argv[bu_optind+1], RT_DIR_PHONY_ADDR, 0, dp->d_flags, (void *)&ip->idb_type);
192  if (dp == RT_DIR_NULL) {
193  bu_vls_printf(gedp->ged_result_str, "Unable to add [%s] to the database directory", argv[bu_optind+1]);
194  return GED_ERROR;
195  }
196  /* save the mirrored object to disk */
197  if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, ip, gedp->ged_wdbp->wdb_resp) < 0) {
198  bu_vls_printf(gedp->ged_result_str, "Unable to store [%s] to the database", argv[bu_optind+1]);
199  return GED_ERROR;
200  }
201 
202  {
203  /* draw the new object */
204  const char *object = (const char *)argv[bu_optind+1];
205  const char *e_argv[3] = {0, 0, 0};
206 
207  e_argv[0] = "draw";
208  e_argv[1] = object;
209  e_argv[2] = NULL;
210 
211  (void)ged_draw(gedp, 2, e_argv);
212  ged_view_update(gedp->ged_gvp);
213  }
214 
215  return GED_OK;
216 }
217 
218 
219 /*
220  * Local Variables:
221  * tab-width: 8
222  * mode: C
223  * indent-tabs-mode: t
224  * c-file-style: "stroustrup"
225  * End:
226  * ex: shiftwidth=4 tabstop=8
227  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
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
int ged_mirror(struct ged *gedp, int argc, const char *argv[])
Definition: mirror.c:31
int rt_db_put_internal(struct directory *dp, struct db_i *dbip, struct rt_db_internal *ip, struct resource *resp)
Definition: dir.c:136
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
#define VSET(a, b, c, d)
Definition: color.c:53
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define e_argv
Definition: search.h:147
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
int ged_draw(struct ged *gedp, int argc, const char *argv[])
Definition: draw.c:1212
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
struct rt_wdb * ged_wdbp
Definition: ged.h:340
char * bu_optarg
Definition: globals.c:91
int bu_optind
Definition: globals.c:89
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
void ged_view_update(struct bview *gvp)
Definition: vutil.c:33
#define GED_ERROR
Definition: ged.h:61
struct bview * ged_gvp
Definition: ged.h:361
Definition: color.c:49
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
int bu_optopt
Definition: globals.c:90
struct rt_db_internal * rt_mirror(struct db_i *dbip, struct rt_db_internal *ip, point_t mirror_pt, vect_t mirror_dir, struct resource *resp)
Definition: mirror.c:97
#define LOOKUP_QUIET
Definition: raytrace.h:893
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
struct bu_vls * ged_result_str
Definition: ged.h:357
struct directory * db_diradd(struct db_i *, const char *name, off_t laddr, size_t len, int flags, void *ptr)
Definition: db_lookup.c:190
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
Definition: color.c:51
ustring object
struct resource * wdb_resp
Definition: raytrace.h:1270
double dbi_local2base
local2mm
Definition: raytrace.h:807
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int d_flags
flags
Definition: raytrace.h:869
Definition: color.c:50