BRL-CAD
eto.c
Go to the documentation of this file.
1 /* E T O . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1992-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/eto/eto.c
23  *
24  * Intersect a ray with an Elliptical Torus.
25  *
26  */
27 
28 #include "common.h"
29 
30 #include <stddef.h>
31 #include <string.h>
32 #include <math.h>
33 #include "bio.h"
34 
35 #include "bu/cv.h"
36 #include "vmath.h"
37 #include "db.h"
38 #include "nmg.h"
39 #include "rtgeom.h"
40 #include "raytrace.h"
41 
42 #include "../../librt_private.h"
43 
44 static int eto_is_valid(struct rt_eto_internal *eto);
45 
46 /*
47  * The ETO has the following input fields:
48  * V V from origin to center.
49  * N Normal to plane of eto.
50  * C Semi-major axis of elliptical cross section.
51  * r Radius of revolution.
52  * rd Semi-minor axis of elliptical cross section.
53  *
54  */
55 
56 /*
57  * Algorithm:
58  *
59  * Given V, N, C, r, and rd, there is a set of points on this eto
60  *
61  * { (x, y, z) | (x, y, z) is on eto defined by V, N, C, r, rd }
62  *
63  * Through a series of Transformations, this set will be transformed
64  * into a set of points on an eto centered at the origin which lies on
65  * the X-Y plane (i.e., N is on the Z axis).
66  *
67  * { (x', y', z') | (x', y', z') is an eto at origin }
68  *
69  * The transformation from X to X' is accomplished by:
70  *
71  * X' = R(X - V)
72  *
73  * where R(X) = (B/(|B|))
74  * (A/(|A|)) . X
75  * (N/(|N|))
76  *
77  * To find the intersection of a line with the eto, consider the
78  * parametric line L:
79  *
80  * L : { P(n) | P + t(n) . D }
81  *
82  * Call W the actual point of intersection between L and the eto. Let
83  * W' be the point of intersection between L' and the unit eto.
84  *
85  * L' : { P'(n) | P' + t(n) . D' }
86  *
87  * W = invR(W') + V
88  *
89  * Where W' = k D' + P'.
90  *
91  *
92  * Given a line and a ratio, alpha, finds the equation of the unit eto
93  * in terms of the variable 't'.
94  *
95  * Given that the equation for the eto is:
96  *
97  * _______ _______
98  * / 2 2 2 / 2 2 2
99  * [Eu(+- \/ x + y - R) + Ev z] + [Fu(+-\/ x + y - R) + Fv z ]
100  * -------------------------------- ------------------------------- = 1
101  * 2 2
102  * Rc Rd
103  *
104  * First, find X, Y, and Z in terms of 't' for this line, then
105  * substitute them into the equation above.
106  *
107  * Wx = Dx*t + Px
108  *
109  * Wx**2 = Dx**2 * t**2 + 2 * Dx * Px + Px**2
110  *
111  * The real roots of the equation in 't' are the intersect points
112  * along the parametric line.
113  *
114  * NORMALS. Given the point W on the eto, what is the vector normal
115  * to the tangent plane at that point?
116  *
117  * Map W onto the eto, i.e.: W' = R(W - V). In this case, we find W'
118  * by solving the parametric line given k.
119  *
120  * The gradient of the eto at W' is in fact the
121  * normal vector.
122  *
123  * For f(x, y, z) = 0, the gradient of f() is (df/dx, df/dy, df/dz).
124  *
125  * Note that the normal vector (gradient) produced above will not have
126  * unit length. Also, to make this useful for the original eto, it
127  * will have to be rotated back to the orientation of the original
128  * eto.
129  */
130 
131 struct eto_specific {
132  vect_t eto_V; /* Vector to center of eto */
133  vect_t eto_N; /* unit normal to plane of eto */
134  vect_t eto_C; /* semi-major axis of ellipse */
135  fastf_t eto_r; /* radius of revolution */
136  fastf_t eto_rc; /* semi-major axis of ellipse */
137  fastf_t eto_rd; /* semi-minor axis of ellipse */
138  mat_t eto_R; /* Rot(vect) */
139  mat_t eto_invR; /* invRot(vect') */
141 };
142 
143 
144 const struct bu_structparse rt_eto_parse[] = {
145  { "%f", 3, "V", bu_offsetofarray(struct rt_eto_internal, eto_V, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
146  { "%f", 3, "N", bu_offsetofarray(struct rt_eto_internal, eto_N, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
147  { "%f", 3, "C", bu_offsetofarray(struct rt_eto_internal, eto_C, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
148  { "%f", 1, "r", bu_offsetof(struct rt_eto_internal, eto_r), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
149  { "%f", 1, "r_d", bu_offsetof(struct rt_eto_internal, eto_rd), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
150  { {'\0', '\0', '\0', '\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
151 };
152 
153 /**
154  * Calculate bounding RPP of elliptical torus
155  */
156 int
157 rt_eto_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol))
158 {
159  vect_t P, Nu, w1; /* for RPP calculation */
160  fastf_t f, eto_rc;
161  struct rt_eto_internal *tip;
162  tip = (struct rt_eto_internal *)ip->idb_ptr;
163  RT_ETO_CK_MAGIC(tip);
164 
165  /*
166  * Compute the bounding RPP planes for a circular eto.
167  *
168  * Given a circular eto with vertex V, vector N, and radii r and
169  * |C|. A bounding plane with direction vector P will touch the
170  * surface of the eto at the points: V +/- [|C| + r * |N x P|] P
171  */
172  VMOVE(Nu, tip->eto_N);
173  VUNITIZE(Nu); /* z axis of coord sys */
174  eto_rc = MAGNITUDE(tip->eto_C);
175 
176  /* X */
177  VSET(P, 1.0, 0, 0); /* bounding plane normal */
178  VCROSS(w1, Nu, P); /* for sin(angle N P) */
179  f = eto_rc + tip->eto_r * MAGNITUDE(w1);
180  VSCALE(w1, P, f);
181  f = fabs(w1[X]);
182  (*min)[X] = tip->eto_V[X] - f;
183  (*max)[X] = tip->eto_V[X] + f;
184 
185  /* Y */
186  VSET(P, 0, 1.0, 0); /* bounding plane normal */
187  VCROSS(w1, Nu, P); /* for sin(angle N P) */
188  f = eto_rc + tip->eto_r * MAGNITUDE(w1);
189  VSCALE(w1, P, f);
190  f = fabs(w1[Y]);
191  (*min)[Y] = tip->eto_V[Y] - f;
192  (*max)[Y] = tip->eto_V[Y] + f;
193 
194  /* Z */
195  VSET(P, 0, 0, 1.0); /* bounding plane normal */
196  VCROSS(w1, Nu, P); /* for sin(angle N P) */
197  f = eto_rc + tip->eto_r * MAGNITUDE(w1);
198  VSCALE(w1, P, f);
199  f = fabs(w1[Z]);
200  (*min)[Z] = tip->eto_V[Z] - f;
201  (*max)[Z] = tip->eto_V[Z] + f;
202 
203  return 0;
204 }
205 
206 
207 /**
208  * Given a pointer to a GED database record, and a transformation
209  * matrix, determine if this is a valid eto, and if so, precompute
210  * various terms of the formula.
211  *
212  * Returns -
213  * 0 ETO is OK
214  * !0 Error in description
215  *
216  * Implicit return -
217  * A struct eto_specific is created, and its address is stored in
218  * stp->st_specific for use by rt_eto_shot().
219  */
220 int
221 rt_eto_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
222 {
223  struct eto_specific *eto;
224 
225  vect_t Au, Bu, Cu, Nu;
226  fastf_t ch, cv, dh, phi;
227  struct rt_eto_internal *tip;
228 
229  if (rtip) RT_CK_RTI(rtip);
230 
231  tip = (struct rt_eto_internal *)ip->idb_ptr;
232  if (!eto_is_valid(tip)) {
233  return 1;
234  }
235 
236  /* Solid is OK, compute constant terms now */
237  BU_GET(eto, struct eto_specific);
238  stp->st_specific = (void *)eto;
239 
240  eto->eto_r = tip->eto_r;
241  eto->eto_rd = tip->eto_rd;
242  eto->eto_rc = MAGNITUDE(tip->eto_C);
243 
244  VMOVE(eto->eto_V, tip->eto_V);
245  VMOVE(eto->eto_N, tip->eto_N);
246  VMOVE(eto->eto_C, tip->eto_C);
247  VMOVE(Nu, tip->eto_N);
248  VUNITIZE(Nu); /* z axis of coord sys */
249  bn_vec_ortho(Bu, Nu); /* x axis */
250  VUNITIZE(Bu);
251  VCROSS(Au, Nu, Bu); /* y axis */
252  VMOVE(Cu, tip->eto_C);
253  VUNITIZE(Cu);
254 
255  /* get horizontal and vertical components of C and Rd */
256  cv = VDOT(eto->eto_C, Nu);
257  ch = sqrt(VDOT(eto->eto_C, eto->eto_C) - cv * cv);
258  /* angle between C and Nu */
259  phi = acos(cv / eto->eto_rc);
260  dh = eto->eto_rd * cos(phi);
261  /* make sure ellipse doesn't overlap itself when revolved */
262  if (ch > eto->eto_r || dh > eto->eto_r) {
263  bu_log("eto(%s): revolved ellipse overlaps itself\n",
264  stp->st_name);
265  return 1;
266  }
267 
268  eto->ev = fabs(VDOT(Cu, Nu)); /* vertical component of Cu */
269  eto->eu = sqrt(1.0 - eto->ev * eto->ev); /* horiz component */
270  eto->fu = -eto->ev;
271  eto->fv = eto->eu;
272 
273  /* Compute R and invR matrices */
274  MAT_IDN(eto->eto_R);
275  VMOVE(&eto->eto_R[0], Bu);
276  VMOVE(&eto->eto_R[4], Au);
277  VMOVE(&eto->eto_R[8], Nu);
278  bn_mat_inv(eto->eto_invR, eto->eto_R);
279 
280  stp->st_aradius = stp->st_bradius = eto->eto_r + eto->eto_rc;
281 
282  if (rt_eto_bbox(ip, &(stp->st_min), &(stp->st_max), &rtip->rti_tol)) return 1;
283 
284  return 0; /* OK */
285 }
286 
287 
288 void
289 rt_eto_print(const struct soltab *stp)
290 {
291  const struct eto_specific *eto =
292  (struct eto_specific *)stp->st_specific;
293 
294  VPRINT("V", eto->eto_V);
295  VPRINT("N", eto->eto_N);
296  VPRINT("C", eto->eto_C);
297  bu_log("r = %f\n", eto->eto_r);
298  bu_log("rc = %f\n", eto->eto_rc);
299  bu_log("rd = %f\n", eto->eto_rd);
300  bn_mat_print("R", eto->eto_R);
301  bn_mat_print("invR", eto->eto_invR);
302  bu_log("rpp: (%g, %g, %g) to (%g, %g, %g)\n",
303  stp->st_min[X], stp->st_min[Y], stp->st_min[Z],
304  stp->st_max[X], stp->st_max[Y], stp->st_max[Z]);
305 }
306 
307 
308 /**
309  * Intersect a ray with an eto, where all constant terms have been
310  * precomputed by rt_eto_prep(). If an intersection occurs, one or
311  * two struct seg(s) will be acquired and filled in.
312  *
313  * NOTE: All lines in this function are represented parametrically by
314  * a point, P(x0, y0, z0) and a direction normal, D = ax + by + cz.
315  * Any point on a line can be expressed by one variable 't', where
316  *
317  * X = a*t + x0, e.g., X = Dx*t + Px
318  * Y = b*t + y0,
319  * Z = c*t + z0.
320  *
321  * First, convert the line to the coordinate system of a "stan- dard"
322  * eto. This is a eto which lies in the X-Y plane and circles the
323  * origin. The semimajor axis is C.
324  *
325  * Then find the equation of that line and the standard eto, which
326  * turns out to be a quartic equation in 't'. Solve the equation
327  * using a general polynomial root finder. Use those values of 't' to
328  * compute the points of intersection in the original coordinate
329  * system.
330  *
331  * Returns -
332  * 0 MISS
333  * >0 HIT
334  */
335 int
336 rt_eto_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
337 {
338  struct eto_specific *eto =
339  (struct eto_specific *)stp->st_specific;
340  struct seg *segp;
341  vect_t dprime; /* D' */
342  vect_t pprime; /* P' */
343  vect_t work; /* temporary vector */
344  bn_poly_t C; /* The final equation */
345  bn_complex_t val[4]; /* The complex roots */
346  double k[4]; /* The real roots */
347  int i;
348  int j;
349  vect_t cor_pprime; /* new ray origin */
350  fastf_t cor_proj;
351  fastf_t A1, A2, A3, A4, A5, A6, A7, A8, B1, B2, B3, C1, C2, C3, D1, term;
352 
353  /* Convert vector into the space of the unit eto */
354  MAT4X3VEC(dprime, eto->eto_R, rp->r_dir);
355  VUNITIZE(dprime);
356 
357  VSUB2(work, rp->r_pt, eto->eto_V);
358  MAT4X3VEC(pprime, eto->eto_R, work);
359 
360  /* normalize distance from eto. substitute corrected pprime which
361  * contains a translation along ray direction to closest approach
362  * to vertex of eto. Translating ray origin along direction of
363  * ray to closest pt. to origin of solid's coordinate system, new
364  * ray origin is 'cor_pprime'.
365  */
366  cor_proj = VDOT(pprime, dprime);
367  VSCALE(cor_pprime, dprime, cor_proj);
368  VSUB2(cor_pprime, pprime, cor_pprime);
369 
370  /*
371  * NOTE: The following code is based on code in eto.f by ERIM for
372  * GIFT.
373  *
374  * Given a line, finds the equation of the eto in terms of the
375  * variable 't'.
376  *
377  * The equation for the eto is:
378  *
379  _______ ________
380  / 2 2 2 / 2 2 2
381  [Eu(+- \/ x + y - R) + Ev z] + [Fu(+-\/ x + y - R) + Fv z ]
382  -------------------------------- ------------------------------- = 1
383  2 2
384  Rc Rd
385  *
386  * ^ ^
387  * where Ev = C . N
388  *
389  * ^ ^
390  * Eu = C . A
391  *
392  * ^ ^
393  * Fv = C . A
394  *
395  * ^ ^
396  * Fu =-C . N.
397  *
398  * First, find X, Y, and Z in terms of 't' for this line, then
399  * substitute them into the equation above.
400  *
401  * Wx = Dx*t + Px, etc.
402  *
403  * Regrouping coefficients and constants, the equation can then be
404  * rewritten as:
405  *
406  * [A1*sqrt(C1 + C2*t + C3*t^2) + A2 + A3*t]^2 +
407  * [B1*sqrt(C1 + C2*t + C3*t^2) + B2 + B3*t]^2 - D1 = 0
408  *
409  * where, (variables defined in code below)
410  */
411  A1 = eto->eto_rd * eto->eu;
412  B1 = eto->eto_rc * eto->fu;
413  C1 = cor_pprime[X] * cor_pprime[X] + cor_pprime[Y] * cor_pprime[Y];
414  C2 = 2 * (dprime[X] * cor_pprime[X] + dprime[Y] * cor_pprime[Y]);
415  C3 = dprime[X] * dprime[X] + dprime[Y] * dprime[Y];
416  A2 = -eto->eto_rd * eto->eto_r * eto->eu + eto->eto_rd * eto->ev * cor_pprime[Z];
417  B2 = -eto->eto_rc * eto->eto_r * eto->fu + eto->eto_rc * eto->fv * cor_pprime[Z];
418  A3 = eto->eto_rd * eto->ev * dprime[Z];
419  B3 = eto->eto_rc * eto->fv * dprime[Z];
420  D1 = eto->eto_rc * eto->eto_rc * eto->eto_rd * eto->eto_rd;
421 
422  /*
423  * Squaring the two terms above and again regrouping coefficients
424  * the equation now becomes:
425  *
426  * A6*t^2 + A5*t + A4 = -(A8*t + A7)*sqrt(C1 + C2*t + C3*t^2)
427  *
428  * where, (variables defined in code)
429  */
430  A4 = A1*A1*C1 + B1*B1*C1 + A2*A2 + B2*B2 - D1;
431  A5 = A1*A1*C2 + B1*B1*C2 + 2*A2*A3 + 2*B2*B3;
432  A6 = A1*A1*C3 + B1*B1*C3 + A3*A3 + B3*B3;
433  A7 = 2*(A1*A2 + B1*B2);
434  A8 = 2*(A1*A3 + B1*B3);
435  term = A6*A6 - A8*A8*C3;
436 
437  /*
438  * Squaring both sides and subtracting RHS from LHS yields:
439  */
440  C.dgr=4;
441  C.cf[4] = (A4*A4 - A7*A7*C1); /* t^0 */
442  C.cf[3] = (2*A4*A5 - A7*A7*C2 - 2*A7*A8*C1); /* t^1 */
443  C.cf[2] = (2*A4*A6 + A5*A5 - A7*A7*C3 - 2*A7*A8*C2 - A8*A8*C1); /* t^2 */
444  C.cf[1] = (2*A5*A6 - 2*A7*A8*C3 - A8*A8*C2); /* t^3 */
445  C.cf[0] = term; /* t^4 */
446  /* NOTE: End of ERIM based code */
447 
448  /* It is known that the equation is 4th order. Therefore, if the
449  * root finder returns other than 4 roots, error.
450  */
451  if ((i = rt_poly_roots(&C, val, stp->st_dp->d_namep)) != 4) {
452  if (i > 0) {
453  bu_log("eto: rt_poly_roots() 4!=%d\n", i);
454  bn_pr_roots(stp->st_name, val, i);
455  } else if (i < 0) {
456  static int reported = 0;
457  bu_log("The root solver failed to converge on a solution for %s\n", stp->st_dp->d_namep);
458  if (!reported) {
459  VPRINT("while shooting from:\t", rp->r_pt);
460  VPRINT("while shooting at:\t", rp->r_dir);
461  bu_log("Additional elliptical torus convergence failure details will be suppressed.\n");
462  reported = 1;
463  }
464  }
465  return 0; /* MISS */
466  }
467 
468  /* Only real roots indicate an intersection in real space.
469  *
470  * Look at each root returned; if the imaginary part is zero or
471  * sufficiently close, then use the real part as one value of 't'
472  * for the intersections
473  */
474  for (j = 0, i = 0; j < 4; j++) {
475  if (NEAR_ZERO(val[j].im, 0.0001))
476  k[i++] = val[j].re;
477  }
478 
479  /* reverse above translation by adding distance to all 'k' values. */
480  for (j = 0; j < i; ++j)
481  k[j] -= cor_proj;
482 
483  /* Here, 'i' is number of points found */
484  switch (i) {
485  case 0:
486  return 0; /* No hit */
487 
488  default:
489  bu_log("rt_eto_shot: reduced 4 to %d roots\n", i);
490  bn_pr_roots(stp->st_name, val, 4);
491  return 0; /* No hit */
492 
493  case 2: {
494  /* Sort most distant to least distant. */
495  fastf_t u;
496  if ((u=k[0]) < k[1]) {
497  /* bubble larger towards [0] */
498  k[0] = k[1];
499  k[1] = u;
500  }
501  }
502  break;
503  case 4: {
504  short n;
505  short lim;
506 
507  /* Inline rt_pt_sort(). Sorts k[] into descending order. */
508  for (lim = i-1; lim > 0; lim--) {
509  for (n = 0; n < lim; n++) {
510  fastf_t u;
511  if ((u=k[n]) < k[n+1]) {
512  /* bubble larger towards [0] */
513  k[n] = k[n+1];
514  k[n+1] = u;
515  }
516  }
517  }
518  }
519  break;
520  }
521 
522  /* Now, t[0] > t[npts-1] */
523  /* k[1] is entry point, and k[0] is farthest exit point */
524  RT_GET_SEG(segp, ap->a_resource);
525  segp->seg_stp = stp;
526  segp->seg_in.hit_dist = k[1];
527  segp->seg_out.hit_dist = k[0];
528  segp->seg_in.hit_surfno = 0;
529  segp->seg_out.hit_surfno = 0;
530  /* Set aside vector for rt_eto_norm() later */
531  VJOIN1(segp->seg_in.hit_vpriv, pprime, k[1], dprime);
532  VJOIN1(segp->seg_out.hit_vpriv, pprime, k[0], dprime);
533  BU_LIST_INSERT(&(seghead->l), &(segp->l));
534 
535  if (i == 2)
536  return 2; /* HIT */
537 
538  /* 4 points */
539  /* k[3] is entry point, and k[2] is exit point */
540  RT_GET_SEG(segp, ap->a_resource);
541  segp->seg_stp = stp;
542  segp->seg_in.hit_dist = k[3];
543  segp->seg_out.hit_dist = k[2];
544  segp->seg_in.hit_surfno = 0;
545  segp->seg_out.hit_surfno = 0;
546  VJOIN1(segp->seg_in.hit_vpriv, pprime, k[3], dprime);
547  VJOIN1(segp->seg_out.hit_vpriv, pprime, k[2], dprime);
548  BU_LIST_INSERT(&(seghead->l), &(segp->l));
549  return 4; /* HIT */
550 }
551 
552 
553 /**
554  * Compute the normal to the eto, given a point on the eto centered at
555  * the origin on the X-Y plane. The gradient of the eto at that point
556  * is in fact the normal vector, which will have to be given unit
557  * length. To make this useful for the original eto, it will have to
558  * be rotated back to the orientation of the original eto. The
559  * equation for the eto is:
560  *
561  * _______ ________
562  * / 2 2 2 / 2 2 2
563  * [Eu(+- \/ x + y - R) + Ev z] + [Fu(+-\/ x + y - R) + Fv z ]
564  * -------------------------------- ------------------------------- = 1
565  * 2 2
566  * Rc Rd
567  *
568  * The normal is the gradient of f(x, y, z) = 0 or
569  *
570  * (df/dx, df/dy, df/dz)
571  */
572 void
573 rt_eto_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
574 {
575  struct eto_specific *eto =
576  (struct eto_specific *)stp->st_specific;
577  fastf_t sqrt_x2y2, efact, ffact, xcomp, ycomp, zcomp;
578  vect_t normp;
579 
580  VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
581 
582  sqrt_x2y2 = sqrt(hitp->hit_vpriv[X] * hitp->hit_vpriv[X]
583  + hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y]);
584 
585  efact = 2 * eto->eto_rd * eto->eto_rd * (eto->eu *
586  (sqrt_x2y2 - eto->eto_r) + eto->ev * hitp->hit_vpriv[Z]);
587 
588  ffact = 2 * eto->eto_rc * eto->eto_rc * (eto->fu *
589  (sqrt_x2y2 - eto->eto_r) + eto->fv * hitp->hit_vpriv[Z]);
590 
591  xcomp = (efact * eto->eu + ffact * eto->fu) / sqrt_x2y2;
592 
593  ycomp = hitp->hit_vpriv[Y] * xcomp;
594  xcomp = hitp->hit_vpriv[X] * xcomp;
595  zcomp = efact * eto->ev + ffact * eto->fv;
596 
597  VSET(normp, xcomp, ycomp, zcomp);
598  VUNITIZE(normp);
599  MAT3X3VEC(hitp->hit_normal, eto->eto_invR, normp);
600 }
601 
602 
603 /**
604  * Return the curvature of the eto.
605  */
606 void
607 rt_eto_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
608 {
609  fastf_t a, b, ch, cv, dh, dv, k_circ, k_ell, phi, rad, xp,
610  yp1, yp2, work;
611  struct eto_specific *eto =
612  (struct eto_specific *)stp->st_specific;
613  vect_t Cp, Dp, Hit_Ell, Nu, Radius, Ru;
614 
615  a = eto->eto_rc;
616  b = eto->eto_rd;
617  VMOVE(Nu, eto->eto_N);
618  VUNITIZE(Nu);
619 
620  /* take elliptical slice of eto at hit point */
621  VSET(Ru, hitp->hit_vpriv[X], hitp->hit_vpriv[Y], 0.);
622  VUNITIZE(Ru);
623  VSCALE(Radius, Ru, eto->eto_r);
624 
625  /* get horizontal and vertical components of C and Rd */
626  cv = VDOT(eto->eto_C, Nu);
627  ch = sqrt(VDOT(eto->eto_C, eto->eto_C) - cv * cv);
628  /* angle between C and Nu */
629  phi = acos(cv / MAGNITUDE(eto->eto_C));
630  dv = eto->eto_rd * sin(phi);
631  dh = -eto->eto_rd * cos(phi);
632 
633  /* build coord system for ellipse: x, y directions are Dp, Cp */
634  VCOMB2(Cp, ch, Ru, cv, Nu);
635  VCOMB2(Dp, dh, Ru, dv, Nu);
636  VUNITIZE(Cp);
637  VUNITIZE(Dp);
638 
639  /* put hit point in cross sectional coordinates */
640  VSUB2(Hit_Ell, hitp->hit_vpriv, Radius);
641  xp = VDOT(Hit_Ell, Dp);
642  /* yp = VDOT(Hit_Ell, Cp); */
643 
644  /* calculate curvature along ellipse */
645  /* k = y'' / (1 + y'^2) ^ 3/2 */
646  rad = 1.0 / sqrt(1.0 - xp*xp/(a*a));
647  yp1 = -b/(a*a)*xp*rad;
648  yp2 = -b/(a*a)*rad*(xp*xp*rad*rad + 1.);
649  work = 1 + yp1*yp1;
650  k_ell = yp2 / (work*sqrt(work));
651 
652  /* calculate curvature along radial circle */
653  k_circ = -1.0 / MAGNITUDE(Radius);
654 
655  if (fabs(k_ell) < fabs(k_circ)) {
656  /* use 1st deriv for principle dir of curvature */
657  VCOMB2(cvp->crv_pdir, xp, Dp, yp1, Cp);
658  cvp->crv_c1 = k_ell;
659  cvp->crv_c2 = k_circ;
660  } else {
661  VCROSS(cvp->crv_pdir, hitp->hit_normal, Radius);
662  cvp->crv_c1 = k_circ;
663  cvp->crv_c2 = k_ell;
664  }
665  VUNITIZE(cvp->crv_pdir);
666 }
667 
668 
669 void
670 rt_eto_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
671 {
672  fastf_t horz, theta_u, theta_v, vert;
673  vect_t Hit_Ell, Nu, Radius, Ru;
674 
675  struct eto_specific *eto =
676  (struct eto_specific *)stp->st_specific;
677 
678  if (ap) RT_CK_APPLICATION(ap);
679 
680  /* take elliptical slice of eto at hit point */
681  VSET(Ru, hitp->hit_vpriv[X], hitp->hit_vpriv[Y], 0.);
682  VUNITIZE(Ru);
683  VSCALE(Radius, Ru, eto->eto_r);
684  /* put cross sectional ellipse at origin */
685  VSUB2(Hit_Ell, hitp->hit_vpriv, Radius);
686 
687  /* find angle between Ru and Hit_Ell
688  (better for circle than ellipse...) */
689  VMOVE(Nu, eto->eto_N);
690  VUNITIZE(Nu);
691  vert = VDOT(Hit_Ell, Nu);
692  horz = VDOT(Hit_Ell, Ru);
693  theta_u = atan2(vert, -horz); /* tuck seam on eto inner diameter */
694 
695  /* find angle between hitp and x axis */
696  theta_v = atan2(hitp->hit_vpriv[Y], hitp->hit_vpriv[X]);
697 
698  /* normalize to [0, 2pi] */
699  if (theta_u < 0.)
700  theta_u += M_2PI;
701  if (theta_v < 0.)
702  theta_v += M_2PI;
703 
704  /* normalize to [0, 1] */
705  uvp->uv_u = theta_u/M_2PI;
706  uvp->uv_v = theta_v/M_2PI;
707  uvp->uv_du = uvp->uv_dv = 0;
708 }
709 
710 
711 void
712 rt_eto_free(struct soltab *stp)
713 {
714  struct eto_specific *eto =
715  (struct eto_specific *)stp->st_specific;
716 
717  BU_PUT(eto, struct eto_specific);
718 }
719 
720 
721 /**
722  * Approximate one fourth (1st quadrant) of an ellipse with line
723  * segments. The initial single segment is broken at the point
724  * farthest from the ellipse if that point is not already within the
725  * distance and normal error tolerances. The two resulting segments
726  * are passed recursively to this routine until each segment is within
727  * tolerance.
728  */
729 HIDDEN int
730 make_ellipse4(struct rt_pt_node *pts, fastf_t a, fastf_t b, fastf_t dtol, fastf_t ntol)
731 {
732  fastf_t dist, intr, m, theta0, theta1;
733  int n;
734  point_t mpt, p0, p1;
735  vect_t norm_line, norm_ell;
736  struct rt_pt_node *newpt;
737 
738  /* endpoints of segment approximating ellipse */
739  VMOVE(p0, pts->p);
740  VMOVE(p1, pts->next->p);
741  /* slope and intercept of segment */
742  m = (p1[X] - p0[X]) / (p1[Y] - p0[Y]);
743  intr = p0[X] - m * p0[Y];
744  /* point on ellipse with max dist between ellipse and line */
745  mpt[Y] = a / sqrt(b*b / (m*m*a*a) + 1);
746  mpt[X] = b * sqrt(1 - mpt[Y] * mpt[Y] / (a*a));
747  mpt[Z] = 0;
748  /* max distance between that point and line */
749  dist = fabs(m * mpt[Y] - mpt[X] + intr) / sqrt(m * m + 1);
750  /* angles between normal of line and of ellipse at line endpoints */
751  VSET(norm_line, m, -1., 0.);
752  VSET(norm_ell, b * b * p0[Y], a * a * p0[X], 0.);
753  VUNITIZE(norm_line);
754  VUNITIZE(norm_ell);
755  theta0 = fabs(acos(VDOT(norm_line, norm_ell)));
756  VSET(norm_ell, b * b * p1[Y], a * a * p1[X], 0.);
757  VUNITIZE(norm_ell);
758  theta1 = fabs(acos(VDOT(norm_line, norm_ell)));
759  /* split segment at widest point if not within error tolerances */
760  if (dist > dtol || theta0 > ntol || theta1 > ntol) {
761  /* split segment */
762  BU_ALLOC(newpt, struct rt_pt_node);
763  VMOVE(newpt->p, mpt);
764  newpt->next = pts->next;
765  pts->next = newpt;
766  /* keep track of number of pts added */
767  n = 1;
768  /* recurse on first new segment */
769  n += make_ellipse4(pts, a, b, dtol, ntol);
770  /* recurse on second new segment */
771  n += make_ellipse4(newpt, a, b, dtol, ntol);
772  } else
773  n = 0;
774  return n;
775 }
776 
777 
778 /**
779  * Return pointer an array of points approximating an ellipse with
780  * semi-major and semi-minor axes a and b. The line segments fall
781  * within the normal and distance tolerances of ntol and dtol.
782  */
783 HIDDEN point_t *
784 make_ellipse(int *n, fastf_t a, fastf_t b, fastf_t dtol, fastf_t ntol)
785 {
786  int i;
787  point_t *ell;
788  struct rt_pt_node *ell_quad, *oldpos, *pos;
789 
790  BU_ALLOC(ell_quad, struct rt_pt_node);
791  VSET(ell_quad->p, b, 0., 0.);
792 
793  BU_ALLOC(ell_quad->next, struct rt_pt_node);
794  VSET(ell_quad->next->p, 0., a, 0.);
795  ell_quad->next->next = NULL;
796 
797  *n = make_ellipse4(ell_quad, a, b, dtol, ntol);
798  ell = (point_t *)bu_malloc(4*(*n+1)*sizeof(point_t), "make_ellipse pts");
799 
800  /* put 1st quad of ellipse into an array */
801  pos = ell_quad;
802  for (i = 0; i < *n+2; i++) {
803  VMOVE(ell[i], pos->p);
804  oldpos = pos;
805  pos = pos->next;
806  bu_free((char *)oldpos, "rt_pt_node");
807  }
808  /* mirror 1st quad to make 2nd */
809  for (i = (*n+1)+1; i < 2*(*n+1); i++) {
810  VMOVE(ell[i], ell[(*n*2+2)-i]);
811  ell[i][X] = -ell[i][X];
812  }
813  /* mirror 2nd quad to make 3rd */
814  for (i = 2*(*n+1); i < 3*(*n+1); i++) {
815  VMOVE(ell[i], ell[i-(*n*2+2)]);
816  ell[i][X] = -ell[i][X];
817  ell[i][Y] = -ell[i][Y];
818  }
819  /* mirror 3rd quad to make 4th */
820  for (i = 3*(*n+1); i < 4*(*n+1); i++) {
821  VMOVE(ell[i], ell[i-(*n*2+2)]);
822  ell[i][X] = -ell[i][X];
823  ell[i][Y] = -ell[i][Y];
824  }
825  *n = 4*(*n + 1);
826  return ell;
827 }
828 
829 /* Calculate axis vectors for the circular contour which shows the extent of
830  * the vector with the given projection onto A.
831  */
832 static void
833 eto_contour_axes(
834  vect_t contour_A,
835  vect_t contour_B,
836  vect_t eto_A,
837  vect_t eto_B,
838  fastf_t proj_A)
839 {
840  fastf_t c;
841 
842  c = 1.0 + proj_A / MAGNITUDE(eto_A);
843  VSCALE(contour_A, eto_A, c);
844  VSCALE(contour_B, eto_B, c);
845 }
846 
847 static int
848 eto_ellipse_points(
849  vect_t ellipse_A,
850  vect_t ellipse_B,
851  const struct rt_view_info *info)
852 {
853  fastf_t avg_radius, circumference;
854 
855  avg_radius = (MAGNITUDE(ellipse_A) + MAGNITUDE(ellipse_B)) / 2.0;
856  circumference = M_2PI * avg_radius;
857 
858  return circumference / info->point_spacing;
859 }
860 
861 int
862 rt_eto_adaptive_plot(struct rt_db_internal *ip, const struct rt_view_info *info)
863 {
864  struct rt_eto_internal *eto;
865  fastf_t radian, radian_step;
866  vect_t ellipse_A, ellipse_B, contour_A, contour_B, I, J;
867  vect_t center, cross_AN, eto_V, eto_N, eto_A, eto_B;
868  fastf_t mag_N, mag_ai, mag_aj, mag_bi, mag_bj;
869  int i, num_cross_sections, points_per_ellipse;
870 
871  BU_CK_LIST_HEAD(info->vhead);
872  RT_CK_DB_INTERNAL(ip);
873 
874  eto = (struct rt_eto_internal *)ip->idb_ptr;
875  if (!eto_is_valid(eto)) {
876  return -1;
877  }
878 
879  VMOVE(eto_V, eto->eto_V);
880 
881  VMOVE(eto_N, eto->eto_N);
882  mag_N = MAGNITUDE(eto_N);
883 
884  VMOVE(ellipse_A, eto->eto_C);
885 
886  VCROSS(cross_AN, ellipse_A, eto_N);
887 
888  VCROSS(ellipse_B, ellipse_A, cross_AN);
889  VUNITIZE(ellipse_B);
890  VSCALE(ellipse_B, ellipse_B, eto->eto_rd);
891 
892  VCROSS(eto_A, eto_N, cross_AN);
893  VUNITIZE(eto_A);
894  VSCALE(eto_A, eto_A, eto->eto_r);
895 
896  VCROSS(eto_B, eto_N, eto_A);
897  VUNITIZE(eto_B);
898  VSCALE(eto_B, eto_B, eto->eto_r);
899 
900  /* We want to be able to plot any of the ellipses that result from
901  * intersecting the eto with a plane containing N. The center point of any
902  * such ellipse lies on a vector (R) orthogonal to N, so we can think of
903  * the ellipse as lying in a vector space formed by the unit component
904  * vectors I and J which correspond to to R and N respectively.
905  *
906  * The A and B axis vectors of the ellipse can then be expressed as a
907  * combination of I and J:
908  *
909  * A = (ai)I + (aj)J
910  * B = (bi)I + (bj)J
911  *
912  * The scalars ai, aj, bi, and bj are the scalar projections of A onto I,
913  * A onto J,and B onto I, and B onto J respectively.
914  */
915  VMOVE(I, eto_A);
916  VMOVE(J, eto_N);
917  VUNITIZE(I);
918  VUNITIZE(J);
919 
920  mag_ai = VDOT(ellipse_A, I);
921  mag_aj = VDOT(ellipse_A, J);
922  mag_bi = VDOT(ellipse_B, I);
923  mag_bj = VDOT(ellipse_B, J);
924 
925 
926  /* plot elliptical contour showing extent of ellipse +A/-A */
927  eto_contour_axes(contour_A, contour_B, eto_A, eto_B, mag_ai);
928 
929  points_per_ellipse = eto_ellipse_points(contour_A, contour_B, info);
930 
931  if (points_per_ellipse < 6) {
932  points_per_ellipse = 6;
933  }
934 
935  VJOIN1(center, eto_V, mag_aj / mag_N, eto_N);
936  plot_ellipse(info->vhead, center, contour_A, contour_B, points_per_ellipse);
937 
938  eto_contour_axes(contour_A, contour_B, eto_A, eto_B, -mag_ai);
939  VJOIN1(center, eto_V, -mag_aj / mag_N, eto_N);
940  plot_ellipse(info->vhead, center, contour_A, contour_B, points_per_ellipse);
941 
942  /* plot elliptical contour showing extent of ellipse +B/-B */
943  eto_contour_axes(contour_A, contour_B, eto_A, eto_B, mag_bi);
944 
945  points_per_ellipse = eto_ellipse_points(contour_A, contour_B, info);
946 
947  if (points_per_ellipse < 6) {
948  points_per_ellipse = 6;
949  }
950 
951  VJOIN1(center, eto_V, mag_bj / mag_N, eto_N);
952  plot_ellipse(info->vhead, center, contour_A, contour_B, points_per_ellipse);
953 
954  eto_contour_axes(contour_A, contour_B, eto_A, eto_B, -mag_bi);
955  VJOIN1(center, eto_V, -mag_bj / mag_N, eto_N);
956  plot_ellipse(info->vhead, center, contour_A, contour_B, points_per_ellipse);
957 
958  /* draw elliptical radial cross sections */
959  num_cross_sections = primitive_curve_count(ip, info);
960 
961  if (num_cross_sections < 3) {
962  num_cross_sections = 3;
963  }
964 
965  points_per_ellipse = eto_ellipse_points(eto_A, eto_B, info);
966 
967  if (points_per_ellipse < 6) {
968  points_per_ellipse = 6;
969  }
970 
971  radian_step = M_2PI / num_cross_sections;
972  radian = 0;
973  for (i = 0; i < num_cross_sections; ++i) {
974  ellipse_point_at_radian(center, eto->eto_V, eto_A, eto_B, radian);
975 
976  VMOVE(I, center);
977  VJOIN1(I, I, -1.0, eto->eto_V);
978  VUNITIZE(I);
979 
980  VCOMB2(ellipse_A, mag_ai, I, mag_aj, J);
981  VCOMB2(ellipse_B, mag_bi, I, mag_bj, J);
982 
983  plot_ellipse(info->vhead, center, ellipse_A, ellipse_B, points_per_ellipse);
984 
985  radian += radian_step;
986  }
987 
988  return 0;
989 }
990 
991 /**
992  * The ETO has the following input fields:
993  *
994  * eto_V V from origin to center
995  * eto_r Radius scalar
996  * eto_N Normal to plane of eto
997  * eto_C Semimajor axis (vector) of eto cross section
998  * eto_rd Semiminor axis length (scalar) of eto cross section
999  */
1000 int
1001 rt_eto_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
1002 {
1003  fastf_t a, b; /* axis lengths of ellipse */
1004  fastf_t ang, ch, cv, dh, dv, ntol, dtol, phi, theta;
1005  fastf_t *eto_ells;
1006  int i, j, npts, nells;
1007  point_t *ell; /* array of ellipse points */
1008  point_t Ell_V; /* vertex of an ellipse */
1009  struct rt_eto_internal *tip;
1010  vect_t Au, Bu, Nu, Cp, Dp, Xu;
1011 
1012  BU_CK_LIST_HEAD(vhead);
1013  RT_CK_DB_INTERNAL(ip);
1014 
1015  tip = (struct rt_eto_internal *)ip->idb_ptr;
1016  if (!eto_is_valid(tip)) {
1017  return -1;
1018  }
1019 
1020  a = MAGNITUDE(tip->eto_C);
1021  b = tip->eto_rd;
1022 
1023  if (tip->eto_r < b) {
1024  dtol = primitive_get_absolute_tolerance(ttol, 2.0 * tip->eto_r);
1025  } else {
1026  dtol = primitive_get_absolute_tolerance(ttol, 2.0 * b);
1027  }
1028 
1029  /* To ensure normal tolerance, remain below this angle */
1030  if (ttol->norm > 0.0)
1031  ntol = ttol->norm;
1032  else
1033  /* tolerate everything */
1034  ntol = M_PI;
1035 
1036  /* (x, y) coords for an ellipse */
1037  ell = make_ellipse(&npts, a, b, dtol, ntol);
1038  /* generate coordinate axes */
1039  VMOVE(Nu, tip->eto_N);
1040  VUNITIZE(Nu); /* z axis of coord sys */
1041  bn_vec_ortho(Bu, Nu); /* x axis */
1042  VUNITIZE(Bu);
1043  VCROSS(Au, Nu, Bu); /* y axis */
1044 
1045  /* number of segments required in eto circles */
1046  nells = rt_num_circular_segments(dtol, tip->eto_r);
1047  theta = M_2PI / nells; /* put ellipse every theta rads */
1048  /* get horizontal and vertical components of C and Rd */
1049  cv = VDOT(tip->eto_C, Nu);
1050  ch = sqrt(VDOT(tip->eto_C, tip->eto_C) - cv * cv);
1051  /* angle between C and Nu */
1052  phi = acos(cv / MAGNITUDE(tip->eto_C));
1053  dv = tip->eto_rd * sin(phi);
1054  dh = -tip->eto_rd * cos(phi);
1055 
1056  /* make sure ellipse doesn't overlap itself when revolved */
1057  if (ch > tip->eto_r || dh > tip->eto_r) {
1058  bu_log("eto_plot: revolved ellipse overlaps itself\n");
1059  return -1;
1060  }
1061 
1062  /* get memory for nells ellipses */
1063  eto_ells = (fastf_t *)bu_malloc(nells * npts * sizeof(point_t), "ells[]");
1064 
1065  /* place each ellipse properly to make eto */
1066  for (i = 0, ang = 0.; i < nells; i++, ang += theta) {
1067  /* direction of current ellipse */
1068  VCOMB2(Xu, cos(ang), Bu, sin(ang), Au);
1069  VUNITIZE(Xu);
1070  /* vertex of ellipse */
1071  VJOIN1(Ell_V, tip->eto_V, tip->eto_r, Xu);
1072  /* coord system for ellipse: x, y directions are Dp, Cp */
1073  VCOMB2(Cp, ch, Xu, cv, Nu);
1074  VCOMB2(Dp, dh, Xu, dv, Nu);
1075  VUNITIZE(Cp);
1076  VUNITIZE(Dp);
1077 
1078 /* convert 2D address to index into 1D array */
1079 #define ETO_PT(www, lll) ((((www)%nells)*npts)+((lll)%npts))
1080 #define ETO_PTA(ww, ll) (&eto_ells[ETO_PT(ww, ll)*3])
1081 #define ETO_NMA(ww, ll) (norms[ETO_PT(ww, ll)])
1082 
1083  /* make ellipse */
1084  for (j = 0; j < npts; j++) {
1085  VJOIN2(ETO_PTA(i, j),
1086  Ell_V, ell[j][X], Dp, ell[j][Y], Cp);
1087  }
1088  }
1089 
1090  /* draw ellipses */
1091  for (i = 0; i < nells; i++) {
1092  RT_ADD_VLIST(vhead, ETO_PTA(i, npts-1), BN_VLIST_LINE_MOVE);
1093  for (j = 0; j < npts; j++)
1094  RT_ADD_VLIST(vhead, ETO_PTA(i, j), BN_VLIST_LINE_DRAW);
1095  }
1096 
1097  /* draw connecting circles */
1098  for (i = 0; i < npts; i++) {
1099  RT_ADD_VLIST(vhead, ETO_PTA(nells-1, i), BN_VLIST_LINE_MOVE);
1100  for (j = 0; j < nells; j++)
1101  RT_ADD_VLIST(vhead, ETO_PTA(j, i), BN_VLIST_LINE_DRAW);
1102  }
1103 
1104  bu_free((char *)eto_ells, "ells[]");
1105  return 0;
1106 }
1107 
1108 
1109 int
1110 rt_eto_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
1111 {
1112  fastf_t a, b; /* axis lengths of ellipse */
1113  fastf_t ang, ch, cv, dh, dv, ntol, dtol, phi, theta;
1114  fastf_t *eto_ells = NULL;
1115  int i, j, nfaces, npts, nells;
1116  point_t *ell = NULL; /* array of ellipse points */
1117  point_t Ell_V; /* vertex of an ellipse */
1118  struct rt_eto_internal *tip;
1119  struct shell *s;
1120  struct vertex **verts = NULL;
1121  struct faceuse **faces = NULL;
1122  struct vertex **vertp[4];
1123  vect_t Au, Bu, Nu, Cp, Dp, Xu;
1124  vect_t *norms = NULL; /* normal vectors for each vertex */
1125  int fail = 0;
1126 
1127  RT_CK_DB_INTERNAL(ip);
1128  tip = (struct rt_eto_internal *)ip->idb_ptr;
1129  RT_ETO_CK_MAGIC(tip);
1130 
1131  a = MAGNITUDE(tip->eto_C);
1132  b = tip->eto_rd;
1133 
1134  if (NEAR_ZERO(tip->eto_r, 0.0001) || NEAR_ZERO(b, 0.0001)
1135  || NEAR_ZERO(a, 0.0001)) {
1136  bu_log("eto_tess: r, rd, or rc zero length\n");
1137  fail = (-2);
1138  goto failure;
1139  }
1140 
1141  if (tip->eto_r < b) {
1142  dtol = primitive_get_absolute_tolerance(ttol, 2.0 * tip->eto_r);
1143  } else {
1144  dtol = primitive_get_absolute_tolerance(ttol, 2.0 * b);
1145  }
1146 
1147  /* To ensure normal tolerance, remain below this angle */
1148  if (ttol->norm > 0.0)
1149  ntol = ttol->norm;
1150  else
1151  /* tolerate everything */
1152  ntol = M_PI;
1153 
1154  /* (x, y) coords for an ellipse */
1155  ell = make_ellipse(&npts, a, b, dtol, ntol);
1156  /* generate coordinate axes */
1157  VMOVE(Nu, tip->eto_N);
1158  VUNITIZE(Nu); /* z axis of coord sys */
1159  bn_vec_ortho(Bu, Nu); /* x axis */
1160  VUNITIZE(Bu);
1161  VCROSS(Au, Nu, Bu); /* y axis */
1162 
1163  /* number of segments required in eto circles */
1164  nells = rt_num_circular_segments(dtol, tip->eto_r);
1165  theta = M_2PI / nells; /* put ellipse every theta rads */
1166  /* get horizontal and vertical components of C and Rd */
1167  cv = VDOT(tip->eto_C, Nu);
1168  ch = sqrt(VDOT(tip->eto_C, tip->eto_C) - cv * cv);
1169  /* angle between C and Nu */
1170  phi = acos(cv / MAGNITUDE(tip->eto_C));
1171  dv = tip->eto_rd * sin(phi);
1172  dh = -tip->eto_rd * cos(phi);
1173 
1174  /* make sure ellipse doesn't overlap itself when revolved */
1175  if (ch > tip->eto_r || dh > tip->eto_r) {
1176  bu_log("eto_tess: revolved ellipse overlaps itself\n");
1177  fail = (-3);
1178  goto failure;
1179  }
1180 
1181  /* get memory for nells ellipses */
1182  eto_ells = (fastf_t *)bu_malloc(nells * npts * sizeof(point_t), "ells[]");
1183  norms = (vect_t *)bu_calloc(nells*npts, sizeof(vect_t), "rt_eto_tess: norms");
1184 
1185  /* place each ellipse properly to make eto */
1186  for (i = 0, ang = 0.; i < nells; i++, ang += theta) {
1187  /* direction of current ellipse */
1188  VCOMB2(Xu, cos(ang), Bu, sin(ang), Au);
1189  VUNITIZE(Xu);
1190  /* vertex of ellipse */
1191  VJOIN1(Ell_V, tip->eto_V, tip->eto_r, Xu);
1192  /* coord system for ellipse: x, y directions are Dp, Cp */
1193  VCOMB2(Cp, ch, Xu, cv, Nu);
1194  VCOMB2(Dp, dh, Xu, dv, Nu);
1195  VUNITIZE(Cp);
1196  VUNITIZE(Dp);
1197  /* make ellipse */
1198  for (j = 0; j < npts; j++) {
1199  VJOIN2(ETO_PTA(i, j),
1200  Ell_V, ell[j][X], Dp, ell[j][Y], Cp);
1201  VBLEND2(ETO_NMA(i, j),
1202  a*a*ell[j][X], Dp, b*b*ell[j][Y], Cp);
1203  VUNITIZE(ETO_NMA(i, j));
1204  }
1205  }
1206 
1207  *r = nmg_mrsv(m); /* Make region, empty shell, vertex */
1208  s = BU_LIST_FIRST(shell, &(*r)->s_hd);
1209 
1210  verts = (struct vertex **)bu_calloc(npts*nells, sizeof(struct vertex *),
1211  "rt_eto_tess *verts[]");
1212  faces = (struct faceuse **)bu_calloc(npts*nells, sizeof(struct faceuse *),
1213  "rt_eto_tess *faces[]");
1214 
1215  /* Build the topology of the eto */
1216  nfaces = 0;
1217  for (i = 0; i < nells; i++) {
1218  for (j = 0; j < npts; j++) {
1219  vertp[0] = &verts[ ETO_PT(i+0, j+0) ];
1220  vertp[1] = &verts[ ETO_PT(i+0, j+1) ];
1221  vertp[2] = &verts[ ETO_PT(i+1, j+1) ];
1222  vertp[3] = &verts[ ETO_PT(i+1, j+0) ];
1223  if ((faces[nfaces++] = nmg_cmface(s, vertp, 4)) == (struct faceuse *)0) {
1224  bu_log("rt_eto_tess() nmg_cmface failed, i=%d/%d, j=%d/%d\n",
1225  i, nells, j, npts);
1226  nfaces--;
1227  }
1228  }
1229  }
1230 
1231  /* Associate vertex geometry */
1232  for (i = 0; i < nells; i++) {
1233  for (j = 0; j < npts; j++) {
1234  nmg_vertex_gv(verts[ETO_PT(i, j)], ETO_PTA(i, j));
1235  }
1236  }
1237 
1238  /* Associate face geometry */
1239  for (i = 0; i < nfaces; i++) {
1240  if (nmg_fu_planeeqn(faces[i], tol) < 0) {
1241  fail = (-1);
1242  goto failure;
1243  }
1244  }
1245 
1246  /* associate vertexuse normals */
1247  for (i = 0; i < nells; i++) {
1248  for (j = 0; j < npts; j++) {
1249  struct vertexuse *vu;
1250  vect_t rev_norm;
1251 
1252  VREVERSE(rev_norm, ETO_NMA(i, j));
1253 
1254  NMG_CK_VERTEX(verts[ETO_PT(i, j)]);
1255 
1256  for (BU_LIST_FOR(vu, vertexuse, &verts[ETO_PT(i, j)]->vu_hd)) {
1257  struct faceuse *fu;
1258 
1259  NMG_CK_VERTEXUSE(vu);
1260 
1261  fu = nmg_find_fu_of_vu(vu);
1262  NMG_CK_FACEUSE(fu);
1263 
1264  if (fu->orientation == OT_SAME)
1265  nmg_vertexuse_nv(vu, ETO_NMA(i, j));
1266  else if (fu->orientation == OT_OPPOSITE)
1267  nmg_vertexuse_nv(vu, rev_norm);
1268  }
1269  }
1270  }
1271 
1272  /* Compute "geometry" for region and shell */
1273  nmg_region_a(*r, tol);
1274 
1275  failure:
1276  bu_free((char *)ell, "make_ellipse pts");
1277  bu_free((char *)eto_ells, "ells[]");
1278  bu_free((char *)verts, "rt_eto_tess *verts[]");
1279  bu_free((char *)faces, "rt_eto_tess *faces[]");
1280  bu_free((char *)norms, "rt_eto_tess: norms[]");
1281 
1282  return fail;
1283 }
1284 
1285 
1286 /**
1287  * Import a eto from the database format to the internal format.
1288  * Apply modeling transformations at the same time.
1289  */
1290 int
1291 rt_eto_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
1292 {
1293  struct rt_eto_internal *tip;
1294  union record *rp;
1295  vect_t v1, v2, v3;
1296 
1297  if (dbip) RT_CK_DBI(dbip);
1298 
1299  BU_CK_EXTERNAL(ep);
1300  rp = (union record *)ep->ext_buf;
1301  /* Check record type */
1302  if (rp->u_id != ID_SOLID) {
1303  bu_log("rt_eto_import4: defective record\n");
1304  return -1;
1305  }
1306 
1307  RT_CK_DB_INTERNAL(ip);
1308  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
1309  ip->idb_type = ID_ETO;
1310  ip->idb_meth = &OBJ[ID_ETO];
1311  BU_ALLOC(ip->idb_ptr, struct rt_eto_internal);
1312 
1313  tip = (struct rt_eto_internal *)ip->idb_ptr;
1314  tip->eto_magic = RT_ETO_INTERNAL_MAGIC;
1315 
1316  /* Apply modeling transformations */
1317  if (mat == NULL) mat = bn_mat_identity;
1318 
1319  if (dbip->dbi_version < 0) {
1320  flip_fastf_float(v1, &rp->s.s_values[0*3], 1, 1);
1321  flip_fastf_float(v2, &rp->s.s_values[1*3], 1, 1);
1322  flip_fastf_float(v3, &rp->s.s_values[2*3], 1, 1);
1323  } else {
1324  VMOVE(v1, &rp->s.s_values[0*3]);
1325  VMOVE(v2, &rp->s.s_values[1*3]);
1326  VMOVE(v3, &rp->s.s_values[2*3]);
1327  }
1328 
1329  MAT4X3PNT(tip->eto_V, mat, v1);
1330  MAT4X3VEC(tip->eto_N, mat, v2);
1331  MAT4X3VEC(tip->eto_C, mat, v3);
1332 
1333  if (dbip->dbi_version < 0) {
1334  v1[X] = flip_dbfloat(rp->s.s_values[3*3+0]);
1335  v1[Y] = flip_dbfloat(rp->s.s_values[3*3+1]);
1336  } else {
1337  v1[X] = rp->s.s_values[3*3+0];
1338  v1[Y] = rp->s.s_values[3*3+1];
1339  }
1340 
1341  tip->eto_r = v1[X] / mat[15];
1342  tip->eto_rd = v1[Y] / mat[15];
1343 
1344  if (tip->eto_r <= SMALL || tip->eto_rd <= SMALL) {
1345  bu_log("rt_eto_import4: zero length R or Rd vector\n");
1346  return -1;
1347  }
1348 
1349  return 0; /* OK */
1350 }
1351 
1352 
1353 /**
1354  * The name will be added by the caller.
1355  */
1356 int
1357 rt_eto_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
1358 {
1359  struct rt_eto_internal *tip;
1360  union record *eto;
1361 
1362  if (dbip) RT_CK_DBI(dbip);
1363 
1364  RT_CK_DB_INTERNAL(ip);
1365  if (ip->idb_type != ID_ETO) return -1;
1366 
1367  tip = (struct rt_eto_internal *)ip->idb_ptr;
1368  if (!eto_is_valid(tip)) {
1369  return -1;
1370  }
1371 
1372  BU_CK_EXTERNAL(ep);
1373  ep->ext_nbytes = sizeof(union record);
1374  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "eto external");
1375  eto = (union record *)ep->ext_buf;
1376 
1377  eto->s.s_id = ID_SOLID;
1378  eto->s.s_type = ETO;
1379 
1380  /* Warning: type conversion */
1381  VSCALE(&eto->s.s_values[0*3], tip->eto_V, local2mm);
1382  VSCALE(&eto->s.s_values[1*3], tip->eto_N, local2mm);
1383  VSCALE(&eto->s.s_values[2*3], tip->eto_C, local2mm);
1384  eto->s.s_values[3*3] = tip->eto_r * local2mm;
1385  eto->s.s_values[3*3+1] = tip->eto_rd * local2mm;
1386 
1387  return 0;
1388 }
1389 
1390 
1391 /**
1392  * Import a eto from the database format to the internal format.
1393  * Apply modeling transformations at the same time.
1394  */
1395 int
1396 rt_eto_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
1397 {
1398  struct rt_eto_internal *tip;
1399 
1400  /* must be double for import and export */
1401  double vec[11];
1402 
1403  if (dbip) RT_CK_DBI(dbip);
1404  BU_CK_EXTERNAL(ep);
1405 
1407 
1408  RT_CK_DB_INTERNAL(ip);
1409  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
1410  ip->idb_type = ID_ETO;
1411  ip->idb_meth = &OBJ[ID_ETO];
1412  BU_ALLOC(ip->idb_ptr, struct rt_eto_internal);
1413 
1414  tip = (struct rt_eto_internal *)ip->idb_ptr;
1415  tip->eto_magic = RT_ETO_INTERNAL_MAGIC;
1416 
1417  /* Convert from database (network) to internal (host) format */
1418  bu_cv_ntohd((unsigned char *)vec, ep->ext_buf, 11);
1419 
1420  /* Apply modeling transformations */
1421  if (mat == NULL) mat = bn_mat_identity;
1422  MAT4X3PNT(tip->eto_V, mat, &vec[0*3]);
1423  MAT4X3VEC(tip->eto_N, mat, &vec[1*3]);
1424  MAT4X3VEC(tip->eto_C, mat, &vec[2*3]);
1425  tip->eto_r = vec[3*3] / mat[15];
1426  tip->eto_rd = vec[3*3+1] / mat[15];
1427 
1428  if (!eto_is_valid(tip)) {
1429  return -1;
1430  }
1431 
1432  return 0; /* OK */
1433 }
1434 
1435 
1436 /**
1437  * The name will be added by the caller.
1438  */
1439 int
1440 rt_eto_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
1441 {
1442  struct rt_eto_internal *tip;
1443 
1444  /* must be double for import and export */
1445  double vec[11];
1446 
1447  if (dbip) RT_CK_DBI(dbip);
1448 
1449  RT_CK_DB_INTERNAL(ip);
1450  if (ip->idb_type != ID_ETO) return -1;
1451 
1452  tip = (struct rt_eto_internal *)ip->idb_ptr;
1453  if (!eto_is_valid(tip)) {
1454  return -1;
1455  }
1456 
1457  BU_CK_EXTERNAL(ep);
1458  ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * 11;
1459  ep->ext_buf = (uint8_t *)bu_malloc(ep->ext_nbytes, "eto external");
1460 
1461  /* scale 'em into local buffer */
1462  VSCALE(&vec[0*3], tip->eto_V, local2mm);
1463  VSCALE(&vec[1*3], tip->eto_N, local2mm);
1464  VSCALE(&vec[2*3], tip->eto_C, local2mm);
1465  vec[3*3] = tip->eto_r * local2mm;
1466  vec[3*3+1] = tip->eto_rd * local2mm;
1467 
1468  /* Convert from internal (host) to database (network) format */
1469  bu_cv_htond(ep->ext_buf, (unsigned char *)vec, 11);
1470 
1471  return 0;
1472 }
1473 
1474 
1475 /**
1476  * Make human-readable formatted presentation of this solid. First
1477  * line describes type of solid. Additional lines are indented one
1478  * tab, and give parameter values.
1479  */
1480 int
1481 rt_eto_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
1482 {
1483  struct rt_eto_internal *tip =
1484  (struct rt_eto_internal *)ip->idb_ptr;
1485  char buf[256];
1486 
1487  RT_ETO_CK_MAGIC(tip);
1488  bu_vls_strcat(str, "Elliptical Torus (ETO)\n");
1489 
1490  sprintf(buf, "\tV (%g, %g, %g)\n",
1491  INTCLAMP(tip->eto_V[X] * mm2local),
1492  INTCLAMP(tip->eto_V[Y] * mm2local),
1493  INTCLAMP(tip->eto_V[Z] * mm2local));
1494  bu_vls_strcat(str, buf);
1495 
1496  sprintf(buf, "\tN=(%g, %g, %g)\n",
1497  INTCLAMP(tip->eto_N[X] * mm2local),
1498  INTCLAMP(tip->eto_N[Y] * mm2local),
1499  INTCLAMP(tip->eto_N[Z] * mm2local));
1500  bu_vls_strcat(str, buf);
1501 
1502  sprintf(buf, "\tC=(%g, %g, %g) mag=%g\n",
1503  INTCLAMP(tip->eto_C[X] * mm2local),
1504  INTCLAMP(tip->eto_C[Y] * mm2local),
1505  INTCLAMP(tip->eto_C[Z] * mm2local),
1506  INTCLAMP(MAGNITUDE(tip->eto_C) * mm2local));
1507  bu_vls_strcat(str, buf);
1508 
1509  if (!verbose)
1510  return 0;
1511 
1512  sprintf(buf, "\tr=%g\n", INTCLAMP(tip->eto_r * mm2local));
1513  bu_vls_strcat(str, buf);
1514 
1515  sprintf(buf, "\td=%g\n", INTCLAMP(tip->eto_rd * mm2local));
1516  bu_vls_strcat(str, buf);
1517 
1518  return 0;
1519 }
1520 
1521 
1522 /**
1523  * Free the storage associated with the rt_db_internal version of this solid.
1524  */
1525 void
1527 {
1528  struct rt_eto_internal *tip;
1529 
1530  RT_CK_DB_INTERNAL(ip);
1531 
1532  tip = (struct rt_eto_internal *)ip->idb_ptr;
1533  RT_ETO_CK_MAGIC(tip);
1534 
1535  bu_free((char *)tip, "eto ifree");
1536  ip->idb_ptr = ((void *)0); /* sanity */
1537 }
1538 
1539 
1540 int
1541 rt_eto_params(struct pc_pc_set *ps, const struct rt_db_internal *ip)
1542 {
1543  if (!ps) return 0;
1544  if (ip) RT_CK_DB_INTERNAL(ip);
1545 
1546  return 0; /* OK */
1547 }
1548 
1549 
1550 void
1551 rt_eto_volume(fastf_t *vol, const struct rt_db_internal *ip)
1552 {
1553  fastf_t mag_c;
1554  struct rt_eto_internal *tip = (struct rt_eto_internal *)ip->idb_ptr;
1555  RT_ETO_CK_MAGIC(tip);
1556 
1557  mag_c = MAGNITUDE(tip->eto_C);
1558  *vol = 2.0 * M_PI * M_PI * tip->eto_r * tip->eto_rd * mag_c;
1559 }
1560 
1561 
1562 void
1563 rt_eto_centroid(point_t *cent, const struct rt_db_internal *ip)
1564 {
1565  struct rt_eto_internal *tip = (struct rt_eto_internal *)ip->idb_ptr;
1566  RT_ETO_CK_MAGIC(tip);
1567  VMOVE(*cent, tip->eto_V);
1568 }
1569 
1570 
1571 void
1572 rt_eto_surf_area(fastf_t *area, const struct rt_db_internal *ip)
1573 {
1574  fastf_t circum, mag_c;
1575  struct rt_eto_internal *tip = (struct rt_eto_internal *)ip->idb_ptr;
1576  RT_ETO_CK_MAGIC(tip);
1577 
1578  mag_c = MAGNITUDE(tip->eto_C);
1579  /* approximation */
1580  circum = ELL_CIRCUMFERENCE(mag_c, tip->eto_rd);
1581  *area = M_2PI * tip->eto_r * circum;
1582 }
1583 
1584 static int
1585 eto_is_valid(struct rt_eto_internal *eto)
1586 {
1587  RT_ETO_CK_MAGIC(eto);
1588 
1589  /* check all vector magnitudes are positive */
1590  if (MAGNITUDE(eto->eto_N) < RT_LEN_TOL
1591  || MAGNITUDE(eto->eto_C) < RT_LEN_TOL
1592  || eto->eto_r < RT_LEN_TOL
1593  || eto->eto_rd < RT_LEN_TOL)
1594  {
1595  return 0;
1596  }
1597 
1598  /* require major axis to be longer than minor axis */
1599  if (eto->eto_rd > MAGNITUDE(eto->eto_C)) {
1600  return 0;
1601  }
1602 
1603  return 1;
1604 }
1605 
1606 /** @} */
1607 /*
1608  * Local Variables:
1609  * mode: C
1610  * tab-width: 8
1611  * indent-tabs-mode: t
1612  * c-file-style: "stroustrup"
1613  * End:
1614  * ex: shiftwidth=4 tabstop=8
1615  */
Definition: db_flip.c:35
char * d_namep
pointer to name string
Definition: raytrace.h:859
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
Definition: raytrace.h:800
#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
int rt_eto_params(struct pc_pc_set *ps, const struct rt_db_internal *ip)
Definition: eto.c:1541
#define SIZEOF_NETWORK_DOUBLE
Definition: cv.h:48
mat_t eto_invR
Definition: eto.c:139
fastf_t C[2 *MAX_CNT+1][2 *MAX_CNT+1]
Definition: dsp_brep.cpp:38
Definition: list.h:118
int nmg_fu_planeeqn(struct faceuse *fu, const struct bn_tol *tol)
Definition: nmg_mod.c:1311
const struct directory * st_dp
Directory entry of solid.
Definition: raytrace.h:436
vect_t eto_V
Definition: eto.c:132
fastf_t eto_rd
Definition: eto.c:137
#define SMALL
Definition: defines.h:351
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
int rt_eto_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
Definition: eto.c:336
#define RT_CK_RTI(_p)
Definition: raytrace.h:1833
fastf_t fv
Definition: eto.c:140
vect_t eto_N
Definition: eto.c:133
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
#define VSET(a, b, c, d)
Definition: color.c:53
Definition: raytrace.h:215
void bn_pr_roots(const char *title, const struct bn_complex roots[], int n)
#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
#define ETO_NMA(ww, ll)
fastf_t st_aradius
Radius of APPROXIMATING sphere.
Definition: raytrace.h:433
int rt_eto_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
Definition: eto.c:1481
Header file for the BRL-CAD common definitions.
void nmg_vertexuse_nv(struct vertexuse *vu, const fastf_t *norm)
Definition: nmg_mk.c:1719
Definition: poly.h:47
void flip_fastf_float(fastf_t *ff, const dbfloat_t *fp, int n, int flip)
Definition: db_flip.c:74
void rt_eto_centroid(point_t *cent, const struct rt_db_internal *ip)
Definition: eto.c:1563
const struct bu_structparse rt_eto_parse[]
Definition: eto.c:144
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
void bu_cv_htond(unsigned char *out, const unsigned char *in, size_t count)
void rt_eto_free(struct soltab *stp)
Definition: eto.c:712
#define HIDDEN
Definition: common.h:86
int rt_eto_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: eto.c:1110
struct bu_list l
Definition: raytrace.h:369
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
void rt_eto_surf_area(fastf_t *area, const struct rt_db_internal *ip)
Definition: eto.c:1572
if(share_geom)
Definition: nmg_mod.c:3829
int idb_major_type
Definition: raytrace.h:192
void rt_eto_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
Definition: eto.c:607
Definition: color.c:49
void rt_eto_print(const struct soltab *stp)
Definition: eto.c:289
vect_t hit_vpriv
PRIVATE vector for xxx_*()
Definition: raytrace.h:253
struct bu_list * vhead
Definition: raytrace.h:1926
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
void bn_mat_print(const char *title, const mat_t m)
Definition: mat.c:81
#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
void rt_eto_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
Definition: eto.c:670
fastf_t crv_c2
curvature in other direction
Definition: raytrace.h:309
fastf_t ev
Definition: eto.c:140
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
int rt_eto_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: eto.c:1396
fastf_t uv_dv
delta in v
Definition: raytrace.h:344
void bn_mat_inv(mat_t output, const mat_t input)
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
#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
void rt_eto_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
Definition: eto.c:573
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
fastf_t flip_dbfloat(dbfloat_t d)
Definition: db_flip.c:58
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
int rt_eto_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: eto.c:1291
void rt_eto_volume(fastf_t *vol, const struct rt_db_internal *ip)
Definition: eto.c:1551
struct faceuse * nmg_find_fu_of_vu(const struct vertexuse *vu)
Definition: nmg_info.c:304
Support for uniform tolerances.
Definition: tol.h:71
int rt_eto_adaptive_plot(struct rt_db_internal *ip, const struct rt_view_info *info)
Definition: eto.c:862
void rt_eto_ifree(struct rt_db_internal *ip)
Definition: eto.c:1526
#define bu_offsetofarray(_t, _a, _d, _i)
Definition: parse.h:65
struct nmgregion * nmg_mrsv(struct model *m)
Definition: nmg_mk.c:306
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
fastf_t fu
Definition: eto.c:140
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
fastf_t eu
Definition: eto.c:140
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
fastf_t primitive_curve_count(struct rt_db_internal *ip, const struct rt_view_info *info)
#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
mat_t eto_R
Definition: eto.c:138
fastf_t point_spacing
Definition: raytrace.h:1934
void * idb_ptr
Definition: raytrace.h:195
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
fastf_t eto_r
Definition: eto.c:135
point_t st_min
min X, Y, Z of bounding RPP
Definition: raytrace.h:437
#define RT_ETO_INTERNAL_MAGIC
Definition: magic.h:93
void bu_cv_ntohd(unsigned char *out, const unsigned char *in, size_t count)
const struct rt_functab OBJ[]
Definition: table.c:159
int rt_poly_roots(bn_poly_t *eqn, bn_complex_t roots[], const char *name)
int rt_eto_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: eto.c:1440
void bn_vec_ortho(vect_t out, const vect_t in)
#define ETO_PTA(ww, ll)
void * st_specific
-> ID-specific (private) struct
Definition: raytrace.h:435
fastf_t uv_du
delta in u
Definition: raytrace.h:343
point_t p
a point
Definition: raytrace.h:1911
int rt_eto_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol, const struct rt_view_info *info)
Definition: eto.c:1001
fastf_t crv_c1
curvature in principle dir
Definition: raytrace.h:308
Definition: color.c:51
int dbi_version
PRIVATE: use db_version()
Definition: raytrace.h:824
void plot_ellipse(struct bu_list *vhead, const vect_t t, const vect_t a, const vect_t b, int num_points)
double norm
normal tol
Definition: raytrace.h:182
int rt_eto_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: eto.c:1357
HIDDEN point_t * make_ellipse(int *n, fastf_t a, fastf_t b, fastf_t dtol, fastf_t ntol)
Definition: eto.c:784
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
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 ELL_CIRCUMFERENCE(a, b)
Definition: librt_private.h:40
#define BU_CK_EXTERNAL(_p)
Definition: parse.h:224
int rt_num_circular_segments(double maxerr, double radius)
Definition: tor.c:940
#define ETO_PT(www, lll)
struct faceuse * nmg_cmface(struct shell *s, struct vertex ***verts, int n)
Definition: nmg_mod.c:979
Complex numbers.
Definition: complex.h:39
vect_t eto_C
Definition: eto.c:134
fastf_t eto_rc
Definition: eto.c:136
size_t ext_nbytes
Definition: parse.h:210
void ellipse_point_at_radian(point_t result, const vect_t center, const vect_t axis_a, const vect_t axis_b, fastf_t radian)
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
HIDDEN void verbose(struct human_data_t *dude)
Definition: human.c:2008
Definition: vls.h:56
#define ID_ETO
Elliptical Torus.
Definition: raytrace.h:479
double fastf_t
Definition: defines.h:300
#define VPRINT(a, b)
Definition: raytrace.h:1881
int rt_eto_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: eto.c:221
int rt_eto_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *tol)
Definition: eto.c:157
Definition: color.c:50
HIDDEN int make_ellipse4(struct rt_pt_node *pts, fastf_t a, fastf_t b, fastf_t dtol, fastf_t ntol)
Definition: eto.c:730
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
fastf_t uv_v
Range 0..1.
Definition: raytrace.h:342
void nmg_region_a(struct nmgregion *r, const struct bn_tol *tol)
Definition: nmg_mk.c:2557