BRL-CAD
fortray.c
Go to the documentation of this file.
1 /* F O R T R A Y . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1986-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup fort */
21 /** @{ */
22 /** @file librt/fortray.c
23  *
24  * A general-purpose set of FORTRAN-callable interface routines to
25  * permit any FORTRAN program to use LIBRT, the ray-tracing library of
26  * the BRL-CAD Package.
27  *
28  */
29 
30 #include "common.h"
31 
32 #include <string.h>
33 #include "bio.h"
34 
35 #include "vmath.h"
36 #include "raytrace.h"
37 
38 
39 static struct partition fr_global_head;
40 
41 
42 HIDDEN int
43 fr_hit(struct application *ap, struct partition *headp, struct seg *segp)
44 {
45  RT_CK_AP(ap);
46  RT_CK_PT_HD(headp);
47  if (segp) RT_CK_SEG(segp);
48 
49  if (headp->pt_forw == headp) return 0;
50 
51  /* Steal the linked list, hang it off a global header */
52  fr_global_head.pt_forw = headp->pt_forw;
53  fr_global_head.pt_back = headp->pt_back;
54  fr_global_head.pt_back->pt_forw = &fr_global_head;
55  fr_global_head.pt_forw->pt_back = &fr_global_head;
56 
57  headp->pt_forw = headp->pt_back = headp;
58  return 1;
59 }
60 
61 
62 HIDDEN int
63 fr_miss(struct application *ap)
64 {
65  RT_CK_AP(ap);
66 
67  fr_global_head.pt_forw = fr_global_head.pt_back = &fr_global_head;
68  return 0;
69 }
70 
71 
72 /**
73  * Take a null-terminated C string, and place it with space padding on
74  * the right into a FORTRAN string of given length.
75  */
76 void
77 fr_string_c2f(register char *fstr, register char *cstr, register int flen)
78 {
79  register int i;
80 
81  for (i = 0; i < flen; i++) {
82  if ((fstr[i] = cstr[i]) == '\0') break;
83  }
84  for (; i < flen; i++)
85  fstr[i] = ' ';
86 }
87 
88 
89 /**
90  * Take a FORTRAN string with a length, and return a pointer to null
91  * terminated copy of that string in a STATIC buffer.
92  */
93 static char *
94 fr_string_f2c(char *str, int maxlen)
95 {
96  static char buf[512];
97  int len;
98  int i;
99 
100  len = sizeof(buf);
101  if (maxlen < len)
102  len = maxlen;
103 
104  bu_strlcpy(buf, str, len);
105 
106  /* Remove any trailing blanks */
107  for (i=(int)strlen(buf)-1; i >= 0; i--) {
108  if (buf[i] != ' ' && buf[i] != '\n') break;
109  buf[i] = '\0';
110  }
111  return buf;
112 }
113 
114 
115 /**
116  * FORTRAN to RT interface for rt_dirbuild()
117  *
118  * XXX NOTE Apollo FORTRAN passes string length as extra (invisible)
119  * argument, by value. Other systems probably are different.
120  *
121  * XXX On some systems, the C standard I/O library may need to be
122  * initialized here (e.g., Cray).
123  */
124 void
125 BU_FORTRAN(frdir, FRDIR)(struct rt_i **rtip, char *filename, int *filelen)
126 {
127  char *file;
128 
129  file = fr_string_f2c(filename, *filelen);
130  *rtip = rt_dirbuild(file, (char *)0, 0);
131 }
132 
133 
134 /**
135  * Add another top-level tree to the in-core geometry.
136  */
137 void
138 BU_FORTRAN(frtree, FRTREE)(int *fail,
139  struct rt_i **rtip,
140  char *objname,
141  int *objlen)
142 {
143  char *obj;
144 
145  RT_CHECK_RTI(*rtip);
146 
147  obj = fr_string_f2c(objname, *objlen);
148  *fail = rt_gettree(*rtip, obj);
149 }
150 
151 
152 void
153 BU_FORTRAN(frprep, FRPREP)(struct rt_i **rtip)
154 {
155  RT_CHECK_RTI(*rtip);
156  rt_prep(*rtip);
157 }
158 
159 
160 #define CONTEXT_LEN 6 /* Reserve this many FORTRAN Doubles for each */
161 struct context {
162  double co_vpriv[3];
163  struct soltab *co_stp;
164  const char *co_priv;
166 };
167 
168 
169 /**
170  * NOTE that the [0] element here corresponds with the caller's (1)
171  * element.
172  */
173 void
174 BU_FORTRAN(frshot, FRSHOT)(int *nloc, /* input & output */
175  double *indist, /* output only */
176  double *outdist,
177  int *region_ids,
178  struct context *context,
179  struct rt_i **rtip, /* input only */
180  double *pt,
181  double *dir)
182 {
183  struct application ap;
184  register struct partition *pp;
185  int ret;
186  register int i;
187 
188  RT_CHECK_RTI(*rtip);
189 
190  if (*nloc <= 0) {
191  bu_log("ERROR frshot: nloc=%d\n", *nloc);
192  *nloc = 0;
193  return;
194  }
195 
196  RT_APPLICATION_INIT(&ap);
197  ap.a_ray.r_pt[X] = pt[0];
198  ap.a_ray.r_pt[Y] = pt[1];
199  ap.a_ray.r_pt[Z] = pt[2];
200  ap.a_ray.r_dir[X] = dir[0];
201  ap.a_ray.r_dir[Y] = dir[1];
202  ap.a_ray.r_dir[Z] = dir[2];
203  VUNITIZE(ap.a_ray.r_dir);
204  ap.a_hit = fr_hit;
205  ap.a_miss = fr_miss;
206  ap.a_level = 0;
207  ap.a_onehit = *nloc * 2;
210  ap.a_purpose = "frshot";
211  ap.a_rt_i = *rtip;
212 
213  /*
214  * Actually fire the ray. The list of results will be linked to
215  * fr_global_head by fr_hit(), for further use below.
216  *
217  * It is a bit risky to rely on the segment structures pointed to
218  * by the partition list to still be valid, because rt_shootray
219  * has already put them back on the free segment queue. However,
220  * they will remain unchanged until the next call to
221  * rt_shootray(), so copying out the data here will work fine.
222  */
223  ret = rt_shootray(&ap);
224 
225  if (ret <= 0) {
226  /* Signal no hits */
227  *nloc = 0;
228  return;
229  }
230 
231  /* Copy hit information from linked list to argument arrays */
232  pp = fr_global_head.pt_forw;
233  if (pp == &fr_global_head) {
234  *nloc = 0;
235  return;
236  }
237  for (i = 0; i < *nloc; i++, pp = pp->pt_forw) {
238  register struct context *ctp;
239 
240  if (pp == &fr_global_head) break;
241  indist[i] = pp->pt_inhit->hit_dist;
242  outdist[i] = pp->pt_outhit->hit_dist;
243  /* This might instead be reg_regionid ?? */
244  region_ids[i] = pp->pt_regionp->reg_bit+1;
245  ctp = &context[i];
246  ctp->co_stp = pp->pt_inseg->seg_stp;
247  VMOVE(ctp->co_vpriv, pp->pt_inhit->hit_vpriv);
248  ctp->co_priv = (const char *)pp->pt_inhit->hit_private;
249  ctp->co_inflip = pp->pt_inflip;
250  }
251  *nloc = i; /* Will have been incremented above, if successful */
252 
253  /* Free linked list storage */
254  for (pp = fr_global_head.pt_forw; pp != &fr_global_head;) {
255  register struct partition *newpp;
256 
257  newpp = pp;
258  pp = pp->pt_forw;
259  FREE_PT(newpp, (&rt_uniresource));
260  }
261 }
262 
263 
264 /**
265  * Given the data returned by a previous call to frshot(), compute the
266  * surface normal at the entry point to the indicated solid.
267  *
268  * In order to save storage, and copying time, frshot() saved only the
269  * minimum amount of data required. Here, the hit and xray structures
270  * are reconstructed, suitable for passing to RT_HIT_NORMAL.
271  */
272 void
273 BU_FORTRAN(frnorm, FRNORM)(double *normal, /* output only */
274  int *idx, /* input only */
275  double *indist,
276  struct context *context,
277  double *UNUSED(pt),
278  double *UNUSED(dir))
279 {
280  register struct context *ctp;
281  struct hit hit;
282  struct soltab *stp;
283  register int i;
284 
285  i = *idx - 1; /* Selects which inhit is used */
286 
287  /* Reconstruct the hit structure */
288  hit.hit_dist = indist[i];
289  ctp = &context[i];
290  stp = ctp->co_stp;
291  VMOVE(hit.hit_vpriv, ctp->co_vpriv);
292  hit.hit_private = (void *)ctp->co_priv;
293 
294  /* The new macro doesn't use ray argument */
295  RT_HIT_NORMAL(normal, &hit, stp, NULL, ctp->co_inflip);
296 }
297 
298 
299 /**
300  * Return the number of regions that exist in the model
301  */
302 void
303 BU_FORTRAN(frnreg, FRNREG)(int *nreg, struct rt_i **rtip)
304 {
305  *nreg = (*rtip)->nregions;
306 }
307 
308 
309 /**
310  * Given a region number (range 1..nregions), return the right-hand
311  * portion of the name in the provided buffer.
312  *
313  * XXX buflen is provided "automatically" on the Apollo.
314  */
315 void
316 BU_FORTRAN(frname, FRNAME)(char *fbuf,
317  int *region_num,
318  struct rt_i **rtip,
319  int fbuflen)
320 {
321  register struct region *rp;
322  int i;
323  int len;
324  int offset;
325  size_t rnum;
326  char buf[512];
327 
328  rnum = *region_num-1;
329  if (rnum > (*rtip)->nregions) {
330  sprintf(buf, "Region id %d out of range, max=%ld",
331  *region_num, (long)((*rtip)->nregions));
332  fr_string_c2f(fbuf, buf, fbuflen);
333  return;
334  }
335  for (BU_LIST_FOR(rp, region, &((*rtip)->HeadRegion))) {
336  if ((size_t)rp->reg_bit != rnum) continue;
337  len = (int)strlen(rp->reg_name);
338  offset = 0;
339  if (len >= fbuflen) {
340  offset = len-(fbuflen+1);
341  len -= (fbuflen+1);
342  }
343  bu_strlcpy(fbuf, rp->reg_name+offset, len);
344  fbuf[len] = ' '; /* replace null with space, needs testing */
345  for (i=offset+len; i < fbuflen; i++)
346  fbuf[i] = ' ';
347  return;
348  }
349  sprintf(fbuf, "Unable to find region %d", *region_num);
350  fr_string_c2f(fbuf, buf, fbuflen);
351 }
352 
353 
354 /** @} */
355 /*
356  * Local Variables:
357  * mode: C
358  * tab-width: 8
359  * indent-tabs-mode: t
360  * c-file-style: "stroustrup"
361  * End:
362  * ex: shiftwidth=4 tabstop=8
363  */
struct xray a_ray
Actual ray to be shot.
Definition: raytrace.h:1583
int reg_bit
constant index into Regions[]
Definition: raytrace.h:541
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
char filename[MAXLENGTH]
Definition: human.c:105
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
void * hit_private
PRIVATE handle for xxx_shot()
Definition: raytrace.h:254
#define RT_CK_SEG(_p)
Definition: raytrace.h:377
HIDDEN int fr_hit(struct application *ap, struct partition *headp, struct seg *segp)
Definition: fortray.c:43
Definition: raytrace.h:368
double co_vpriv[3]
Definition: fortray.c:162
Definition: raytrace.h:248
Header file for the BRL-CAD common definitions.
const char * reg_name
Identifying string.
Definition: raytrace.h:539
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
int a_onehit
flag to stop on first hit
Definition: raytrace.h:1586
int(* a_hit)(struct application *, struct partition *, struct seg *)
called when shot hits model
Definition: raytrace.h:1584
#define HIDDEN
Definition: common.h:86
uint32_t re_magic
Magic number.
Definition: raytrace.h:1441
Definition: color.c:49
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
int co_inflip
Definition: fortray.c:165
vect_t hit_vpriv
PRIVATE vector for xxx_*()
Definition: raytrace.h:253
const char * co_priv
Definition: fortray.c:164
#define RESOURCE_MAGIC
Definition: magic.h:210
struct rt_i * rt_dirbuild(const char *filename, char *buf, int len)
Definition: dir.c:48
#define RT_CHECK_RTI(_p)
Definition: raytrace.h:1832
#define RT_CK_AP(_p)
Definition: raytrace.h:1674
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
int a_level
recursion level (for printing)
Definition: raytrace.h:1595
const char * a_purpose
Debug string: purpose of ray.
Definition: raytrace.h:1598
#define UNUSED(parameter)
Definition: common.h:239
struct partition * pt_back
backwards link
Definition: raytrace.h:575
void fr_string_c2f(register char *fstr, register char *cstr, register int flen)
Definition: fortray.c:77
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
void BU_FORTRAN(frdir, FRDIR)
Definition: fortray.c:125
int rt_gettree(struct rt_i *rtip, const char *node)
Definition: tree.c:869
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
#define RT_CK_PT_HD(_p)
Definition: raytrace.h:591
void rt_prep(struct rt_i *rtip)
Definition: color.c:51
int rt_shootray(struct application *ap)
int(* a_miss)(struct application *)
called when shot misses
Definition: raytrace.h:1585
#define RT_HIT_NORMAL(_normal, _hitp, _stp, _unused, _flipflag)
Definition: raytrace.h:273
#define FREE_PT(p, res)
Definition: raytrace.h:622
struct partition * pt_forw
forwards link
Definition: raytrace.h:574
#define RT_APPLICATION_INIT(_p)
Definition: raytrace.h:1676
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
struct soltab * co_stp
Definition: fortray.c:163
Definition: color.c:50
HIDDEN int fr_miss(struct application *ap)
Definition: fortray.c:63