BRL-CAD
solids_on_ray.c
Go to the documentation of this file.
1 /* S O L I D S _ O N _ R A Y . 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/solids_on_ray.c
21  *
22  *
23  */
24 
25 #include "common.h"
26 
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <string.h>
30 
31 
32 #include "bn.h"
33 #include "bu/cmd.h"
34 
35 
36 #include "./ged_private.h"
37 
38 
39 /*
40  * Null event handler for use by rt_shootray().
41  *
42  * Does nothing. Returns 1.
43  */
44 static int
45 no_op(struct application *ap, struct partition *ph, struct region *r1, struct region *r2, struct partition *hp)
46 {
47  if (ap) RT_CK_APPLICATION(ap);
48  if (ph) RT_CK_PARTITION(ph);
49  if (r1) RT_CK_REGION(r1);
50  if (r2) RT_CK_REGION(r2);
51  if (hp) RT_CK_PARTITION(hp);
52 
53  return 1;
54 }
55 
56 
57 /*
58  * Each partition represents a segment, i.e. a single solid.
59  *
60  * Boolean operations have not been performed.
61  *
62  * The partition list is sorted by ascending inhit distance. This
63  * code does not attempt to eliminate duplicate segs, e.g. from
64  * piercing the torus twice.
65  */
66 static int
67 rpt_hits(struct application *ap, struct partition *PartHeadp, struct seg *UNUSED(segp))
68 {
69  struct partition *pp;
70  int len;
71  char **list;
72  int i;
73 
74  len = rt_partition_len(PartHeadp) + 2;
75  list = (char **)bu_calloc(len, sizeof(char *), "hit list[]");
76 
77  i = 0;
78  for (pp = PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw) {
79  RT_CK_PT(pp);
80  list[i++] = db_path_to_string(&(pp->pt_inseg->seg_stp->st_path));
81  }
82  list[i++] = NULL;
83  if (i > len) bu_exit(EXIT_FAILURE, "rpt_hits_mike: array overflow\n");
84 
85  ap->a_uptr = (void *)list;
86  return len;
87 }
88 
89 
90 /*
91  * Miss handler for use by rt_shootray().
92  *
93  * Stuffs the address of a null string in ap->a_uptr and returns 0.
94  */
95 
96 static int
97 rpt_miss(struct application *ap)
98 {
99  ap->a_uptr = NULL;
100 
101  return 0;
102 }
103 
104 
105 /*
106  * Fire a ray at some geometry and obtain a list of the solids
107  * encountered, sorted by first intersection.
108  *
109  * The function has five parameters: the model and objects at which to
110  * fire (in an argc/argv pair) the origination point and direction for
111  * the ray, and a result-format specifier. So long as it could find
112  * the objects in the model, skewer_solids() returns a null-
113  * terminated array of solid names. Otherwise, it returns 0. If
114  * full_path is nonzero, then the entire path for each solid is
115  * recorded. Otherwise, only the basename is recorded.
116  *
117  * N.B. - It is the caller's responsibility to free the array
118  * of solid names.
119  */
120 static char **
121 skewer_solids(struct ged *gedp, int argc, const char **argv, fastf_t *ray_orig, fastf_t *ray_dir, int UNUSED(full_path))
122 {
123  struct application ap;
124  struct rt_i *rtip;
125  struct bu_list sol_list;
126 
127  if (argc <= 0) {
128  bu_vls_printf(gedp->ged_result_str, "skewer_solids argc<=0\n");
129  return (char **) 0;
130  }
131 
132  /* .inmem rt_gettrees .rt -i -u [who] */
133  rtip = rt_new_rti(gedp->ged_wdbp->dbip);
134  rtip->useair = 1;
135  rtip->rti_dont_instance = 1; /* full paths to solids, too. */
136  if (rt_gettrees(rtip, argc, argv, 1) == -1) {
137  bu_vls_printf(gedp->ged_result_str, "rt_gettrees() failed\n");
138  rt_clean(rtip);
139  bu_free((void *)rtip, "struct rt_i");
140  return (char **) 0;
141  }
142 
143  /* .rt prep 1 */
144  rtip->rti_hasty_prep = 1;
145  rt_prep(rtip);
146 
147  BU_LIST_INIT(&sol_list);
148 
149  /*
150  * Initialize the application
151  */
152  RT_APPLICATION_INIT(&ap);
153  ap.a_magic = RT_AP_MAGIC;
154  ap.a_ray.magic = RT_RAY_MAGIC;
155  ap.a_hit = rpt_hits;
156  ap.a_miss = rpt_miss;
158  ap.a_overlap = no_op;
159  ap.a_onehit = 0;
160  ap.a_user = 1; /* Requests full paths to solids, not just basenames */
161  ap.a_rt_i = rtip;
162  ap.a_zero1 = ap.a_zero2 = 0;
163  ap.a_purpose = "skewer_solids()";
164  ap.a_no_booleans = 1; /* full paths, no booleans */
165  VMOVE(ap.a_ray.r_pt, ray_orig);
166  VMOVE(ap.a_ray.r_dir, ray_dir);
167 
168  (void) rt_shootray(&ap);
169 
170  rt_clean(rtip);
171  bu_free((void *)rtip, "struct rt_i");
172 
173  return (char **) ap.a_uptr;
174 }
175 
176 
177 int
178 ged_solids_on_ray(struct ged *gedp, int argc, const char *argv[])
179 {
180  char **solids_on_ray_cmd_vec = NULL;
181  int solids_on_ray_cmd_vec_len = 0;
182 
183  size_t args;
184  char **snames;
185  int h = 0;
186  int v = 0;
187  int i; /* Dummy loop index */
188  double t;
189  double t_in;
190  point_t ray_orig;
191  vect_t ray_dir;
192  point_t extremum[2];
193  vect_t unit_H, unit_V;
194  static const char *usage = "[h v]";
195 
199  GED_CHECK_VIEW(gedp, GED_ERROR);
200  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
201 
202  /* initialize result */
203  bu_vls_trunc(gedp->ged_result_str, 0);
204 
205  /* must be wanting help */
206  if (argc == 1) {
207  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
208  return GED_HELP;
209  }
210 
211  if (argc != 1 && argc != 3) {
212  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
213  return GED_ERROR;
214  }
215 
216  if (argc == 3 &&
217  (sscanf(argv[1], "%d", &h) != 1 ||
218  sscanf(argv[2], "%d", &v) != 1)) {
219  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
220  return GED_ERROR;
221  }
222 
223  if ((int)GED_VMIN > h || h > (int)GED_VMAX || (int)GED_VMIN > v || v > (int)GED_VMAX) {
224  bu_vls_printf(gedp->ged_result_str, "Screen coordinates out of range\nMust be between +/-2048");
225  return GED_ERROR;
226  }
227 
228  VSET(ray_orig, -gedp->ged_gvp->gv_center[MDX],
229  -gedp->ged_gvp->gv_center[MDY], -gedp->ged_gvp->gv_center[MDZ]);
230  /*
231  * Compute bounding box of all objects displayed.
232  * Borrowed from size_reset() in chgview.c
233  */
234  for (i = 0; i < 3; ++i) {
235  extremum[0][i] = INFINITY;
236  extremum[1][i] = -INFINITY;
237  }
238 
239  VMOVEN(ray_dir, gedp->ged_gvp->gv_rotation + 8, 3);
240  VSCALE(ray_dir, ray_dir, -1.0);
241  for (i = 0; i < 3; ++i)
242  if (NEAR_ZERO(ray_dir[i], 1e-10))
243  ray_dir[i] = 0.0;
244  if ((ray_orig[X] >= extremum[0][X])
245  && (ray_orig[X] <= extremum[1][X])
246  && (ray_orig[Y] >= extremum[0][Y])
247  && (ray_orig[Y] <= extremum[1][Y])
248  && (ray_orig[Z] >= extremum[0][Z])
249  && (ray_orig[Z] <= extremum[1][Z]))
250  {
251  t_in = -INFINITY;
252  for (i = 0; i < 6; ++i) {
253  if (ZERO(ray_dir[i%3]))
254  continue;
255  t = (extremum[i/3][i%3] - ray_orig[i%3]) /
256  ray_dir[i%3];
257  if ((t < 0) && (t > t_in))
258  t_in = t;
259  }
260  VJOIN1(ray_orig, ray_orig, t_in, ray_dir);
261  }
262 
263  VMOVEN(unit_H, gedp->ged_gvp->gv_model2view, 3);
264  VMOVEN(unit_V, gedp->ged_gvp->gv_model2view + 4, 3);
265  VJOIN1(ray_orig, ray_orig, h * gedp->ged_gvp->gv_scale * INV_GED_V, unit_H);
266  VJOIN1(ray_orig, ray_orig, v * gedp->ged_gvp->gv_scale * INV_GED_V, unit_V);
267 
268  /* allocate space for display top-levels */
269  args = 2 + ged_count_tops(gedp);
270  solids_on_ray_cmd_vec = (char **)bu_calloc(args, sizeof(char *), "alloca solids_on_ray_cmd_vec");
271 
272  /*
273  * Build a list of all the top-level objects currently displayed
274  */
275  solids_on_ray_cmd_vec_len = ged_build_tops(gedp, &solids_on_ray_cmd_vec[0], &solids_on_ray_cmd_vec[args]);
276 
277  snames = skewer_solids(gedp, solids_on_ray_cmd_vec_len, (const char **)solids_on_ray_cmd_vec, ray_orig, ray_dir, 1);
278 
279  bu_free(solids_on_ray_cmd_vec, "free solids_on_ray_cmd_vec");
280  solids_on_ray_cmd_vec = NULL;
281 
282  if (snames == 0) {
283  bu_vls_printf(gedp->ged_result_str, "Error executing skewer_solids: ");
284  return GED_ERROR;
285  }
286 
287  for (i = 0; snames[i] != 0; ++i)
288  bu_vls_printf(gedp->ged_result_str, " %s", snames[i]);
289 
290  bu_free((void *) snames, "solid names");
291 
292  return GED_OK;
293 }
294 
295 
296 /*
297  * Local Variables:
298  * tab-width: 8
299  * mode: C
300  * indent-tabs-mode: t
301  * c-file-style: "stroustrup"
302  * End:
303  * ex: shiftwidth=4 tabstop=8
304  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
struct xray a_ray
Actual ray to be shot.
Definition: raytrace.h:1583
mat_t gv_center
Definition: bview.h:221
Definition: list.h:118
void rt_clean(struct rt_i *rtip)
#define RT_RAY_MAGIC
Definition: magic.h:165
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
struct soltab * seg_stp
pointer back to soltab
Definition: raytrace.h:372
size_t ged_count_tops(struct ged *gedp)
Definition: rt.c:409
int useair
1="air" regions are retained while prepping
Definition: raytrace.h:1756
#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 GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
Definition: raytrace.h:368
struct db_full_path st_path
path from region to leaf
Definition: raytrace.h:442
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
int a_onehit
flag to stop on first hit
Definition: raytrace.h:1586
#define RT_CK_REGION(_p)
Definition: raytrace.h:559
#define RESOURCE_NULL
Definition: raytrace.h:1489
int(* a_hit)(struct application *, struct partition *, struct seg *)
called when shot hits model
Definition: raytrace.h:1584
#define GED_ERROR
Definition: ged.h:61
struct bview * ged_gvp
Definition: ged.h:361
int a_zero2
must be zero (sanity check)
Definition: raytrace.h:1627
Definition: color.c:49
uint32_t a_magic
Definition: raytrace.h:1581
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
#define RT_AP_MAGIC
Definition: magic.h:152
#define GED_CHECK_VIEW(_gedp, _flags)
Definition: ged.h:140
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
fastf_t gv_scale
Definition: bview.h:211
int a_user
application-specific value
Definition: raytrace.h:1617
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
struct seg * pt_inseg
IN seg ptr (gives stp)
Definition: raytrace.h:576
#define GED_VMAX
Definition: ged.h:67
#define GED_CHECK_DRAWABLE(_gedp, _flags)
Definition: ged.h:129
const char * a_purpose
Debug string: purpose of ray.
Definition: raytrace.h:1598
#define UNUSED(parameter)
Definition: common.h:239
int(* a_overlap)(struct application *, struct partition *, struct region *, struct region *, struct partition *)
DEPRECATED.
Definition: raytrace.h:1592
char * db_path_to_string(const struct db_full_path *pp)
Definition: db_fullpath.c:191
struct bu_vls * ged_result_str
Definition: ged.h:357
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
int rti_hasty_prep
1=hasty prep, slower ray-trace
Definition: raytrace.h:1759
struct rt_i * rt_new_rti(struct db_i *dbip)
Definition: prep.c:58
int a_zero1
must be zero (sanity check)
Definition: raytrace.h:1589
mat_t gv_rotation
Definition: bview.h:220
#define ZERO(val)
Definition: units.c:38
#define BU_LIST_INIT(_hp)
Definition: list.h:148
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
mat_t gv_model2view
Definition: bview.h:222
#define RT_CK_PT(_p)
Definition: raytrace.h:589
void rt_prep(struct rt_i *rtip)
int a_no_booleans
1= partitions==segs, no booleans
Definition: raytrace.h:1602
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define GED_HELP
Definition: ged.h:62
int rti_dont_instance
1=Don't compress instances of solids into 1 while prepping
Definition: raytrace.h:1758
Definition: color.c:51
int rt_shootray(struct application *ap)
void * a_uptr
application-specific pointer
Definition: raytrace.h:1618
#define RT_CK_PARTITION(_p)
Definition: raytrace.h:590
int rt_gettrees(struct rt_i *rtip, int argc, const char **argv, int ncpus)
Definition: tree.c:888
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int(* a_miss)(struct application *)
called when shot misses
Definition: raytrace.h:1585
#define INV_GED_V
Definition: ged.h:69
struct partition * pt_forw
forwards link
Definition: raytrace.h:574
#define RT_APPLICATION_INIT(_p)
Definition: raytrace.h:1676
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int ged_solids_on_ray(struct ged *gedp, int argc, const char *argv[])
#define GED_VMIN
Definition: ged.h:66
int rt_partition_len(const struct partition *partheadp)
Definition: bool.c:1936
double fastf_t
Definition: defines.h:300
int ged_build_tops(struct ged *gedp, char **start, char **end)
Definition: rt.c:424
Definition: color.c:50
uint32_t magic
Definition: raytrace.h:216