BRL-CAD
hyp.c
Go to the documentation of this file.
1 /* H Y P . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1990-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 primitives */
21 /** @{ */
22 /** @file primitives/hyp/hyp.c
23  *
24  * Intersect a ray with an elliptical hyperboloid of one sheet.
25  *
26  * [ (x*x) / (r1*r1) ] + [ (y*y) / (r2*r2) ] - [ (z*z) * (c*c) / (r1*r1) ] = 1
27  *
28  * r1: semi-major axis, along Au
29  * r2: semi-minor axis, along Au x H
30  * c: slope of asymptotic cone in the Au-H plane
31  */
32 /** @} */
33 
34 #include "common.h"
35 
36 /* system headers */
37 #include <stdio.h>
38 #include <math.h>
39 
40 /* interface headers */
41 #include "bu/cv.h"
42 #include "vmath.h"
43 #include "db.h"
44 #include "nmg.h"
45 #include "raytrace.h"
46 #include "rtgeom.h"
47 
48 #include "../../librt_private.h"
49 
50 
51 /* ray tracing form of solid, including precomputed terms */
52 struct hyp_specific {
53  point_t hyp_V; /* scaled vector to hyp origin */
54  vect_t hyp_H; /* scaled height vector */
55  vect_t hyp_Au; /* unit vector along semi-major axis */
56  fastf_t hyp_r1; /* scalar semi-major axis length */
57  fastf_t hyp_r2; /* scalar semi-minor axis length */
58  fastf_t hyp_c; /* slope of asymptote cone */
59 
60  vect_t hyp_Hunit; /* unit H vector */
61  vect_t hyp_Aunit; /* unit vector along semi-major axis */
62  vect_t hyp_Bunit; /* unit vector, H x A, semi-minor axis */
63  fastf_t hyp_Hmag; /* scaled height of hyperboloid */
64 
66  fastf_t hyp_ry; /* hyp_r* store coeffs */
68 
69  fastf_t hyp_bounds; /* const used to check if a ray hits the top/bottom surfaces */
70 };
71 
72 
73 struct hyp_specific *
74 hyp_internal_to_specific(struct rt_hyp_internal *hyp_in) {
75  struct hyp_specific *hyp;
76  BU_GET(hyp, struct hyp_specific);
77 
78  hyp->hyp_r1 = hyp_in->hyp_bnr * MAGNITUDE(hyp_in->hyp_A);
79  hyp->hyp_r2 = hyp_in->hyp_bnr * hyp_in->hyp_b;
80  hyp->hyp_c = sqrt(4 * MAGSQ(hyp_in->hyp_A) / MAGSQ(hyp_in->hyp_Hi) * (1 - hyp_in->hyp_bnr * hyp_in->hyp_bnr));
81 
82  VSCALE(hyp->hyp_H, hyp_in->hyp_Hi, 0.5);
83  VADD2(hyp->hyp_V, hyp_in->hyp_Vi, hyp->hyp_H);
84  VMOVE(hyp->hyp_Au, hyp_in->hyp_A);
85  VUNITIZE(hyp->hyp_Au);
86 
87  hyp->hyp_rx = 1.0 / (hyp->hyp_r1 * hyp->hyp_r1);
88  hyp->hyp_ry = 1.0 / (hyp->hyp_r2 * hyp->hyp_r2);
89  hyp->hyp_rz = (hyp->hyp_c * hyp->hyp_c) / (hyp->hyp_r1 * hyp->hyp_r1);
90 
91  /* calculate height to use for top/bottom intersection planes */
92  hyp->hyp_Hmag = MAGNITUDE(hyp->hyp_H);
93  hyp->hyp_bounds = hyp->hyp_rz*hyp->hyp_Hmag*hyp->hyp_Hmag + 1.0;
94 
95  /* setup unit vectors for hyp_specific */
96  VMOVE(hyp->hyp_Hunit, hyp->hyp_H);
97  VMOVE(hyp->hyp_Aunit, hyp->hyp_Au);
98  VCROSS(hyp->hyp_Bunit, hyp->hyp_Hunit, hyp->hyp_Aunit);
99 
100  VUNITIZE(hyp->hyp_Aunit);
101  VUNITIZE(hyp->hyp_Bunit);
102  VUNITIZE(hyp->hyp_Hunit);
103 
104  return hyp;
105 }
106 
107 
108 const struct bu_structparse rt_hyp_parse[] = {
109  { "%f", 3, "V", bu_offsetofarray(struct rt_hyp_internal, hyp_Vi, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
110  { "%f", 3, "H", bu_offsetofarray(struct rt_hyp_internal, hyp_Hi, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
111  { "%f", 3, "A", bu_offsetofarray(struct rt_hyp_internal, hyp_A, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
112  { "%f", 1, "b", bu_offsetof(struct rt_hyp_internal, hyp_b), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
113  { "%f", 1, "bnr", bu_offsetof(struct rt_hyp_internal, hyp_bnr), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
114  { {'\0', '\0', '\0', '\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
115 };
116 
117 /**
118  * Create a bounding RPP for an hyp
119  */
120 int
121 rt_hyp_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) {
122  struct rt_hyp_internal *xip;
123  vect_t hyp_Au, hyp_B, hyp_An, hyp_Bn, hyp_H;
124  vect_t pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8;
125  RT_CK_DB_INTERNAL(ip);
126  xip = (struct rt_hyp_internal *)ip->idb_ptr;
127  RT_HYP_CK_MAGIC(xip);
128 
129  VMOVE(hyp_H, xip->hyp_Hi);
130  VUNITIZE(hyp_H);
131  VMOVE(hyp_Au, xip->hyp_A);
132  VUNITIZE(hyp_Au);
133  VCROSS(hyp_B, hyp_Au, hyp_H);
134 
135  VSETALL((*min), INFINITY);
136  VSETALL((*max), -INFINITY);
137 
138  VSCALE(hyp_B, hyp_B, xip->hyp_b);
139  VREVERSE(hyp_An, xip->hyp_A);
140  VREVERSE(hyp_Bn, hyp_B);
141 
142  VADD3(pt1, xip->hyp_Vi, xip->hyp_A, hyp_B);
143  VADD3(pt2, xip->hyp_Vi, xip->hyp_A, hyp_Bn);
144  VADD3(pt3, xip->hyp_Vi, hyp_An, hyp_B);
145  VADD3(pt4, xip->hyp_Vi, hyp_An, hyp_Bn);
146  VADD4(pt5, xip->hyp_Vi, xip->hyp_A, hyp_B, xip->hyp_Hi);
147  VADD4(pt6, xip->hyp_Vi, xip->hyp_A, hyp_Bn, xip->hyp_Hi);
148  VADD4(pt7, xip->hyp_Vi, hyp_An, hyp_B, xip->hyp_Hi);
149  VADD4(pt8, xip->hyp_Vi, hyp_An, hyp_Bn, xip->hyp_Hi);
150 
151  /* Find the RPP of the rotated axis-aligned hyp bbox - that is,
152  * the bounding box the given hyp would have if its height
153  * vector were in the positive Z direction. This does not give
154  * us an optimal bbox except in the case where the hyp is
155  * actually axis aligned to start with, but it's usually
156  * at least a bit better than the bounding sphere RPP. */
157  VMINMAX((*min), (*max), pt1);
158  VMINMAX((*min), (*max), pt2);
159  VMINMAX((*min), (*max), pt3);
160  VMINMAX((*min), (*max), pt4);
161  VMINMAX((*min), (*max), pt5);
162  VMINMAX((*min), (*max), pt6);
163  VMINMAX((*min), (*max), pt7);
164  VMINMAX((*min), (*max), pt8);
165 
166  return 0;
167 }
168 
169 /**
170  * Given a pointer to a GED database record, and a transformation
171  * matrix, determine if this is a valid HYP, and if so, precompute
172  * various terms of the formula.
173  *
174  * Returns -
175  * 0 HYP is OK
176  * !0 Error in description
177  *
178  * Implicit return -
179  * A struct hyp_specific is created, and its address is stored in
180  * stp->st_specific for use by hyp_shot().
181  */
182 int
183 rt_hyp_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
184 {
185  struct rt_hyp_internal *hyp_ip;
186  struct hyp_specific *hyp;
187 
188  RT_CK_DB_INTERNAL(ip);
189 
190  hyp_ip = (struct rt_hyp_internal *)ip->idb_ptr;
191  RT_HYP_CK_MAGIC(hyp_ip);
192 
193  /* TODO: check that this is a valid hyperboloid (assume it is, for now) */
194 
195  /* set soltab ID */
196  stp->st_id = ID_HYP;
197  stp->st_meth = &OBJ[ID_HYP];
198 
199  hyp = hyp_internal_to_specific(hyp_ip);
200  stp->st_specific = (void *)hyp;
201 
202  /* calculate bounding sphere */
203  VMOVE(stp->st_center, hyp->hyp_V);
204  stp->st_aradius = sqrt((hyp->hyp_c*hyp->hyp_c + 1)*MAGSQ(hyp->hyp_H)
205  + (hyp->hyp_r1*hyp->hyp_r1));
206  stp->st_bradius = stp->st_aradius;
207 
208  /* calculate bounding RPP */
209  if (rt_hyp_bbox(ip, &(stp->st_min), &(stp->st_max), &rtip->rti_tol)) return 1;
210  return 0; /* OK */
211 }
212 
213 
214 void
215 rt_hyp_print(const struct soltab *stp)
216 {
217  const struct hyp_specific *hyp =
218  (struct hyp_specific *)stp->st_specific;
219 
220  VPRINT("V", hyp->hyp_V);
221  VPRINT("Hunit", hyp->hyp_Hunit);
222  VPRINT("Aunit", hyp->hyp_Aunit);
223  VPRINT("Bunit", hyp->hyp_Bunit);
224  fprintf(stderr, "h = %g\n", hyp->hyp_Hmag);
225 }
226 
227 
228 /* hit_surfno is set to one of these */
229 #define HYP_NORM_BODY (1) /* compute normal */
230 #define HYP_NORM_TOP (2) /* copy hyp_Hunit */
231 #define HYP_NORM_BOTTOM (3) /* copy -hyp_Hunit */
232 
233 
234 /**
235  * Intersect a ray with a hyp. If an intersection occurs, a struct
236  * seg will be acquired and filled in.
237  *
238  * Returns -
239  * 0 MISS
240  * >0 HIT
241  */
242 int
243 rt_hyp_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
244 {
245  struct hyp_specific *hyp = (struct hyp_specific *)stp->st_specific;
246  struct seg *segp;
247 
248  struct hit hits[5]; /* 4 potential hits (top, bottom, 2 sides) */
249  struct hit *hitp; /* pointer to hitpoint */
250 
251  vect_t dp;
252  vect_t pp;
253  fastf_t k1, k2;
254  vect_t xlated;
255 
256  fastf_t a, b, c;
257  fastf_t disc;
258  fastf_t hitX, hitY;
259 
260  fastf_t height;
261 
262  hitp = &hits[0];
263 
264  dp[X] = VDOT(hyp->hyp_Aunit, rp->r_dir);
265  dp[Y] = VDOT(hyp->hyp_Bunit, rp->r_dir);
266  dp[Z] = VDOT(hyp->hyp_Hunit, rp->r_dir);
267 
268  VSUB2(xlated, rp->r_pt, hyp->hyp_V);
269  pp[X] = VDOT(hyp->hyp_Aunit, xlated);
270  pp[Y] = VDOT(hyp->hyp_Bunit, xlated);
271  pp[Z] = VDOT(hyp->hyp_Hunit, xlated);
272 
273  /* find roots to quadratic (hitpoints) */
274  a = hyp->hyp_rx*dp[X]*dp[X] + hyp->hyp_ry*dp[Y]*dp[Y] - hyp->hyp_rz*dp[Z]*dp[Z];
275  b = 2.0 * (hyp->hyp_rx*pp[X]*dp[X] + hyp->hyp_ry*pp[Y]*dp[Y] - hyp->hyp_rz*pp[Z]*dp[Z]);
276  c = hyp->hyp_rx*pp[X]*pp[X] + hyp->hyp_ry*pp[Y]*pp[Y] - hyp->hyp_rz*pp[Z]*pp[Z] - 1.0;
277 
278  disc = b*b - (4.0 * a * c);
279  if (!NEAR_ZERO(a, RT_PCOEF_TOL)) {
280  if (disc > 0) {
281  disc = sqrt(disc);
282 
283  k1 = (-b + disc) / (2.0 * a);
284  k2 = (-b - disc) / (2.0 * a);
285 
286  VJOIN1(hitp->hit_vpriv, pp, k1, dp);
287  height = hitp->hit_vpriv[Z];
288  if (fabs(height) <= hyp->hyp_Hmag) {
289  hitp->hit_magic = RT_HIT_MAGIC;
290  hitp->hit_dist = k1;
291  hitp->hit_surfno = HYP_NORM_BODY;
292  hitp++;
293  }
294 
295  VJOIN1(hitp->hit_vpriv, pp, k2, dp);
296  height = hitp->hit_vpriv[Z];
297  if (fabs(height) <= hyp->hyp_Hmag) {
298  hitp->hit_magic = RT_HIT_MAGIC;
299  hitp->hit_dist = k2;
300  hitp->hit_surfno = HYP_NORM_BODY;
301  hitp++;
302  }
303  }
304  } else if (!NEAR_ZERO(b, RT_PCOEF_TOL)) {
305  k1 = -c / b;
306  VJOIN1(hitp->hit_vpriv, pp, k1, dp);
307  if (hitp->hit_vpriv[Z] >= -hyp->hyp_Hmag
308  && hitp->hit_vpriv[Z] <= hyp->hyp_Hmag) {
309  hitp->hit_magic = RT_HIT_MAGIC;
310  hitp->hit_dist = k1;
311  hitp->hit_surfno = HYP_NORM_BODY;
312  hitp++;
313  }
314  }
315 
316  /* check top & bottom plates */
317  k1 = (hyp->hyp_Hmag - pp[Z]) / dp[Z];
318  k2 = (-hyp->hyp_Hmag - pp[Z]) / dp[Z];
319 
320  VJOIN1(hitp->hit_vpriv, pp, k1, dp);
321  hitX = hitp->hit_vpriv[X];
322  hitY = hitp->hit_vpriv[Y];
323  /* check if hitpoint is on the top surface */
324  if ((hyp->hyp_rx*hitX*hitX + hyp->hyp_ry*hitY*hitY) < hyp->hyp_bounds) {
325  hitp->hit_magic = RT_HIT_MAGIC;
326  hitp->hit_dist = k1;
327  hitp->hit_surfno = HYP_NORM_TOP;
328  hitp++;
329  }
330 
331  VJOIN1(hitp->hit_vpriv, pp, k2, dp);
332  hitX = hitp->hit_vpriv[X];
333  hitY = hitp->hit_vpriv[Y];
334  /* check if hitpoint is on the bottom surface */
335  if ((hyp->hyp_rx*hitX*hitX + hyp->hyp_ry*hitY*hitY) < hyp->hyp_bounds) {
336  hitp->hit_magic = RT_HIT_MAGIC;
337  hitp->hit_dist = k2;
338  hitp->hit_surfno = HYP_NORM_BOTTOM;
339  hitp++;
340  }
341 
342  if (hitp == &hits[0] || hitp == &hits[1] || hitp == &hits[3]) {
343  return 0; /* MISS */
344  }
345 
346  if (hitp == &hits[2]) {
347  /* 2 hits */
348  if (hits[0].hit_dist < hits[1].hit_dist) {
349  /* entry is [0], exit is [1] */
350  RT_GET_SEG(segp, ap->a_resource);
351  segp->seg_stp = stp;
352  segp->seg_in = hits[0]; /* struct copy */
353  segp->seg_out = hits[1]; /* struct copy */
354  BU_LIST_INSERT(&(seghead->l), &(segp->l));
355  } else {
356  /* entry is [1], exit is [0] */
357 
358  RT_GET_SEG(segp, ap->a_resource);
359  segp->seg_stp = stp;
360  segp->seg_in = hits[1]; /* struct copy */
361  segp->seg_out = hits[0]; /* struct copy */
362  BU_LIST_INSERT(&(seghead->l), &(segp->l));
363  }
364  return 2; /* HIT */
365  } else {
366  /* 4 hits: 0, 1 are sides, 2, 3 are top/bottom*/
367  struct hit sorted[4];
368 
369  if (hits[0].hit_dist > hits[1].hit_dist) {
370  sorted[1] = hits[1];
371  sorted[2] = hits[0];
372  } else {
373  sorted[1] = hits[0];
374  sorted[2] = hits[1];
375  }
376  if (hits[2].hit_dist > hits[3].hit_dist) {
377  sorted[0] = hits[3];
378  sorted[3] = hits[2];
379  } else {
380  sorted[0] = hits[2];
381  sorted[3] = hits[3];
382  }
383 
384  if (sorted[0].hit_dist > sorted[1].hit_dist
385  || sorted[1].hit_dist > sorted[2].hit_dist
386  || sorted[2].hit_dist > sorted[3].hit_dist) {
387  bu_log("sorting error\n");
388  }
389 
390  /* hit segments are now (0, 1) and (2, 3) */
391  RT_GET_SEG(segp, ap->a_resource);
392  segp->seg_stp = stp;
393  segp->seg_in = sorted[0]; /* struct copy */
394  segp->seg_out = sorted[1]; /* struct copy */
395  BU_LIST_INSERT(&(seghead->l), &(segp->l));
396 
397  RT_GET_SEG(segp, ap->a_resource);
398  segp->seg_stp = stp;
399  segp->seg_in = sorted[2]; /* struct copy */
400  segp->seg_out = sorted[3]; /* struct copy */
401  BU_LIST_INSERT(&(seghead->l), &(segp->l));
402 
403  return 4;
404  }
405 }
406 
407 
408 /**
409  * Given ONE ray distance, return the normal and entry/exit point.
410  */
411 void
412 rt_hyp_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
413 {
414  struct hyp_specific *hyp =
415  (struct hyp_specific *)stp->st_specific;
416 
417  /* normal from basic hyperboloid and transformed normal */
418  vect_t n, nT;
419 
420  VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
421  switch (hitp->hit_surfno) {
422  case HYP_NORM_TOP:
423  VMOVE(hitp->hit_normal, hyp->hyp_Hunit);
424  break;
425  case HYP_NORM_BOTTOM:
426  VREVERSE(hitp->hit_normal, hyp->hyp_Hunit);
427  break;
428  case HYP_NORM_BODY:
429  /* normal vector is VUNITIZE(z * dz/dx, z * dz/dy, -z) */
430  /* z = +- (c/a) * sqrt(x^2/a^2 + y^2/b^2 -1) */
431  VSET(n, hyp->hyp_rx * hitp->hit_vpriv[X],
432  hyp->hyp_ry * hitp->hit_vpriv[Y],
433  -hyp->hyp_rz * hitp->hit_vpriv[Z]);
434 
435  nT[X] = (hyp->hyp_Aunit[X] * n[X])
436  + (hyp->hyp_Bunit[X] * n[Y])
437  + (hyp->hyp_Hunit[X] * n[Z]);
438  nT[Y] = (hyp->hyp_Aunit[Y] * n[X])
439  + (hyp->hyp_Bunit[Y] * n[Y])
440  + (hyp->hyp_Hunit[Y] * n[Z]);
441  nT[Z] = (hyp->hyp_Aunit[Z] * n[X])
442  + (hyp->hyp_Bunit[Z] * n[Y])
443  + (hyp->hyp_Hunit[Z] * n[Z]);
444 
445  VUNITIZE(nT);
446  VMOVE(hitp->hit_normal, nT);
447  break;
448  default:
449  bu_log("rt_hyp_norm: surfno=%d bad\n", hitp->hit_surfno);
450  break;
451  }
452 }
453 
454 
455 /**
456  * Return the curvature of the hyp.
457  */
458 void
459 rt_hyp_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
460 {
461  struct hyp_specific *hyp =
462  (struct hyp_specific *)stp->st_specific;
463  vect_t vert, horiz;
464  point_t hp;
465  fastf_t c, h, k1, k2, denom;
466  fastf_t x, y, ratio;
467 
468  switch (hitp->hit_surfno) {
469  case HYP_NORM_BODY:
470  /* calculate principle curvature directions */
471  VMOVE(hp, hitp->hit_vpriv);
472 
473  VMOVE(vert, hitp->hit_normal);
474  vert[Z] += 10;
475  VCROSS(horiz, vert, hitp->hit_normal);
476  VUNITIZE(horiz);
477  VCROSS(vert, hitp->hit_normal, horiz);
478  VUNITIZE(vert);
479 
480  /* vertical curvature */
481  c = hyp->hyp_c;
482  h = sqrt(hp[X]*hp[X] + hp[Y]*hp[Y]);
483 
484  denom = 1 + (c*c*c*c)*(hp[Z]*hp[Z])/(h*h);
485  denom = sqrt(denom*denom*denom);
486 
487  /* k1 is in the vert direction on the hyberbola */
488  k1 = fabs(c*c/h - (c*c*c*c)*(hp[Z]*hp[Z])/(h*h*h)) / denom;
489 
490  /* horizontal curvature */
491  if (fabs(hp[Y]) >= fabs(hp[X])) {
492  ratio = hyp->hyp_rx / hyp->hyp_ry; /* (b/a)^2 */
493  x = hp[X];
494  y = hp[Y];
495  } else {
496  /* flip x and y to avoid div by zero */
497  ratio = hyp->hyp_ry / hyp->hyp_rx;
498  x = hp[Y];
499  y = hp[X];
500  }
501 
502  denom = fabs(y*y*y + (ratio*ratio)*(x*x)*y);
503  denom = sqrt(denom*denom*denom);
504 
505  /* k2 is in the horiz direction on the ellipse */
506  k2 = -fabs(ratio*y + (ratio*ratio)*(x*x)/y) / denom;
507 
508  if (k1 < fabs(k2)) {
509  VMOVE(cvp->crv_pdir, vert);
510  cvp->crv_c1 = k1;
511  cvp->crv_c2 = k2;
512  } else {
513  VMOVE(cvp->crv_pdir, horiz);
514  cvp->crv_c1 = k2;
515  cvp->crv_c2 = k1;
516  }
517  break;
518  case HYP_NORM_TOP:
519  case HYP_NORM_BOTTOM:
520  cvp->crv_c1 = cvp->crv_c2 = 0;
521  bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal);
522  break;
523  }
524 }
525 
526 
527 /**
528  * For a hit on the surface of an hyp, return the (u, v) coordinates
529  * of the hit point, 0 <= u, v <= 1.
530  *
531  * u = azimuth
532  * v = elevation
533  */
534 void
535 rt_hyp_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
536 {
537  struct hyp_specific *hyp = (struct hyp_specific *)stp->st_specific;
538 
539  if (ap) RT_CK_APPLICATION(ap);
540 
541  /* u = (angle from semi-major axis on basic hyperboloid) / (2*pi) */
542  uvp->uv_u = M_1_2PI
543  * (atan2(-hitp->hit_vpriv[X] * hyp->hyp_r2, hitp->hit_vpriv[Y] * hyp->hyp_r1) + M_PI);
544 
545  /* v ranges (0, 1) on each plate */
546  switch (hitp->hit_surfno) {
547  case HYP_NORM_BODY:
548  /* v = (z + Hmag) / (2*Hmag) */
549  uvp->uv_v = (hitp->hit_vpriv[Z] + hyp->hyp_Hmag) / (2.0 * hyp->hyp_Hmag);
550  break;
551  case HYP_NORM_TOP:
552  uvp->uv_v = 1.0 - sqrt(
553  ((hitp->hit_vpriv[X]*hitp->hit_vpriv[X])*hyp->hyp_rx
554  + (hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y])*hyp->hyp_ry)
555  / (1 + (hitp->hit_vpriv[Z]*hitp->hit_vpriv[Z])*hyp->hyp_rz));
556  break;
557  case HYP_NORM_BOTTOM:
558  uvp->uv_v = sqrt(
559  ((hitp->hit_vpriv[X]*hitp->hit_vpriv[X])*hyp->hyp_rx
560  + (hitp->hit_vpriv[Y]*hitp->hit_vpriv[Y])*hyp->hyp_ry)
561  / (1 + (hitp->hit_vpriv[Z]*hitp->hit_vpriv[Z])*hyp->hyp_rz));
562  break;
563  }
564 
565  /* sanity checks */
566  if (uvp->uv_u < 0.0)
567  uvp->uv_u = 0.0;
568  else if (uvp->uv_u > 1.0)
569  uvp->uv_u = 1.0;
570  if (uvp->uv_v < 0.0)
571  uvp->uv_v = 0.0;
572  else if (uvp->uv_v > 1.0)
573  uvp->uv_v = 1.0;
574 
575  /* copied from g_ehy.c */
576  uvp->uv_du = uvp->uv_dv = 0;
577 }
578 
579 
580 void
581 rt_hyp_free(struct soltab *stp)
582 {
583  struct hyp_specific *hyp =
584  (struct hyp_specific *)stp->st_specific;
585 
586  BU_PUT(hyp, struct hyp_specific);
587 }
588 
589 
590 int
591 rt_hyp_plot(struct bu_list *vhead, struct rt_db_internal *incoming, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
592 {
593  int i, j; /* loop indices */
594  struct rt_hyp_internal *hyp_in;
595  struct hyp_specific *hyp;
596  vect_t majorAxis[8], /* vector offsets along major axis */
597  minorAxis[8], /* vector offsets along minor axis */
598  heightAxis[7], /* vector offsets for layers */
599  Bunit; /* unit vector along semi-minor axis */
600  vect_t ell[16]; /* stores 16 points to draw ellipses */
601  vect_t ribs[16][7]; /* assume 7 layers for now */
602  fastf_t scale; /* used to calculate semi-major/minor axes for top/bottom */
603  fastf_t cos22_5 = 0.9238795325112867385;
604  fastf_t cos67_5 = 0.3826834323650898373;
605 
606  BU_CK_LIST_HEAD(vhead);
607  RT_CK_DB_INTERNAL(incoming);
608  hyp_in = (struct rt_hyp_internal *)incoming->idb_ptr;
609  RT_HYP_CK_MAGIC(hyp_in);
610 
611  hyp = hyp_internal_to_specific(hyp_in);
612 
613  VCROSS(Bunit, hyp->hyp_H, hyp->hyp_Au);
614  VUNITIZE(Bunit);
615 
616  VMOVE(heightAxis[0], hyp->hyp_H);
617  VSCALE(heightAxis[1], heightAxis[0], 0.5);
618  VSCALE(heightAxis[2], heightAxis[0], 0.25);
619  VSETALL(heightAxis[3], 0);
620  VREVERSE(heightAxis[4], heightAxis[2]);
621  VREVERSE(heightAxis[5], heightAxis[1]);
622  VREVERSE(heightAxis[6], heightAxis[0]);
623 
624  for (i = 0; i < 7; i++) {
625  /* determine Z height depending on i */
626  scale = sqrt(MAGSQ(heightAxis[i])*(hyp->hyp_c * hyp->hyp_c)/(hyp->hyp_r1 * hyp->hyp_r1) + 1);
627 
628  /* calculate vectors for offset */
629  VSCALE(majorAxis[0], hyp->hyp_Au, hyp->hyp_r1 * scale);
630  VSCALE(majorAxis[1], majorAxis[0], cos22_5);
631  VSCALE(majorAxis[2], majorAxis[0], M_SQRT1_2);
632  VSCALE(majorAxis[3], majorAxis[0], cos67_5);
633  VREVERSE(majorAxis[4], majorAxis[3]);
634  VREVERSE(majorAxis[5], majorAxis[2]);
635  VREVERSE(majorAxis[6], majorAxis[1]);
636  VREVERSE(majorAxis[7], majorAxis[0]);
637 
638  VSCALE(minorAxis[0], Bunit, hyp->hyp_r2 * scale);
639  VSCALE(minorAxis[1], minorAxis[0], cos22_5);
640  VSCALE(minorAxis[2], minorAxis[0], M_SQRT1_2);
641  VSCALE(minorAxis[3], minorAxis[0], cos67_5);
642  VREVERSE(minorAxis[4], minorAxis[3]);
643  VREVERSE(minorAxis[5], minorAxis[2]);
644  VREVERSE(minorAxis[6], minorAxis[1]);
645  VREVERSE(minorAxis[7], minorAxis[0]);
646 
647  /* calculate ellipse */
648  VADD3(ell[ 0], hyp->hyp_V, heightAxis[i], majorAxis[0]);
649  VADD4(ell[ 1], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[3]);
650  VADD4(ell[ 2], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[2]);
651  VADD4(ell[ 3], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[1]);
652  VADD3(ell[ 4], hyp->hyp_V, heightAxis[i], minorAxis[0]);
653  VADD4(ell[ 5], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[1]);
654  VADD4(ell[ 6], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[2]);
655  VADD4(ell[ 7], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[3]);
656  VADD3(ell[ 8], hyp->hyp_V, heightAxis[i], majorAxis[7]);
657  VADD4(ell[ 9], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[4]);
658  VADD4(ell[10], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[5]);
659  VADD4(ell[11], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[6]);
660  VADD3(ell[12], hyp->hyp_V, heightAxis[i], minorAxis[7]);
661  VADD4(ell[13], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[6]);
662  VADD4(ell[14], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[5]);
663  VADD4(ell[15], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[4]);
664 
665  /* draw ellipse */
666  RT_ADD_VLIST(vhead, ell[15], BN_VLIST_LINE_MOVE);
667  for (j = 0; j < 16; j++) {
668  RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
669  }
670 
671  /* add ellipse's points to ribs */
672  for (j = 0; j < 16; j++) {
673  VMOVE(ribs[j][i], ell[j]);
674  }
675  }
676 
677  /* draw ribs */
678  for (i = 0; i < 16; i++) {
679  RT_ADD_VLIST(vhead, ribs[i][0], BN_VLIST_LINE_MOVE);
680  for (j = 1; j < 7; j++) {
681  RT_ADD_VLIST(vhead, ribs[i][j], BN_VLIST_LINE_DRAW);
682  }
683 
684  }
685 
686  BU_PUT(hyp, struct hyp_specific);
687 
688  return 0;
689 }
690 
691 
692 /**
693  * Returns -
694  * -1 failure
695  * 0 OK. *r points to nmgregion that holds this tessellation.
696  */
697 int
698 rt_hyp_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
699 {
700  fastf_t c, dtol, f, mag_a, mag_h, ntol, r1, r2, r3, cprime;
701  fastf_t **ellipses = NULL;
702  fastf_t theta_new;
703  int *pts_dbl, face, i, j, nseg;
704  int jj, nell;
705  mat_t invRoS;
706  mat_t SoR;
707  struct rt_hyp_internal *iip;
708  struct hyp_specific *xip;
709  struct rt_pt_node *pos_a, *pos_b, *pts_a, *pts_b;
710  struct shell *s;
711  struct faceuse **outfaceuses = NULL;
712  struct faceuse *fu_top;
713  struct loopuse *lu;
714  struct edgeuse *eu;
715  struct vertex *vertp[3];
716  struct vertex ***vells = (struct vertex ***)NULL;
717  vect_t A, Au, B, Bu, Hu, V;
718  struct bu_ptbl vert_tab;
719 
720  MAT_ZERO(invRoS);
721  MAT_ZERO(SoR);
722 
723  RT_CK_DB_INTERNAL(ip);
724  iip = (struct rt_hyp_internal *)ip->idb_ptr;
725  RT_HYP_CK_MAGIC(iip);
726 
727  xip = hyp_internal_to_specific(iip);
728 
729  /*
730  * make sure hyp description is valid
731  */
732 
733  /* compute |A| |H| */
734  mag_a = MAGSQ(xip->hyp_Au); /* should already be unit vector */
735  mag_h = MAGNITUDE(xip->hyp_H);
736  c = xip->hyp_c;
737  cprime = c / mag_h;
738  r1 = xip->hyp_r1;
739  r2 = xip->hyp_r2;
740  r3 = r1 / c;
741  /* Check for |H| > 0, |A| == 1, r1 > 0, r2 > 0, c > 0 */
742  if (NEAR_ZERO(mag_h, RT_LEN_TOL)
743  || !NEAR_EQUAL(mag_a, 1.0, RT_LEN_TOL)
744  || r1 <= 0.0 || r2 <= 0.0 || c <= 0.) {
745  return 1; /* BAD */
746  }
747 
748  /* Check for A.H == 0 */
749  f = VDOT(xip->hyp_Au, xip->hyp_H) / mag_h;
750  if (! NEAR_ZERO(f, RT_DOT_TOL)) {
751  return 1; /* BAD */
752  }
753 
754  /* make unit vectors in A, H, and HxA directions */
755  VMOVE(Hu, xip->hyp_H);
756  VUNITIZE(Hu);
757  VMOVE(Au, xip->hyp_Au);
758  VCROSS(Bu, Hu, Au);
759 
760  dtol = primitive_get_absolute_tolerance(ttol, 2.0 * r2);
761 
762  /* To ensure normal tolerance, remain below this angle */
763  if (ttol->norm > 0.0)
764  ntol = ttol->norm;
765  else
766  /* tolerate everything */
767  ntol = M_PI;
768 
769  /*
770  * build hyp from 2 hyperbolas
771  */
772 
773  /* calculate major axis hyperbola */
774  BU_ALLOC(pts_a, struct rt_pt_node);
775 
776  /* set base, center, and top points */
777  pos_a = pts_a;
778  VSET(pos_a->p, sqrt((mag_h*mag_h) * (c*c) + (r1*r1)), 0, -mag_h);
779  BU_ALLOC(pos_a->next, struct rt_pt_node);
780  pos_a = pos_a->next;
781  VSET(pos_a->p, r1, 0, 0);
782  BU_ALLOC(pos_a->next, struct rt_pt_node);
783  pos_a = pos_a->next;
784  VSET(pos_a->p, sqrt((mag_h*mag_h) * (c*c) + (r1*r1)), 0, mag_h);
785  pos_a->next = NULL;
786 
787  /* refine hyp according to tolerances */
788  i = 1;
789  {
790  point_t p0, p1, p2;
791  fastf_t mm, len, dist, ang0, ang2;
792  vect_t v01, v02; /* vectors from p0->p1 and p0->p2 */
793  vect_t nLine, nHyp;
794  struct rt_pt_node *add;
795 
796  while (i) {
797  pos_a = pts_a;
798  i = 0;
799  while (pos_a->next) {
800 
801  VMOVE(p0, pos_a->p);
802  VMOVE(p2, pos_a->next->p);
803  /* either X or Y will be zero; so adding handles either case */
804  mm = (p2[Z] - p0[Z]) / ((p2[X]+p2[Y]) - (p0[X]+p0[Y]));
805  if (!ZERO(p0[X])) {
806  p1[X] = fabs(mm*c*r1) / sqrt(mm*mm*c*c - 1.0);
807  p1[Y] = 0.0;
808  p1[Z] = sqrt(p1[X]*p1[X] - r1*r1) / c;
809  } else {
810  p1[X] = 0.0;
811  p1[Y] = fabs(mm*r2*r2*c) / sqrt(mm*mm*r2*r2*c*c - r1*r1);
812  p1[Z] = (r3/r2) * sqrt(p1[Y]*p1[Y] - r2*r2);
813  }
814  if (p0[Z] + p2[Z] < 0) p1[Z] = -p1[Z];
815 
816  VSUB2(v01, p1, p0);
817  VSUB2(v02, p2, p0);
818  VUNITIZE(v02);
819  len = VDOT(v01, v02);
820  VSCALE(v02, v02, len);
821  VSUB2(nLine, v01, v02);
822  dist = MAGNITUDE(nLine);
823  VUNITIZE(nLine);
824 
825  VSET(nHyp, p0[X] / (r1*r1), p0[Y] / (r2*r2), p0[Z] / (r3*r3));
826  VUNITIZE(nHyp);
827  ang0 = fabs(acos(VDOT(nLine, nHyp)));
828  VSET(nHyp, p2[X] / (r1*r1), p2[Y] / (r2*r2), p2[Z] / (r3*r3));
829  VUNITIZE(nHyp);
830  ang2 = fabs(acos(VDOT(nLine, nHyp)));
831 
832  if (dist > dtol || ang0 > ntol || ang2 > ntol) {
833  /* split segment */
834  BU_ALLOC(add, struct rt_pt_node);
835  VMOVE(add->p, p1);
836  add->next = pos_a->next;
837  pos_a->next = add;
838  pos_a = pos_a->next;
839  i = 1;
840  }
841  pos_a = pos_a->next;
842  }
843  }
844 
845  }
846 
847  /* calculate minor axis hyperbola */
848  BU_ALLOC(pts_b, struct rt_pt_node);
849 
850  pos_a = pts_a;
851  pos_b = pts_b;
852  i = 0;
853  while (pos_a) {
854  pos_b->p[Z] = pos_a->p[Z];
855  pos_b->p[X] = 0;
856  pos_b->p[Y] = r2 * sqrt(pos_b->p[Z] * pos_b->p[Z]/(r3*r3) + 1.0);
857  pos_a = pos_a->next;
858  if (pos_a) {
859  BU_ALLOC(pos_b->next, struct rt_pt_node);
860  pos_b = pos_b->next;
861  } else {
862  pos_b->next = NULL;
863  }
864  i++;
865  }
866 
867  nell = i;
868 
869  /* make array of ptrs to hyp ellipses */
870  ellipses = (fastf_t **)bu_malloc(nell * sizeof(fastf_t *), "fastf_t ell[]");
871 
872  /* keep track of whether pts in each ellipse are doubled or not */
873  pts_dbl = (int *)bu_malloc(nell * sizeof(int), "dbl ints");
874 
875  /* make ellipses at each z level */
876  i = 0;
877  nseg = 0;
878  pos_a = pts_a; /*->next; */ /* skip over apex of hyp */
879  pos_b = pts_b; /*->next; */
880  while (pos_a) {
881  point_t p1;
882 
883  VSCALE(A, Au, pos_a->p[X]); /* semimajor axis */
884  VSCALE(B, Bu, pos_b->p[Y]); /* semiminor axis */
885  VJOIN1(V, xip->hyp_V, -pos_a->p[Z], Hu);
886 
887  VSET(p1, 0., pos_b->p[Y], 0.);
888  theta_new = ell_angle(p1, pos_a->p[X], pos_b->p[Y], dtol, ntol);
889  if (nseg == 0) {
890  nseg = (int)(M_2PI / theta_new) + 1;
891  pts_dbl[i] = 0;
892  /* maximum number of faces needed for hyp */
893  face = 2*nseg*nell - 4; /*nseg*(1 + 3*((1 << (nell-1)) - 1));*/
894  /* array for each triangular face */
895  outfaceuses = (struct faceuse **)
896  bu_malloc((face+1) * sizeof(struct faceuse *), "hyp: *outfaceuses[]");
897  } else {
898  pts_dbl[i] = 0;
899  }
900 
901  ellipses[i] = (fastf_t *)bu_malloc(3*(nseg+1)*sizeof(fastf_t), "pts ell");
902  rt_ell(ellipses[i], V, A, B, nseg);
903 
904  i++;
905  pos_a = pos_a->next;
906  pos_b = pos_b->next;
907  }
908 
909  /*
910  * put hyp geometry into nmg data structures
911  */
912 
913  *r = nmg_mrsv(m); /* Make region, empty shell, vertex */
914  s = BU_LIST_FIRST(shell, &(*r)->s_hd);
915 
916  /* vertices of ellipses of hyp */
917  vells = (struct vertex ***)
918  bu_malloc(nell*sizeof(struct vertex **), "vertex [][]");
919  j = nseg;
920  for (i = nell-1; i >= 0; i--) {
921  vells[i] = (struct vertex **)
922  bu_malloc(j*sizeof(struct vertex *), "vertex []");
923  if (i && pts_dbl[i])
924  j /= 2;
925  }
926 
927  /* top face of hyp */
928  for (i = 0; i < nseg; i++)
929  vells[nell-1][i] = (struct vertex *)NULL;
930  face = 0;
931  BU_ASSERT_PTR(outfaceuses, !=, NULL);
932  if ((outfaceuses[face++] = nmg_cface(s, vells[nell-1], nseg)) == 0) {
933  bu_log("rt_hyp_tess() failure, top face\n");
934  goto fail;
935  }
936  fu_top = outfaceuses[0];
937 
938  /* Mark edges of this face as real, this is the only real edge */
939  for (BU_LIST_FOR (lu, loopuse, &outfaceuses[0]->lu_hd)) {
940  NMG_CK_LOOPUSE(lu);
941 
942  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
943  continue;
944  for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) {
945  struct edge *e;
946 
947  NMG_CK_EDGEUSE(eu);
948  e = eu->e_p;
949  NMG_CK_EDGE(e);
950  e->is_real = 1;
951  }
952  }
953 
954  for (i = 0; i < nseg; i++) {
955  NMG_CK_VERTEX(vells[nell-1][i]);
956  nmg_vertex_gv(vells[nell-1][i], &ellipses[nell-1][3*i]);
957  }
958 
959  /* connect ellipses with triangles */
960 
961  for (i = nell-2; i >= 0; i--) {
962  /* skip top ellipse */
963  int bottom, top;
964 
965  top = i + 1;
966  bottom = i;
967  if (pts_dbl[top])
968  nseg /= 2; /* # segs in 'bottom' ellipse */
969  vertp[0] = (struct vertex *)0;
970 
971  /* make triangular faces */
972  for (j = 0; j < nseg; j++) {
973  jj = j + j; /* top ellipse index */
974 
975  if (pts_dbl[top]) {
976  /* first triangle */
977  vertp[1] = vells[top][jj+1];
978  vertp[2] = vells[top][jj];
979  if ((outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
980  bu_log("rt_hyp_tess() failure\n");
981  goto fail;
982  }
983  if (j == 0)
984  vells[bottom][j] = vertp[0];
985 
986  /* second triangle */
987  vertp[2] = vertp[1];
988  if (j == nseg-1)
989  vertp[1] = vells[bottom][0];
990  else
991  vertp[1] = (struct vertex *)0;
992  if ((outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
993  bu_log("rt_hyp_tess() failure\n");
994  goto fail;
995  }
996  if (j != nseg-1)
997  vells[bottom][j+1] = vertp[1];
998 
999  /* third triangle */
1000  vertp[0] = vertp[1];
1001  if (j == nseg-1)
1002  vertp[1] = vells[top][0];
1003  else
1004  vertp[1] = vells[top][jj+2];
1005  if ((outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
1006  bu_log("rt_hyp_tess() failure\n");
1007  goto fail;
1008  }
1009  } else {
1010  /* first triangle */
1011  if (j == nseg-1)
1012  vertp[1] = vells[top][0];
1013  else
1014  vertp[1] = vells[top][j+1];
1015  vertp[2] = vells[top][j];
1016  if ((outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
1017  bu_log("rt_hyp_tess() failure\n");
1018  goto fail;
1019  }
1020  if (j == 0)
1021  vells[bottom][j] = vertp[0];
1022 
1023  /* second triangle */
1024  vertp[2] = vertp[0];
1025  if (j == nseg-1)
1026  vertp[0] = vells[bottom][0];
1027  else
1028  vertp[0] = (struct vertex *)0;
1029  if ((outfaceuses[face++] = nmg_cface(s, vertp, 3)) == 0) {
1030  bu_log("rt_hyp_tess() failure\n");
1031  goto fail;
1032  }
1033  if (j != nseg-1)
1034  vells[bottom][j+1] = vertp[0];
1035  }
1036  }
1037 
1038  /* associate geometry with each vertex */
1039  for (j = 0; j < nseg; j++) {
1040  NMG_CK_VERTEX(vells[bottom][j]);
1041  nmg_vertex_gv(vells[bottom][j],
1042  &ellipses[bottom][3*j]);
1043  }
1044  }
1045 
1046  /* bottom face of hyp */
1047  for (i = 0; i < nseg; i++)
1048  vells[0][i] = (struct vertex *)NULL;
1049 
1050  BU_ASSERT_PTR(outfaceuses, !=, NULL);
1051  if ((outfaceuses[face++] = nmg_cface(s, vells[0], nseg)) == 0) {
1052  bu_log("rt_hyp_tess() failure, top face\n");
1053  goto fail;
1054  }
1055  fu_top = outfaceuses[face-1];
1056 
1057  /* Mark edges of this face as real, this is the only real edge */
1058  for (BU_LIST_FOR (lu, loopuse, &outfaceuses[face-1]->lu_hd)) {
1059  NMG_CK_LOOPUSE(lu);
1060 
1061  if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC)
1062  continue;
1063  for (BU_LIST_FOR (eu, edgeuse, &lu->down_hd)) {
1064  struct edge *e;
1065 
1066  NMG_CK_EDGEUSE(eu);
1067  e = eu->e_p;
1068  NMG_CK_EDGE(e);
1069  e->is_real = 1;
1070  }
1071  }
1072 
1073  for (i = 0; i < nseg; i++) {
1074  NMG_CK_VERTEX(vells[0][i]);
1075  nmg_vertex_gv(vells[0][i], &ellipses[0][3*i]);
1076  }
1077 
1078  /* Associate the face geometry */
1079  for (i = 0; i < face; i++) {
1080  if (nmg_fu_planeeqn(outfaceuses[i], tol) < 0) {
1081  bu_log("planeeqn fail:\n\ti:\t%d\n\toutfaceuses:\n\tmin:\t%f\t%f\t%f\n\tmax:\t%f\t%f\t%f\n",
1082  i, outfaceuses[i]->f_p->min_pt[0],
1083  outfaceuses[i]->f_p->min_pt[1],
1084  outfaceuses[i]->f_p->min_pt[2],
1085  outfaceuses[i]->f_p->max_pt[0],
1086  outfaceuses[i]->f_p->max_pt[1],
1087  outfaceuses[i]->f_p->max_pt[2]);
1088  goto fail;
1089  }
1090  }
1091 
1092  /* Glue the edges of different outward pointing face uses together */
1093  nmg_gluefaces(outfaceuses, face, tol);
1094 
1095  /* Compute "geometry" for region and shell */
1096  nmg_region_a(*r, tol);
1097 
1098  /* XXX just for testing, to make up for loads of triangles ... */
1099  nmg_shell_coplanar_face_merge(s, tol, 1);
1100 
1101  /* free mem */
1102  if (outfaceuses)
1103  bu_free((char *)outfaceuses, "faceuse []");
1104  for (i = 0; i < nell; i++) {
1105  if (ellipses)
1106  bu_free((char *)ellipses[i], "pts ell");
1107  if (vells)
1108  bu_free((char *)vells[i], "vertex []");
1109  }
1110  if (ellipses)
1111  bu_free((char *)ellipses, "fastf_t ell[]");
1112  if (vells)
1113  bu_free((char *)vells, "vertex [][]");
1114 
1115  /* Assign vertexuse normals */
1116  nmg_vertex_tabulate(&vert_tab, &s->l.magic);
1117  for (i = 0; i < BU_PTBL_END(&vert_tab); i++) {
1118  point_t pt_prime, tmp_pt;
1119  vect_t norm, rev_norm, tmp_vect;
1120  struct vertex_g *vg;
1121  struct vertex *v;
1122  struct vertexuse *vu;
1123 
1124  v = (struct vertex *)BU_PTBL_GET(&vert_tab, i);
1125  NMG_CK_VERTEX(v);
1126  vg = v->vg_p;
1127  NMG_CK_VERTEX_G(vg);
1128 
1129  VSUB2(tmp_pt, vg->coord, xip->hyp_V);
1130  MAT4X3VEC(pt_prime, SoR, tmp_pt);
1131  VSET(tmp_vect, pt_prime[X]*(2*cprime+1), pt_prime[Y]*(2*cprime+1), -(pt_prime[Z]+cprime+1));
1132  MAT4X3VEC(norm, invRoS, tmp_vect);
1133  VUNITIZE(norm);
1134  VREVERSE(rev_norm, norm);
1135 
1136  for (BU_LIST_FOR (vu, vertexuse, &v->vu_hd)) {
1137  struct faceuse *fu;
1138 
1139  NMG_CK_VERTEXUSE(vu);
1140  fu = nmg_find_fu_of_vu(vu);
1141 
1142  /* don't assign vertexuse normals to top face (flat) */
1143  if (fu == fu_top || fu->fumate_p == fu_top)
1144  continue;
1145 
1146  NMG_CK_FACEUSE(fu);
1147  if (fu->orientation == OT_SAME)
1148  nmg_vertexuse_nv(vu, norm);
1149  else if (fu->orientation == OT_OPPOSITE)
1150  nmg_vertexuse_nv(vu, rev_norm);
1151  }
1152  }
1153 
1154  bu_ptbl_free(&vert_tab);
1155  BU_PUT(xip, struct hyp_specific);
1156  return 0;
1157 
1158  fail:
1159  /* free mem */
1160  if (xip)
1161  BU_PUT(xip, struct hyp_specific);
1162  if (outfaceuses)
1163  bu_free((char *)outfaceuses, "faceuse []");
1164  for (i = 0; i < nell; i++) {
1165  if (ellipses)
1166  bu_free((char *)ellipses[i], "pts ell");
1167  if (vells)
1168  bu_free((char *)vells[i], "vertex []");
1169  }
1170  if (ellipses)
1171  bu_free((char *)ellipses, "fastf_t ell[]");
1172  if (vells)
1173  bu_free((char *)vells, "vertex [][]");
1174 
1175  return -1;
1176 }
1177 
1178 
1179 /**
1180  * Import an HYP from the database format to the internal format.
1181  * Note that the data read will be in network order. This means
1182  * Big-Endian integers and IEEE doubles for floating point.
1183  *
1184  * Apply modeling transformations as well.
1185  */
1186 int
1187 rt_hyp_import5(struct rt_db_internal *ip, const struct bu_external *ep, const mat_t mat, const struct db_i *dbip)
1188 {
1189  struct rt_hyp_internal *hyp_ip;
1190 
1191  /* must be double for import and export */
1192  double vec[ELEMENTS_PER_VECT*4];
1193 
1194  RT_CK_DB_INTERNAL(ip);
1195  BU_CK_EXTERNAL(ep);
1196  if (dbip) RT_CK_DBI(dbip);
1197 
1199 
1200  /* set up the internal structure */
1201  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
1202  ip->idb_type = ID_HYP;
1203  ip->idb_meth = &OBJ[ID_HYP];
1204  BU_ALLOC(ip->idb_ptr, struct rt_hyp_internal);
1205 
1206  hyp_ip = (struct rt_hyp_internal *)ip->idb_ptr;
1207  hyp_ip->hyp_magic = RT_HYP_INTERNAL_MAGIC;
1208 
1209  /* Convert the data in ep->ext_buf into internal format. Note the
1210  * conversion from network data (Big Endian ints, IEEE double
1211  * floating point) to host local data representations.
1212  */
1213  bu_cv_ntohd((unsigned char *)&vec, (const unsigned char *)ep->ext_buf, ELEMENTS_PER_VECT*4);
1214 
1215  /* Apply the modeling transformation */
1216  if (mat == NULL) mat = bn_mat_identity;
1217  MAT4X3PNT(hyp_ip->hyp_Vi, mat, &vec[0*3]);
1218  MAT4X3VEC(hyp_ip->hyp_Hi, mat, &vec[1*3]);
1219  MAT4X3VEC(hyp_ip->hyp_A, mat, &vec[2*3]);
1220 
1221  if (!ZERO(mat[15]))
1222  hyp_ip->hyp_b = vec[9] / mat[15];
1223  else
1224  hyp_ip->hyp_b = INFINITY;
1225  hyp_ip->hyp_bnr = vec[10] ;
1226 
1227  return 0; /* OK */
1228 }
1229 
1230 
1231 /**
1232  * Export an HYP from internal form to external format. Note that
1233  * this means converting all integers to Big-Endian format and
1234  * floating point data to IEEE double.
1235  *
1236  * Apply the transformation to mm units as well.
1237  */
1238 int
1239 rt_hyp_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
1240 {
1241  struct rt_hyp_internal *hyp_ip;
1242 
1243  /* must be double for import and export */
1244  double vec[ELEMENTS_PER_VECT * 4];
1245 
1246  if (dbip) RT_CK_DBI(dbip);
1247 
1248  RT_CK_DB_INTERNAL(ip);
1249  if (ip->idb_type != ID_HYP) return -1;
1250  hyp_ip = (struct rt_hyp_internal *)ip->idb_ptr;
1251  RT_HYP_CK_MAGIC(hyp_ip);
1252 
1253  BU_CK_EXTERNAL(ep);
1254  ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * ELEMENTS_PER_VECT * 4;
1255  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "hyp external");
1256 
1257 
1258  /* Since libwdb users may want to operate in units other than mm,
1259  * we offer the opportunity to scale the solid (to get it into mm)
1260  * on the way out.
1261  */
1262  VSCALE(&vec[0*3], hyp_ip->hyp_Vi, local2mm);
1263  VSCALE(&vec[1*3], hyp_ip->hyp_Hi, local2mm);
1264  VSCALE(&vec[2*3], hyp_ip->hyp_A, local2mm);
1265  vec[ 9] = hyp_ip->hyp_b * local2mm;
1266  vec[10] = hyp_ip->hyp_bnr * local2mm;
1267 
1268  /* Convert from internal (host) to database (network) format */
1269  bu_cv_htond(ep->ext_buf, (unsigned char *)vec, ELEMENTS_PER_VECT*4);
1270 
1271  return 0;
1272 }
1273 
1274 
1275 /**
1276  * Make human-readable formatted presentation of this solid. First
1277  * line describes type of solid. Additional lines are indented one
1278  * tab, and give parameter values.
1279  */
1280 int
1281 rt_hyp_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
1282 {
1283  struct rt_hyp_internal *hyp_ip;
1284  char buf[256];
1285 
1286  hyp_ip = (struct rt_hyp_internal *)ip->idb_ptr;
1287  RT_HYP_CK_MAGIC(hyp_ip);
1288  bu_vls_strcat(str, "truncated general hyp (HYP)\n");
1289 
1290  if (!verbose)
1291  return 0;
1292 
1293  sprintf(buf, "\tV (%g, %g, %g)\n",
1294  INTCLAMP(hyp_ip->hyp_Vi[X] * mm2local),
1295  INTCLAMP(hyp_ip->hyp_Vi[Y] * mm2local),
1296  INTCLAMP(hyp_ip->hyp_Vi[Z] * mm2local));
1297  bu_vls_strcat(str, buf);
1298 
1299  sprintf(buf, "\tH (%g, %g, %g) mag=%g\n",
1300  INTCLAMP(hyp_ip->hyp_Hi[X] * mm2local),
1301  INTCLAMP(hyp_ip->hyp_Hi[Y] * mm2local),
1302  INTCLAMP(hyp_ip->hyp_Hi[Z] * mm2local),
1303  INTCLAMP(MAGNITUDE(hyp_ip->hyp_Hi) * mm2local));
1304  bu_vls_strcat(str, buf);
1305 
1306  sprintf(buf, "\tA (%g, %g, %g)\n",
1307  INTCLAMP(hyp_ip->hyp_A[X] * mm2local),
1308  INTCLAMP(hyp_ip->hyp_A[Y] * mm2local),
1309  INTCLAMP(hyp_ip->hyp_A[Z] * mm2local));
1310  bu_vls_strcat(str, buf);
1311 
1312  sprintf(buf, "\tMag B=%g\n", INTCLAMP(hyp_ip->hyp_b * mm2local));
1313  bu_vls_strcat(str, buf);
1314 
1315  sprintf(buf, "\tNeck to Base Ratio=%g\n", INTCLAMP(hyp_ip->hyp_bnr * mm2local));
1316  bu_vls_strcat(str, buf);
1317 
1318  return 0;
1319 }
1320 
1321 
1322 /**
1323  * Free the storage associated with the rt_db_internal version of this
1324  * solid.
1325  */
1326 void
1328 {
1329  struct rt_hyp_internal *hyp_ip;
1330 
1331  RT_CK_DB_INTERNAL(ip);
1332 
1333  hyp_ip = (struct rt_hyp_internal *)ip->idb_ptr;
1334  RT_HYP_CK_MAGIC(hyp_ip);
1335  hyp_ip->hyp_magic = 0; /* sanity */
1336 
1337  bu_free((char *)hyp_ip, "hyp ifree");
1338  ip->idb_ptr = ((void *)0); /* sanity */
1339 }
1340 
1341 
1342 int
1343 rt_hyp_params(struct pc_pc_set * UNUSED(ps), const struct rt_db_internal *ip)
1344 {
1345  if (ip) RT_CK_DB_INTERNAL(ip);
1346 
1347  return 0; /* OK */
1348 }
1349 
1350 
1351 void
1352 rt_hyp_centroid(point_t *cent, const struct rt_db_internal *ip)
1353 {
1354  if (cent != NULL && ip != NULL) {
1355  struct rt_hyp_internal *hip;
1356 
1357  RT_CK_DB_INTERNAL(ip);
1358  hip = (struct rt_hyp_internal *)ip->idb_ptr;
1359  RT_HYP_CK_MAGIC(hip);
1360 
1361  VSCALE(*cent, hip->hyp_Hi, 0.5);
1362  VADD2(*cent, hip->hyp_Vi, *cent);
1363  }
1364 }
1365 
1366 
1367 /**
1368  * only the stub to make analyze happy
1369  * TODO: needs an implementation
1370  */
1371 void
1372 rt_hyp_surf_area(fastf_t *UNUSED(area), const struct rt_db_internal *UNUSED(ip)) {}
1373 
1374 
1375 void
1376 rt_hyp_volume(fastf_t *volume, const struct rt_db_internal *ip)
1377 {
1378  if (volume != NULL || ip != NULL) {
1379  struct rt_hyp_internal *hip;
1380  struct hyp_specific *hyp;
1381 
1382  RT_CK_DB_INTERNAL(ip);
1383  hip = (struct rt_hyp_internal *)ip->idb_ptr;
1384  RT_HYP_CK_MAGIC(hip);
1385 
1386  hyp = hyp_internal_to_specific(hip);
1387  *volume = M_2PI * hyp->hyp_r1 * hyp->hyp_r2 * hyp->hyp_Hmag *
1388  (1 + hyp->hyp_Hmag * hyp->hyp_Hmag * hyp->hyp_c * hyp->hyp_c / (12 * hyp->hyp_r1 * hyp->hyp_r1));
1389  bu_free(hyp, "hyp volume");
1390  }
1391 }
1392 
1393 
1394 /*
1395  * Local Variables:
1396  * mode: C
1397  * tab-width: 8
1398  * indent-tabs-mode: t
1399  * c-file-style: "stroustrup"
1400  * End:
1401  * ex: shiftwidth=4 tabstop=8
1402  */
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
Definition: raytrace.h:800
#define NMG_EDGEUSE_MAGIC
Definition: magic.h:120
#define RT_LEN_TOL
Definition: raytrace.h:169
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
#define SIZEOF_NETWORK_DOUBLE
Definition: cv.h:48
vect_t hyp_Aunit
Definition: hyp.c:61
int rt_hyp_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
Definition: hyp.c:243
struct faceuse * nmg_cface(struct shell *s, struct vertex **verts, int n)
Definition: nmg_mod.c:1130
Definition: list.h:118
int nmg_fu_planeeqn(struct faceuse *fu, const struct bn_tol *tol)
Definition: nmg_mod.c:1311
#define RT_DOT_TOL
Definition: raytrace.h:170
void rt_hyp_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
Definition: hyp.c:412
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
vect_t crv_pdir
Principle direction.
Definition: raytrace.h:307
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
fastf_t uv_u
Range 0..1.
Definition: raytrace.h:341
if lu s
Definition: nmg_mod.c:3860
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
lu
Definition: nmg_mod.c:3855
#define VSET(a, b, c, d)
Definition: color.c:53
point_t hyp_V
Definition: hyp.c:53
#define VSETALL(a, s)
Definition: color.c:54
Definition: raytrace.h:215
#define M_PI
Definition: fft.h:35
Definition: pc.h:108
Definition: raytrace.h:368
#define BU_ASSERT_LONG(_lhs, _relation, _rhs)
Definition: defines.h:240
Definition: raytrace.h:248
void nmg_vertex_gv(struct vertex *v, const fastf_t *pt)
Definition: nmg_mk.c:1668
fastf_t hyp_c
Definition: hyp.c:58
fastf_t st_aradius
Radius of APPROXIMATING sphere.
Definition: raytrace.h:433
#define HYP_NORM_BOTTOM
Definition: hyp.c:231
int rt_hyp_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: hyp.c:698
fastf_t ell_angle(fastf_t *p1, fastf_t a, fastf_t b, fastf_t dtol, fastf_t ntol)
Definition: ell.c:1788
int rt_hyp_import5(struct rt_db_internal *ip, const struct bu_external *ep, const mat_t mat, const struct db_i *dbip)
Definition: hyp.c:1187
Header file for the BRL-CAD common definitions.
void nmg_vertexuse_nv(struct vertexuse *vu, const fastf_t *norm)
Definition: nmg_mk.c:1719
double add(double a, double b)
Definition: vm_test.cpp:38
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
#define HYP_NORM_TOP
Definition: hyp.c:230
fastf_t hyp_rz
Definition: hyp.c:67
void bu_cv_htond(unsigned char *out, const unsigned char *in, size_t count)
fastf_t hyp_r1
Definition: hyp.c:56
NMG_CK_LOOPUSE(lu)
struct bu_list l
Definition: raytrace.h:369
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
Definition: ptbl.h:62
#define RT_HYP_INTERNAL_MAGIC
Definition: magic.h:98
void rt_hyp_print(const struct soltab *stp)
Definition: hyp.c:215
if(share_geom)
Definition: nmg_mod.c:3829
int idb_major_type
Definition: raytrace.h:192
Definition: color.c:49
#define HYP_NORM_BODY
Definition: hyp.c:229
int rt_hyp_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: hyp.c:1239
vect_t hyp_H
Definition: hyp.c:54
void rt_hyp_free(struct soltab *stp)
Definition: hyp.c:581
vect_t hit_vpriv
PRIVATE vector for xxx_*()
Definition: raytrace.h:253
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
int rt_hyp_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
Definition: hyp.c:1281
#define ID_HYP
Hyperboloid of one sheet.
Definition: raytrace.h:510
void nmg_shell_coplanar_face_merge(struct shell *s, const struct bn_tol *tol, const int simplify)
Definition: nmg_mod.c:93
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
fastf_t st_bradius
Radius of BOUNDING sphere.
Definition: raytrace.h:434
fastf_t crv_c2
curvature in other direction
Definition: raytrace.h:309
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
void rt_hyp_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
Definition: hyp.c:459
fastf_t hyp_rx
Definition: hyp.c:65
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
fastf_t uv_dv
delta in v
Definition: raytrace.h:344
fastf_t primitive_get_absolute_tolerance(const struct rt_tess_tol *ttol, fastf_t rel_to_abs)
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
uint8_t * ext_buf
Definition: parse.h:216
static void top()
#define BU_GET(_ptr, _type)
Definition: malloc.h:201
point_t hit_point
DEPRECATED: Intersection point, use VJOIN1 hit_dist.
Definition: raytrace.h:251
point_t st_max
max X, Y, Z of bounding RPP
Definition: raytrace.h:438
struct hyp_specific * hyp_internal_to_specific(struct rt_hyp_internal *hyp_in)
Definition: hyp.c:74
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
vect_t hyp_Hunit
Definition: hyp.c:60
void rt_hyp_ifree(struct rt_db_internal *ip)
Definition: hyp.c:1327
void rt_hyp_surf_area(fastf_t *area, const struct rt_db_internal *ip)
Definition: hyp.c:1372
struct bu_list l
Definition: ptbl.h:63
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
struct faceuse * nmg_find_fu_of_vu(const struct vertexuse *vu)
Definition: nmg_info.c:304
Support for uniform tolerances.
Definition: tol.h:71
#define BU_LIST_FIRST_MAGIC(hp)
Definition: list.h:416
int rt_hyp_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: hyp.c:183
uint32_t magic
Magic # for mem id/check.
Definition: list.h:119
#define bu_offsetofarray(_t, _a, _d, _i)
Definition: parse.h:65
struct nmgregion * nmg_mrsv(struct model *m)
Definition: nmg_mk.c:306
void rt_hyp_volume(fastf_t *volume, const struct rt_db_internal *ip)
Definition: hyp.c:1376
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
struct bn_tol rti_tol
Math tolerances for this model.
Definition: raytrace.h:1765
struct rt_pt_node * next
ptr to next pt
Definition: raytrace.h:1912
#define bu_offsetof(_t, _m)
Definition: parse.h:64
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
#define RT_GET_SEG(p, res)
Definition: raytrace.h:379
void rt_hyp_centroid(point_t *cent, const struct rt_db_internal *ip)
Definition: hyp.c:1352
int rt_hyp_plot(struct bu_list *vhead, struct rt_db_internal *incoming, const struct rt_tess_tol *ttol, const struct bn_tol *tol, const struct rt_view_info *info)
Definition: hyp.c:591
vect_t hyp_Bunit
Definition: hyp.c:62
#define ZERO(val)
Definition: units.c:38
void * idb_ptr
Definition: raytrace.h:195
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
point_t st_min
min X, Y, Z of bounding RPP
Definition: raytrace.h:437
void bu_cv_ntohd(unsigned char *out, const unsigned char *in, size_t count)
const struct rt_functab OBJ[]
Definition: table.c:159
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
#define BU_ASSERT_PTR(_lhs, _relation, _rhs)
Definition: defines.h:227
int rt_hyp_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *tol)
Definition: hyp.c:121
void bn_vec_ortho(vect_t out, const vect_t in)
void rt_ell(fastf_t *ov, const fastf_t *V, const fastf_t *A, const fastf_t *B, int sides)
Definition: epa.c:1141
void * st_specific
-> ID-specific (private) struct
Definition: raytrace.h:435
fastf_t uv_du
delta in u
Definition: raytrace.h:343
const struct bu_structparse rt_hyp_parse[]
Definition: hyp.c:108
point_t p
a point
Definition: raytrace.h:1911
fastf_t crv_c1
curvature in principle dir
Definition: raytrace.h:308
#define A
Definition: msr.c:51
Definition: color.c:51
fastf_t hyp_r2
Definition: hyp.c:57
double norm
normal tol
Definition: raytrace.h:182
int hit_surfno
solid-specific surface indicator
Definition: raytrace.h:255
int rt_hyp_params(struct pc_pc_set *ps, const struct rt_db_internal *ip)
Definition: hyp.c:1343
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
vect_t hyp_Au
Definition: hyp.c:55
vect_t hit_normal
DEPRECATED: Surface Normal at hit_point, use RT_HIT_NORMAL.
Definition: raytrace.h:252
#define BU_CK_LIST_HEAD(_p)
Definition: list.h:142
#define BU_CK_EXTERNAL(_p)
Definition: parse.h:224
fastf_t hyp_Hmag
Definition: hyp.c:63
void nmg_gluefaces(struct faceuse **fulist, int n, const struct bn_tol *tol)
Definition: nmg_mod.c:1408
const struct rt_functab * st_meth
pointer to per-solid methods
Definition: raytrace.h:428
#define RT_PCOEF_TOL
Definition: raytrace.h:171
int st_id
Solid ident.
Definition: raytrace.h:431
size_t ext_nbytes
Definition: parse.h:210
fastf_t hyp_bounds
Definition: hyp.c:69
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
void rt_hyp_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
Definition: hyp.c:535
HIDDEN void verbose(struct human_data_t *dude)
Definition: human.c:2008
Definition: vls.h:56
#define M_SQRT1_2
Definition: fft.h:38
fastf_t hyp_ry
Definition: hyp.c:66
double fastf_t
Definition: defines.h:300
#define VPRINT(a, b)
Definition: raytrace.h:1881
Definition: color.c:50
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
fastf_t uv_v
Range 0..1.
Definition: raytrace.h:342
void nmg_vertex_tabulate(struct bu_ptbl *tab, const uint32_t *magic_p)
Definition: nmg_info.c:1985
point_t st_center
Centroid of solid.
Definition: raytrace.h:432
#define RT_HIT_MAGIC
Definition: magic.h:161
void nmg_region_a(struct nmgregion *r, const struct bn_tol *tol)
Definition: nmg_mk.c:2557