BRL-CAD
revolve.c
Go to the documentation of this file.
1 /* R E V O L V E . 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/revolve/revolve.c
23  *
24  * Intersect a ray with an 'revolve' primitive object.
25  *
26  */
27 /** @} */
28 
29 #include "common.h"
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <math.h>
34 
35 #include "vmath.h"
36 #include "bu/cv.h"
37 #include "bu/debug.h"
38 #include "db.h"
39 #include "nmg.h"
40 #include "rtgeom.h"
41 #include "raytrace.h"
42 
43 /* local interface header */
44 #include "./revolve.h"
45 
46 
47 #define START_FACE_POS -1
48 #define START_FACE_NEG -2
49 #define END_FACE_POS -3
50 #define END_FACE_NEG -4
51 #define HORIZ_SURF -5
52 
53 #define MAX_HITS 64
54 
55 
56 /* some sketch routines called here */
57 extern int rt_sketch_contains(struct rt_sketch_internal *, point2d_t);
58 extern void rt_sketch_bounds(struct rt_sketch_internal *, fastf_t *);
59 
60 /**
61  * Routine to make a new REVOLVE solid. The only purpose of this routine
62  * is to initialize the internal to legal values (e.g., vls)
63  */
64 void
65 rt_revolve_make(const struct rt_functab *ftp, struct rt_db_internal *intern)
66 {
67  struct rt_revolve_internal *rev;
68 
69  intern->idb_major_type = DB5_MAJORTYPE_BRLCAD;
70  intern->idb_type = ID_REVOLVE;
71  BU_ASSERT(&OBJ[intern->idb_type] == ftp);
72 
73  intern->idb_meth = ftp;
74  BU_ALLOC(rev, struct rt_revolve_internal);
75 
76  intern->idb_ptr = (void *)rev;
77  rev->magic = RT_REVOLVE_INTERNAL_MAGIC;
78 
79  BU_VLS_INIT(&rev->sketch_name);
80  rev->skt = NULL;
81 }
82 
83 
84 /**
85  * Calculate a bounding RPP around a sketch
86  */
87 int
88 rt_revolve_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) {
89  struct rt_revolve_internal *rip;
90  vect_t zUnit;
91  fastf_t bounds[4]; /* 2D sketch bounds */
92  fastf_t radius;
93  point_t center;
94 
95  int *endcount = NULL;
96  size_t nseg, i, j, k;
97 
99  rip = (struct rt_revolve_internal *)ip->idb_ptr;
100  RT_REVOLVE_CK_MAGIC(rip);
101 
102  /* if there's no sketch, there's no bounding box */
103  if (!rip->skt || rip->skt->vert_count < 1) {
104  return -1;
105  }
106 
107  /* count the number of times an endpoint is used:
108  * if even, the point is ok
109  * if odd, the point is at the end of a path
110  */
111  endcount = (int *)bu_calloc(rip->skt->vert_count, sizeof(int), "endcount");
112  nseg = rip->skt->curve.count;
113 
114  for (i=0; i<nseg; i++) {
115  uint32_t *lng;
116  struct line_seg *lsg;
117  struct carc_seg *csg;
118  struct nurb_seg *nsg;
119  struct bezier_seg *bsg;
120 
121  lng = (uint32_t *)rip->skt->curve.segment[i];
122 
123  switch (*lng) {
124  case CURVE_LSEG_MAGIC:
125  lsg = (struct line_seg *)lng;
126  endcount[lsg->start]++;
127  endcount[lsg->end]++;
128  break;
129  case CURVE_CARC_MAGIC:
130  csg = (struct carc_seg *)lng;
131  if (csg->radius <= 0.0) break;
132  endcount[csg->start]++;
133  endcount[csg->end]++;
134  break;
135  case CURVE_BEZIER_MAGIC:
136  bsg = (struct bezier_seg *)lng;
137  endcount[bsg->ctl_points[0]]++;
138  endcount[bsg->ctl_points[bsg->degree]]++;
139  break;
140  case CURVE_NURB_MAGIC:
141  nsg = (struct nurb_seg *)lng;
142  endcount[nsg->ctl_points[0]]++;
143  endcount[nsg->ctl_points[nsg->c_size-1]]++;
144  break;
145  default:
146  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
147  break;
148  }
149  }
150 
151  /* convert endcounts to store which endpoints are odd */
152  for (i=0, j=0; i<rip->skt->vert_count; i++) {
153  if (endcount[i] % 2 != 0) {
154  /* add 'i' to list, insertion sort by vert[i][Y] */
155  for (k=j; k>0; k--) {
156  if ((ZERO(rip->skt->verts[i][Y] - rip->skt->verts[endcount[k-1]][Y])
157  && rip->skt->verts[i][X] > rip->skt->verts[endcount[k-1]][X])
158  || (!ZERO(rip->skt->verts[i][Y] - rip->skt->verts[endcount[k-1]][Y])
159  && rip->skt->verts[i][Y] < rip->skt->verts[endcount[k-1]][Y])) {
160  endcount[k] = endcount[k-1];
161  } else {
162  break;
163  }
164  }
165  endcount[k] = i;
166  j++;
167  }
168  }
169  while (j < rip->skt->vert_count)
170  endcount[j++] = -1;
171 
172  VMOVE(zUnit, rip->axis3d);
173  VUNITIZE(zUnit);
174 
175  /* bounding volume */
176  rt_sketch_bounds(rip->skt, bounds);
177  if (endcount[0] != -1 && bounds[0] > 0) bounds[0] = 0;
178  VJOIN1(center, rip->v3d, 0.5*(bounds[2]+bounds[3]), zUnit);
179  radius = sqrt(0.25*(bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + FMAX(bounds[0]*bounds[0], bounds[1]*bounds[1]));
180 
181  /* cheat, make bounding RPP by enclosing bounding sphere (copied from g_ehy.c) */
182  (*min)[X] = center[X] - radius;
183  (*max)[X] = center[X] + radius;
184  (*min)[Y] = center[Y] - radius;
185  (*max)[Y] = center[Y] + radius;
186  (*min)[Z] = center[Z] - radius;
187  (*max)[Z] = center[Z] + radius;
188 
189  bu_free(endcount, "endcount");
190 
191  return 0; /* OK */
192 }
193 
194 /**
195  * Given a pointer to a GED database record, and a transformation
196  * matrix, determine if this is a valid REVOLVE, and if so, precompute
197  * various terms of the formula.
198  *
199  * Returns -
200  * 0 REVOLVE is OK
201  * !0 Error in description
202  *
203  * Implicit return -
204  * A struct revolve_specific is created, and its address is stored
205  * in stp->st_specific for use by revolve_shot().
206  */
207 int
208 rt_revolve_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
209 {
210  struct rt_revolve_internal *rip;
211  struct revolve_specific *rev;
212 
213  vect_t xEnd, yEnd;
214 
215  int *endcount = NULL;
216  size_t nseg, i, j, k;
217 
218  if (rtip) RT_CK_RTI(rtip);
219 
220  RT_CK_DB_INTERNAL(ip);
221  rip = (struct rt_revolve_internal *)ip->idb_ptr;
222  RT_REVOLVE_CK_MAGIC(rip);
223 
224  /* if there's no sketch, there's nothing to do */
225  if (!rip->skt || rip->skt->vert_count < 1) {
226  return -1;
227  }
228 
229  stp->st_id = ID_REVOLVE;
230  stp->st_meth = &OBJ[ID_REVOLVE];
231 
232  BU_GET(rev, struct revolve_specific);
233  stp->st_specific = (void *)rev;
234 
235  VMOVE(rev->v3d, rip->v3d);
236  VMOVE(rev->zUnit, rip->axis3d);
237  VMOVE(rev->xUnit, rip->r);
238  VCROSS(rev->yUnit, rev->zUnit, rev->xUnit);
239 
240  VUNITIZE(rev->xUnit);
241  VUNITIZE(rev->yUnit);
242  VUNITIZE(rev->zUnit);
243 
244  rev->ang = rip->ang;
245  rev->sketch_name = bu_vls_addr(&rip->sketch_name);
246  rev->skt = rip->skt;
247 
248  /* calculate end plane */
249  VSCALE(xEnd, rev->xUnit, cos(rev->ang));
250  VSCALE(yEnd, rev->yUnit, sin(rev->ang));
251  VADD2(rev->rEnd, xEnd, yEnd);
252  VUNITIZE(rev->rEnd);
253 
254  /* check the sketch - degree & closed/open */
255 
256  /* count the number of times an endpoint is used:
257  * if even, the point is ok
258  * if odd, the point is at the end of a path
259  */
260  endcount = (int *)bu_calloc(rev->skt->vert_count, sizeof(int), "endcount");
261  nseg = rev->skt->curve.count;
262 
263  for (i=0; i<nseg; i++) {
264  uint32_t *lng;
265  struct line_seg *lsg;
266  struct carc_seg *csg;
267  struct nurb_seg *nsg;
268  struct bezier_seg *bsg;
269 
270  lng = (uint32_t *)rev->skt->curve.segment[i];
271 
272  switch (*lng) {
273  case CURVE_LSEG_MAGIC:
274  lsg = (struct line_seg *)lng;
275  endcount[lsg->start]++;
276  endcount[lsg->end]++;
277  break;
278  case CURVE_CARC_MAGIC:
279  csg = (struct carc_seg *)lng;
280  if (csg->radius <= 0.0) break;
281  endcount[csg->start]++;
282  endcount[csg->end]++;
283  break;
284  case CURVE_BEZIER_MAGIC:
285  bsg = (struct bezier_seg *)lng;
286  endcount[bsg->ctl_points[0]]++;
287  endcount[bsg->ctl_points[bsg->degree]]++;
288  break;
289  case CURVE_NURB_MAGIC:
290  nsg = (struct nurb_seg *)lng;
291  endcount[nsg->ctl_points[0]]++;
292  endcount[nsg->ctl_points[nsg->c_size-1]]++;
293  break;
294  default:
295  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
296  break;
297  }
298  }
299 
300  /* convert endcounts to store which endpoints are odd */
301  for (i=0, j=0; i<rip->skt->vert_count; i++) {
302  if (endcount[i] % 2 != 0) {
303  /* add 'i' to list, insertion sort by vert[i][Y] */
304  for (k=j; k>0; k--) {
305  if ((ZERO(rip->skt->verts[i][Y] - rip->skt->verts[endcount[k-1]][Y])
306  && rip->skt->verts[i][X] > rip->skt->verts[endcount[k-1]][X])
307  || (!ZERO(rip->skt->verts[i][Y] - rip->skt->verts[endcount[k-1]][Y])
308  && rip->skt->verts[i][Y] < rip->skt->verts[endcount[k-1]][Y])) {
309  endcount[k] = endcount[k-1];
310  } else {
311  break;
312  }
313  }
314  endcount[k] = i;
315  j++;
316  }
317  }
318  while (j < rev->skt->vert_count)
319  endcount[j++] = -1;
320 
321  rev->ends = endcount;
322 
323  /* bounding volume */
324  rt_sketch_bounds(rev->skt, rev->bounds);
325  if (endcount[0] != -1 && rev->bounds[0] > 0) rev->bounds[0] = 0;
326  VJOIN1(stp->st_center, rev->v3d, 0.5*(rev->bounds[2]+rev->bounds[3]), rev->zUnit);
327  stp->st_aradius = sqrt(0.25*(rev->bounds[3]-rev->bounds[2])*(rev->bounds[3]-rev->bounds[2]) + FMAX(rev->bounds[0]*rev->bounds[0], rev->bounds[1]*rev->bounds[1]));
328  stp->st_bradius = stp->st_aradius;
329 
330  /* cheat, make bounding RPP by enclosing bounding sphere (copied from g_ehy.c) */
331  stp->st_min[X] = stp->st_center[X] - stp->st_bradius;
332  stp->st_max[X] = stp->st_center[X] + stp->st_bradius;
333  stp->st_min[Y] = stp->st_center[Y] - stp->st_bradius;
334  stp->st_max[Y] = stp->st_center[Y] + stp->st_bradius;
335  stp->st_min[Z] = stp->st_center[Z] - stp->st_bradius;
336  stp->st_max[Z] = stp->st_center[Z] + stp->st_bradius;
337 
338  return 0; /* OK */
339 }
340 
341 
342 void
343 rt_revolve_print(const struct soltab *stp)
344 {
345  const struct revolve_specific *rev =
346  (struct revolve_specific *)stp->st_specific;
347 
348  VPRINT("V", rev->v3d);
349  VPRINT("Axis", rev->zUnit);
350  VPRINT("Start", rev->xUnit);
351  VPRINT("End", rev->rEnd);
352  fprintf(stderr, "angle = %g\n", rev->ang);
353  fprintf(stderr, "sketch = %s\n", rev->sketch_name);
354 }
355 
356 
357 /**
358  * Intersect a ray with a revolve. If an intersection occurs, a struct
359  * seg will be acquired and filled in.
360  *
361  * Returns -
362  * 0 MISS
363  * >0 HIT
364  */
365 int
366 rt_revolve_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
367 {
368  struct revolve_specific *rev =
369  (struct revolve_specific *)stp->st_specific;
370  struct seg *segp;
371 
372  struct hit *hitp;
373  struct hit *hits[MAX_HITS], hit[MAX_HITS];
374 
375  size_t i, j, nseg, nhits;
376  int in, out;
377 
378  fastf_t k, m, h, aa, bb;
379  point_t dp, pr, xlated;
380  vect_t vr, ur, norm, normS, normE;
381 
382  fastf_t start, end, angle;
383 
384  vect_t dir;
385  point_t hit1, hit2;
386  point2d_t hit2d, pt1, pt2;
387  fastf_t a, b, c, disc, k1, k2, t1, t2;
388  uint32_t *lng;
389  struct line_seg *lsg;
390  struct carc_seg *csg;
391 
392  nhits = 0;
393 
394  for (i=0; i<MAX_HITS; i++) hits[i] = &hit[i];
395 
396  vr[X] = VDOT(rev->xUnit, rp->r_dir);
397  vr[Y] = VDOT(rev->yUnit, rp->r_dir);
398  vr[Z] = VDOT(rev->zUnit, rp->r_dir);
399 
400  VSUB2(xlated, rp->r_pt, rev->v3d);
401  pr[X] = VDOT(rev->xUnit, xlated);
402  pr[Y] = VDOT(rev->yUnit, xlated);
403  pr[Z] = VDOT(rev->zUnit, xlated);
404 
405  VMOVE(ur, vr);
406  VUNITIZE(ur);
407 
408  if (rev->ang < M_2PI) {
409  VREVERSE(normS, rev->yUnit); /* start normal */
410  start = (VDOT(normS, rev->v3d) - VDOT(normS, rp->r_pt)) / VDOT(normS, rp->r_dir);
411 
412  VCROSS(normE, rev->zUnit, rev->rEnd); /* end normal */
413  end = (VDOT(normE, rev->v3d) - VDOT(normE, rp->r_pt)) / VDOT(normE, rp->r_dir);
414 
415  VJOIN1(hit1, pr, start, vr);
416  hit2d[Y] = hit1[Z];
417  hit2d[X] = sqrt(hit1[X]*hit1[X] + hit1[Y]*hit1[Y]);
418 
419  VJOIN1(hit2, xlated, start, rp->r_dir);
420  if (VDOT(rev->xUnit, hit2) < 0) {
421  /* set the sign of the 2D point's x coord */
422  hit2d[X] = -hit2d[X];
423  }
424 
425  if (rt_sketch_contains(rev->skt, hit2d)) {
426  hit2d[X] = -hit2d[X];
427  if (rev->ang > M_PI && rt_sketch_contains(rev->skt, hit2d)) {
428  /* skip it */
429  } else {
430  hitp = hits[nhits++];
431  hitp->hit_magic = RT_HIT_MAGIC;
432  hitp->hit_dist = start;
433  hitp->hit_surfno = (hit2d[X]>0) ? START_FACE_NEG : START_FACE_POS;
434  VSET(hitp->hit_vpriv, -hit2d[X], hit2d[Y], 0);
435  }
436  }
437 
438  VJOIN1(hit1, pr, end, vr);
439  hit2d[Y] = hit1[Z];
440  hit2d[X] = sqrt(hit1[X]*hit1[X] + hit1[Y]*hit1[Y]);
441 
442  VJOIN1(hit2, xlated, end, rp->r_dir);
443  if (VDOT(rev->rEnd, hit2) < 0) {
444  /* set the sign of the 2D point's x coord */
445  hit2d[X] = -hit2d[X];
446  }
447 
448  if (rt_sketch_contains(rev->skt, hit2d)) {
449  hit2d[X] = -hit2d[X];
450  if (rev->ang > M_PI && rt_sketch_contains(rev->skt, hit2d)) {
451  /* skip it */
452  } else {
453  if (nhits >= MAX_HITS) return -1; /* too many hits */
454  hitp = hits[nhits++];
455  hitp->hit_magic = RT_HIT_MAGIC;
456  hitp->hit_dist = end;
457  hitp->hit_surfno = (hit2d[X]>0) ? END_FACE_NEG : END_FACE_POS;
458  VSET(hitp->hit_vpriv, -hit2d[X], hit2d[Y], 0);
459  }
460  }
461  }
462 
463  /**
464  * calculate hyperbola parameters
465  *
466  * [ (x*x) / aa^2 ] - [ (y-h)^2 / bb^2 ] = 1
467  *
468  * x = aa cosh(t - k);
469  * y = h + bb sinh(t - k);
470  */
471 
472  VREVERSE(dp, pr);
473  VSET(norm, ur[X], ur[Y], 0);
474 
475  k = VDOT(dp, norm) / VDOT(ur, norm);
476  h = pr[Z] + k*vr[Z];
477 
478  if (NEAR_EQUAL(fabs(ur[Z]), 1.0, RT_DOT_TOL)) {
479  aa = sqrt(pr[X]*pr[X] + pr[Y]*pr[Y]);
480  bb = MAX_FASTF;
481  } else {
482  aa = sqrt((pr[X] + k*vr[X])*(pr[X] + k*vr[X]) + (pr[Y] + k*vr[Y])*(pr[Y] + k*vr[Y]));
483  bb = sqrt(aa*aa * (1.0/(1 - ur[Z]*ur[Z]) - 1.0));
484  }
485 
486  /**
487  * if (ur[Z] == 1) {
488  * bb = inf;
489  * // ray becomes a line parallel to sketch's y-axis instead of a hyberbola
490  * }
491  * if (ur[Z] == 0) {
492  * bb = 0;
493  * // ray becomes a line parallel to sketch's x-axis instead of a hyperbola
494  * // all hits must have x > aa
495  * }
496  */
497 
498  /* handle open sketches */
499  if (!NEAR_ZERO(ur[Z], RT_DOT_TOL)) {
500  for (i=0; i<rev->skt->vert_count && rev->ends[i] != -1; i++) {
501  V2MOVE(pt1, rev->skt->verts[rev->ends[i]]);
502  hit2d[Y] = pt1[Y];
503  if (NEAR_EQUAL(fabs(ur[Z]), 1.0, RT_DOT_TOL)) {
504  /* ur[Z] == 1 */
505  hit2d[X] = aa;
506  } else {
507  hit2d[X] = aa*sqrt((hit2d[Y]-h)*(hit2d[Y]-h)/(bb*bb) + 1);
508  }
509  if (pt1[X] < 0) hit2d[X] = -fabs(hit2d[X]);
510  if (fabs(hit2d[X]) < fabs(pt1[X])) {
511  /* valid hit */
512  if (nhits >= MAX_HITS) return -1; /* too many hits */
513  hitp = hits[nhits++];
514  hitp->hit_magic = RT_HIT_MAGIC;
515  hitp->hit_dist = (hit2d[Y] - pr[Z]) / vr[Z];
516  hitp->hit_surfno = HORIZ_SURF;
517  VJOIN1(hitp->hit_vpriv, pr, hitp->hit_dist, vr);
518  hitp->hit_point[X] = hit2d[X];
519  hitp->hit_point[Y] = hit2d[Y];
520  hitp->hit_point[Z] = 0;
521 
522  angle = atan2(hitp->hit_vpriv[Y], hitp->hit_vpriv[X]);
523  if (pt1[X] < 0) {
524  angle += M_PI;
525  } else if (angle < 0) {
526  angle += M_2PI;
527  }
528  hit2d[X] = -hit2d[X];
529  if (angle > rev->ang) {
530  nhits--;
531  continue;
532  } else if ((angle + M_PI < rev->ang || angle - M_PI > 0)
533  && rt_sketch_contains(rev->skt, hit2d)
534  && hit2d[X] > 0) {
535  nhits--;
536  continue;
537  }
538  /* X and Y are used for uv(), Z is used for norm() */
539  hitp->hit_vpriv[X] = pt1[X];
540  hitp->hit_vpriv[Y] = angle;
541  if (i+1 < rev->skt->vert_count && rev->ends[i+1] != -1 &&
542  NEAR_EQUAL(rev->skt->verts[rev->ends[i]][Y],
543  rev->skt->verts[rev->ends[i+1]][Y], SMALL)) {
544  hitp->hit_vpriv[Z] = rev->skt->verts[rev->ends[i+1]][X];
545  i++;
546  if (fabs(hit2d[X]) < fabs(hitp->hit_vpriv[Z])) {
547  nhits--;
548  }
549  } else {
550  hitp->hit_vpriv[Z] = 0;
551  }
552  }
553  }
554  }
555 
556  /* find hyperbola intersection with each sketch segment */
557  nseg = rev->skt->curve.count;
558  for (i=0; i<nseg; i++) {
559  lng = (uint32_t *)rev->skt->curve.segment[i];
560 
561  switch (*lng) {
562  case CURVE_LSEG_MAGIC:
563  lsg = (struct line_seg *)lng;
564  V2MOVE(pt1, rev->skt->verts[lsg->start]);
565  V2MOVE(pt2, rev->skt->verts[lsg->end]);
566  V2SUB2(dir, pt2, pt1);
567  if (ZERO(dir[X])) {
568  m = 1.0;
569  } else {
570  m = dir[Y] / dir[X];
571  }
572 
573  if (NEAR_EQUAL(fabs(ur[Z]), 1.0, RT_DOT_TOL)) {
574  /* ray is vertical line at x=aa */
575  if (FMIN(pt1[X], pt2[X]) < aa && aa < FMAX(pt1[X], pt2[X])) {
576  /* check the positive side of the sketch (x > 0) */
577  k1 = (m * (aa - pt1[X]) + pt1[Y] - pr[Z]) / vr[Z];
578  VJOIN1(hit1, pr, k1, vr);
579  angle = atan2(hit1[Y], hit1[X]);
580  hit2d[X] = -aa; /* use neg to check for overlap in contains() */
581  hit2d[Y] = hit1[Z];
582  if (angle < 0) {
583  angle += M_2PI;
584  }
585  if (angle < rev->ang &&
586  !((angle + M_PI < rev->ang || angle - M_PI > 0)
587  && rt_sketch_contains(rev->skt, hit2d))) {
588  if (nhits >= MAX_HITS) return -1; /* too many hits */
589  hitp = hits[nhits++];
590  hitp->hit_point[X] = -hit2d[X];
591  hitp->hit_point[Y] = hit2d[Y];
592  hitp->hit_point[Z] = 0;
593  VMOVE(hitp->hit_vpriv, hit1);
594  if (ZERO(m)) {
595  hitp->hit_vpriv[Z] = 0.0;
596  } else {
597  hitp->hit_vpriv[Z] = -1.0/m;
598  }
599  hitp->hit_magic = RT_HIT_MAGIC;
600  hitp->hit_dist = k1;
601  hitp->hit_surfno = i;
602  }
603  }
604  if (FMIN(pt1[X], pt2[X]) < -aa && -aa < FMAX(pt1[X], pt2[X])) {
605  /* check negative side of the sketch (x < 0) */
606  k1 = (m * (-aa - pt1[X]) + pt1[Y] - pr[Z]) / vr[Z];
607  VJOIN1(hit1, pr, k1, vr);
608  angle = atan2(hit1[Y], hit1[X]);
609  hit2d[X] = aa; /* use neg to check for overlap in contains() */
610  hit2d[Y] = hit1[Z];
611  if (angle < 0) {
612  angle += M_PI;
613  }
614  if (angle < rev->ang &&
615  !((angle + M_PI < rev->ang || angle - M_PI > 0)
616  && rt_sketch_contains(rev->skt, hit2d))) {
617  if (nhits >= MAX_HITS) return -1; /* too many hits */
618  hitp = hits[nhits++];
619  hitp->hit_point[X] = -hit2d[X];
620  hitp->hit_point[Y] = hit2d[Y];
621  hitp->hit_point[Z] = 0;
622  VMOVE(hitp->hit_vpriv, hit1);
623  if (ZERO(m)) {
624  hitp->hit_vpriv[Z] = 0.0;
625  } else {
626  hitp->hit_vpriv[Z] = 1.0/m;
627  }
628  hitp->hit_magic = RT_HIT_MAGIC;
629  hitp->hit_dist = k1;
630  hitp->hit_surfno = i;
631  }
632  }
633  } else if (NEAR_ZERO(ur[Z], RT_DOT_TOL)) {
634  /* ray is horizontal line at y = h; hit2d[X] > aa */
635  if (FMIN(pt1[Y], pt2[Y]) < h && h < FMAX(pt1[Y], pt2[Y])) {
636  if (ZERO(m)) {
637  hit2d[X] = pt1[X];
638  } else {
639  hit2d[X] = pt1[X] + (h-pt1[Y])/m;
640  }
641  hit2d[Y] = h;
642  if (fabs(hit2d[X]) > aa) {
643  k1 = k + sqrt(hit2d[X]*hit2d[X] - aa*aa);
644  k2 = k - sqrt(hit2d[X]*hit2d[X] - aa*aa);
645 
646  VJOIN1(hit1, pr, k1, vr);
647  angle = atan2(hit1[Y], hit1[X]);
648  if (hit2d[X] < 0) {
649  angle += M_PI;
650  } else if (angle < 0) {
651  angle += M_2PI;
652  }
653  hit2d[X] = -hit2d[X];
654  if (angle < rev->ang &&
655  !((angle + M_PI < rev->ang || angle - M_PI > 0)
656  && rt_sketch_contains(rev->skt, hit2d))) {
657  if (nhits >= MAX_HITS) return -1; /* too many hits */
658  hitp = hits[nhits++];
659  hitp->hit_point[X] = -hit2d[X];
660  hitp->hit_point[Y] = hit2d[Y];
661  hitp->hit_point[Z] = 0;
662  VMOVE(hitp->hit_vpriv, hit1);
663  if (ZERO(m)) {
664  hitp->hit_vpriv[Z] = 0.0;
665  } else {
666  hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
667  }
668  hitp->hit_magic = RT_HIT_MAGIC;
669  hitp->hit_dist = k1;
670  hitp->hit_surfno = i;
671  }
672 
673  VJOIN1(hit2, pr, k2, vr);
674  angle = atan2(hit2[Y], hit2[X]);
675  if (-hit2d[X] < 0) {
676  angle += M_PI;
677  } else if (angle < 0) {
678  angle += M_2PI;
679  }
680  if (angle < rev->ang &&
681  !((angle + M_PI < rev->ang || angle - M_PI > 0)
682  && rt_sketch_contains(rev->skt, hit2d))) {
683  if (nhits >= MAX_HITS) return -1; /* too many hits */
684  hitp = hits[nhits++];
685  hitp->hit_point[X] = -hit2d[X];
686  hitp->hit_point[Y] = hit2d[Y];
687  hitp->hit_point[Z] = 0;
688  VMOVE(hitp->hit_vpriv, hit2);
689  if (ZERO(m)) {
690  hitp->hit_vpriv[Z] = 0.0;
691  } else {
692  hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
693  }
694  hitp->hit_magic = RT_HIT_MAGIC;
695  hitp->hit_dist = k2;
696  hitp->hit_surfno = i;
697  }
698  }
699  }
700  } else {
701 
702  a = dir[X]*dir[X]/(aa*aa) - dir[Y]*dir[Y]/(bb*bb);
703  b = 2*(dir[X]*pt1[X]/(aa*aa) - dir[Y]*(pt1[Y]-h)/(bb*bb));
704  c = pt1[X]*pt1[X]/(aa*aa) - (pt1[Y]-h)*(pt1[Y]-h)/(bb*bb) - 1;
705  disc = b*b - (4.0 * a * c);
706  if (!NEAR_ZERO(a, RT_PCOEF_TOL)) {
707  if (disc > 0) {
708  disc = sqrt(disc);
709  t1 = (-b + disc) / (2.0 * a);
710  t2 = (-b - disc) / (2.0 * a);
711  k1 = (pt1[Y]-pr[Z] + t1*dir[Y])/vr[Z];
712  k2 = (pt1[Y]-pr[Z] + t2*dir[Y])/vr[Z];
713 
714  if (t1 > 0 && t1 < 1) {
715  if (nhits >= MAX_HITS) return -1; /* too many hits */
716  VJOIN1(hit1, pr, k1, vr);
717  angle = atan2(hit1[Y], hit1[X]);
718  V2JOIN1(hit2d, pt1, t1, dir);
719  if (hit2d[X] < 0) {
720  angle += M_PI;
721  } else if (angle < 0) {
722  angle += M_2PI;
723  }
724  hit2d[X] = -hit2d[X];
725  if (angle < rev->ang) {
726  if ((angle + M_PI < rev->ang || angle - M_PI > 0)
727  && rt_sketch_contains(rev->skt, hit2d)) {
728  /* overlap, so ignore it */
729  } else {
730  hitp = hits[nhits++];
731  hitp->hit_point[X] = -hit2d[X];
732  hitp->hit_point[Y] = hit2d[Y];
733  hitp->hit_point[Z] = 0;
734  VMOVE(hitp->hit_vpriv, hit1);
735  if (ZERO(m)) {
736  hitp->hit_vpriv[Z] = 0.0;
737  } else {
738  hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
739  }
740  hitp->hit_magic = RT_HIT_MAGIC;
741  hitp->hit_dist = k1;
742  hitp->hit_surfno = i;
743  }
744  }
745  }
746  if (t2 > 0 && t2 < 1) {
747  if (nhits >= MAX_HITS) return -1; /* too many hits */
748  VJOIN1(hit2, pr, k2, vr);
749  angle = atan2(hit2[Y], hit2[X]);
750  V2JOIN1(hit2d, pt1, t2, dir);
751  if (hit2d[X] < 0) {
752  angle += M_PI;
753  } else if (angle < 0) {
754  angle += M_2PI;
755  }
756  hit2d[X] = -hit2d[X];
757  if (angle < rev->ang) {
758  if ((angle + M_PI < rev->ang || angle - M_PI > 0)
759  && rt_sketch_contains(rev->skt, hit2d)) {
760  /* overlap, so ignore it */
761  } else {
762  hitp = hits[nhits++];
763  hitp->hit_point[X] = -hit2d[X];
764  hitp->hit_point[Y] = hit2d[Y];
765  hitp->hit_point[Z] = 0;
766  VMOVE(hitp->hit_vpriv, hit2);
767  if (ZERO(m)) {
768  hitp->hit_vpriv[Z] = 0.0;
769  } else {
770  hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
771  }
772  hitp->hit_magic = RT_HIT_MAGIC;
773  hitp->hit_dist = k2;
774  hitp->hit_surfno = i;
775  }
776  }
777  }
778  }
779  } else if (!NEAR_ZERO(b, RT_PCOEF_TOL)) {
780  t1 = -c / b;
781  k1 = (pt1[Y]-pr[Z] + t1*dir[Y])/vr[Z];
782  if (t1 > 0 && t1 < 1) {
783  if (nhits >= MAX_HITS) return -1; /* too many hits */
784 
785  VJOIN1(hit1, pr, k1, vr);
786  angle = atan2(hit1[Y], hit1[X]);
787  V2JOIN1(hit2d, pt1, t1, dir);
788  if (hit2d[X] < 0) {
789  angle += M_PI;
790  } else if (angle < 0) {
791  angle += M_2PI;
792  }
793  hit2d[X] = -hit2d[X];
794  if (angle < rev->ang) {
795  if ((angle + M_PI < rev->ang || angle - M_PI > 0)
796  && rt_sketch_contains(rev->skt, hit2d)) {
797  /* overlap, so ignore it */
798  } else {
799  hitp = hits[nhits++];
800  hitp->hit_point[X] = -hit2d[X];
801  hitp->hit_point[Y] = hit2d[Y];
802  hitp->hit_point[Z] = 0;
803  VMOVE(hitp->hit_vpriv, hit1);
804  if (ZERO(m)) {
805  hitp->hit_vpriv[Z] = 0.0;
806  } else {
807  hitp->hit_vpriv[Z] = (hit2d[X]>0) ? 1.0/m : -1.0/m;
808  }
809  hitp->hit_magic = RT_HIT_MAGIC;
810  hitp->hit_dist = k1;
811  hitp->hit_surfno = i;
812  }
813  }
814  }
815  }
816  }
817  break;
818  case CURVE_CARC_MAGIC:
819  /*
820  circle: (x-cx)^2 + (y-cy)^2 = cr^2
821  x = (1/2cx)y^2 + (-cy/cx)y + (1/2cx)(cy^2 + cx^2 - cr^2) + (1/2cx)(x^2)
822  x = f(y) + (1/2cx)x^2
823 
824  hyperbola:
825  [(x-hx)/a]^2 - [(y-hy)/b]^2 = 1
826  x^2 = (a^2/b^2)y^2 + (-2*hy*a^2/b^2)y + (hy^2 * a^2/b^2) + a^2
827  x^2 = g(y)
828 
829  plug the second equation into the first to get:
830  x = f(y) + (1/2cx)g(y)
831  then square that to get:
832  x^2 = {f(y) + (1/2cx)g(y)}^2 = g(y)
833  move all to one side to get:
834  0 = {f(y) + (1/2cx)g(y)}^2 - g(y)
835  this is a fourth order polynomial in y.
836  */
837  {
838  bn_poly_t circleX; /* f(y) */
839  bn_poly_t hypXsq; /* g(y) */
840  bn_poly_t hypXsq_scaled; /* g(y) / (2*cx) */
841  bn_poly_t sum; /* f(y) + g(y)/(2cx) */
842  bn_poly_t sum_sq; /* {f(y) + g(y)/(2cx)}^2 */
843  bn_poly_t answer; /* {f(y) + g(y)/(2cx)}^2 - g(y) */
844  bn_complex_t roots[4];
845  int rootcnt;
846 
847  fastf_t cx, cy, crsq = 0; /* carc's (x, y) coords and radius^2 */
848  point2d_t center, radius;
849 
850  /* calculate circle parameters */
851  csg = (struct carc_seg *)lng;
852 
853  if (csg->radius <= 0.0) {
854  /* full circle, "end" is center and "start" is on the circle */
855  V2MOVE(center, rev->skt->verts[csg->end]);
856  V2SUB2(radius, rev->skt->verts[csg->start], center);
857  crsq = MAG2SQ(radius);
858  } else {
859  point_t startpt, endpt, midpt;
860  vect_t s_to_m;
861  vect_t bisector;
862  vect_t vertical;
863  fastf_t distance;
864  fastf_t magsq_s2m;
865 
866  VSET(vertical, 0, 0, 1);
867  V2MOVE(startpt, rev->skt->verts[csg->start]);
868  startpt[Z] = 0.0;
869  V2MOVE(endpt, rev->skt->verts[csg->end]);
870  endpt[Z] = 0.0;
871 
872  VBLEND2(midpt, 0.5, startpt, 0.5, endpt);
873  VSUB2(s_to_m, midpt, startpt);
874  VCROSS(bisector, vertical, s_to_m);
875  VUNITIZE(bisector);
876  magsq_s2m = MAGSQ(s_to_m);
877  if (magsq_s2m > csg->radius*csg->radius) {
878  fastf_t max_radius;
879 
880  max_radius = sqrt(magsq_s2m);
881  if (NEAR_EQUAL(max_radius, csg->radius, RT_LEN_TOL)) {
882  csg->radius = max_radius;
883  } else {
884  bu_log("Impossible radius for circular arc in extrusion (%s), is %g, cannot be more than %g!\n",
885  stp->st_dp->d_namep, csg->radius, sqrt(magsq_s2m));
886  bu_log("Difference is %g\n", max_radius - csg->radius);
887  return -1;
888  }
889  }
890  distance = sqrt(csg->radius*csg->radius - magsq_s2m);
891 
892  /* save arc center */
893  if (csg->center_is_left) {
894  V2JOIN1(center, midpt, distance, bisector);
895  } else {
896  V2JOIN1(center, midpt, -distance, bisector);
897  }
898  }
899 
900  cx = center[X];
901  cy = center[Y];
902 
903  circleX.dgr = 2;
904  hypXsq.dgr = 2;
905  hypXsq_scaled.dgr = 2;
906  sum.dgr = 2;
907  sum_sq.dgr = 4;
908  answer.dgr = 4;
909 
910  circleX.cf[0] = (cy*cy + cx*cx - crsq)/(2.0*cx);
911  circleX.cf[1] = -cy/cx;
912  circleX.cf[2] = 1/(2.0*cx);
913 
914  hypXsq_scaled.cf[0] = hypXsq.cf[0] = aa*aa + h*h*aa*aa/(bb*bb);
915  hypXsq_scaled.cf[1] = hypXsq.cf[1] = -2.0*h*aa*aa/(bb*bb);
916  hypXsq_scaled.cf[2] = hypXsq.cf[2] = (aa*aa)/(bb*bb);
917 
918  bn_poly_scale(&hypXsq_scaled, 1.0 / (2.0 * cx));
919  bn_poly_add(&sum, &hypXsq_scaled, &circleX);
920  bn_poly_mul(&sum_sq, &sum, &sum);
921  bn_poly_sub(&answer, &sum_sq, &hypXsq);
922 
923  /* It is known that the equation is 4th order. Therefore, if the
924  * root finder returns other than 4 roots, error.
925  */
926  rootcnt = rt_poly_roots(&answer, roots, stp->st_dp->d_namep);
927  if (rootcnt != 4) {
928  if (rootcnt > 0) {
929  bu_log("tor: rt_poly_roots() 4!=%d\n", rootcnt);
930  bn_pr_roots(stp->st_name, roots, rootcnt);
931  } else if (rootcnt < 0) {
932  static int reported=0;
933  bu_log("The root solver failed to converge on a solution for %s\n", stp->st_dp->d_namep);
934  if (!reported) {
935  VPRINT("while shooting from:\t", rp->r_pt);
936  VPRINT("while shooting at:\t", rp->r_dir);
937  bu_log("Additional torus convergence failure details will be suppressed.\n");
938  reported=1;
939  }
940  }
941  }
942 
943  break;
944  }
945  case CURVE_BEZIER_MAGIC:
946  break;
947  case CURVE_NURB_MAGIC:
948  break;
949  default:
950  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
951  break;
952  }
953 
954  }
955 
956  if (nhits%2 != 0) {
957  bu_log("odd number of hits: %zu\n", nhits);
958  for (i=0; i<nhits; i++) {
959  bu_log("\t(%6.2f, %6.2f)\t%6.2f\t%2d\n",
960  hits[i]->hit_point[X], hits[i]->hit_point[Y], hits[i]->hit_dist, hits[i]->hit_surfno);
961  }
962  return -1;
963  }
964 
965  /* sort hitpoints (an arbitrary number of hits depending on sketch) */
966  for (i=0; i<nhits; i+=2) {
967  in = out = -1;
968  for (j=0; j<nhits; j++) {
969  if (hits[j] == NULL) continue;
970  if (in == -1) {
971  in = j;
972  continue;
973  }
974  /* store shortest dist as 'in', second shortest as 'out' */
975  if (hits[j]->hit_dist <= hits[in]->hit_dist) {
976  out = in;
977  in = j;
978  } else if (out == -1 || hits[j]->hit_dist <= hits[out]->hit_dist) {
979  out = j;
980  }
981  }
982  if (in == -1 || out == -1) {
983  bu_log("failed to find valid segment. nhits: %zu\n", nhits);
984  break;
985  }
986 
987  if (ZERO(hits[in]->hit_dist - hits[out]->hit_dist)) {
988  hits[in] = NULL;
989  hits[out] = NULL;
990  continue;
991  }
992 
993  RT_GET_SEG(segp, ap->a_resource);
994  segp->seg_stp = stp;
995 
996  segp->seg_in = *hits[in];
997  hits[in] = NULL;
998  segp->seg_out = *hits[out];
999  hits[out] = NULL;
1000  BU_LIST_INSERT(&(seghead->l), &(segp->l));
1001  }
1002 
1003  return nhits;
1004 }
1005 
1006 
1007 /**
1008  * Given ONE ray distance, return the normal and entry/exit point.
1009  */
1010 void
1011 rt_revolve_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
1012 {
1013  struct revolve_specific *rev =
1014  (struct revolve_specific *)stp->st_specific;
1015  vect_t n, nT;
1016 
1017  VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
1018 
1019 /*
1020  XXX debug printing
1021  VPRINT("hitp", hitp->hit_point);
1022  VPRINT("vpriv", hitp->hit_vpriv);
1023 */
1024 
1025  switch (hitp->hit_surfno) {
1026  case START_FACE_POS:
1027  VREVERSE(hitp->hit_normal, rev->yUnit);
1028  break;
1029  case START_FACE_NEG:
1030  VMOVE(hitp->hit_normal, rev->yUnit);
1031  break;
1032  case END_FACE_POS:
1033  VCROSS(hitp->hit_normal, rev->zUnit, rev->rEnd);
1034  VUNITIZE(hitp->hit_normal);
1035  break;
1036  case END_FACE_NEG:
1037  VCROSS(hitp->hit_normal, rev->rEnd, rev->zUnit);
1038  VUNITIZE(hitp->hit_normal);
1039  break;
1040  default:
1041  VMOVE(n, hitp->hit_vpriv);
1042  n[Z] *= sqrt((hitp->hit_vpriv[X] * hitp->hit_vpriv[X]) + (hitp->hit_vpriv[Y] * hitp->hit_vpriv[Y]));
1043 
1044  if (hitp->hit_surfno == HORIZ_SURF) {
1045  VSET(n, 0, 0, 1);
1046  }
1047 
1048  nT[X] = (rev->xUnit[X] * n[X])
1049  + (rev->yUnit[X] * n[Y])
1050  + (rev->zUnit[X] * n[Z]);
1051  nT[Y] = (rev->xUnit[Y] * n[X])
1052  + (rev->yUnit[Y] * n[Y])
1053  + (rev->zUnit[Y] * n[Z]);
1054  nT[Z] = (rev->xUnit[Z] * n[X])
1055  + (rev->yUnit[Z] * n[Y])
1056  + (rev->zUnit[Z] * n[Z]);
1057 
1058  VUNITIZE(nT);
1059 
1060 /* XXX Debug printing
1061  VPRINT("xUnit", rev->xUnit);
1062  VPRINT("yUnit", rev->yUnit);
1063  VPRINT("zUnit", rev->zUnit);
1064  VPRINT("n", n);
1065  VPRINT("nT", nT);
1066 */
1067 
1068  if (VDOT(nT, rp->r_dir) < 0) {
1069  VMOVE(hitp->hit_normal, nT);
1070  } else {
1071  VREVERSE(hitp->hit_normal, nT);
1072  }
1073  break;
1074  }
1075 }
1076 
1077 
1078 /**
1079  * Return the curvature of the revolve.
1080  */
1081 void
1082 rt_revolve_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
1083 {
1084  if (!cvp || !hitp)
1085  return;
1086  RT_CK_HIT(hitp);
1087  if (stp) RT_CK_SOLTAB(stp);
1088 
1089  cvp->crv_c1 = cvp->crv_c2 = 0;
1090 
1091  /* any tangent direction */
1092  bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal);
1093 }
1094 
1095 
1096 /**
1097  * For a hit on the surface of an revolve, return the (u, v) coordinates
1098  * of the hit point, 0 <= u, v <= 1.
1099 
1100  * u = azimuth, v = elevation
1101  */
1102 void
1103 rt_revolve_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
1104 {
1105  struct revolve_specific *rev = (struct revolve_specific *)stp->st_specific;
1106 
1107  point_t hitpoint;
1108  fastf_t angle;
1109  uint32_t *lng;
1110  struct line_seg *lsg;
1111 
1112  /*
1113  struct carc_seg *csg;
1114  struct nurb_seg *nsg;
1115  struct bezier_seg *bsg;
1116  */
1117 
1118  if (ap) RT_CK_APPLICATION(ap);
1119 
1120  VJOIN1(hitpoint, hitp->hit_rayp->r_pt, hitp->hit_dist, hitp->hit_rayp->r_dir);
1121 
1122  switch (hitp->hit_surfno) {
1123  case START_FACE_POS:
1124  case START_FACE_NEG:
1125  case END_FACE_POS:
1126  case END_FACE_NEG:
1127  uvp->uv_u = fabs((hitp->hit_vpriv[X] - rev->bounds[0]) / (rev->bounds[1] - rev->bounds[0]));
1128  uvp->uv_v = fabs((hitp->hit_vpriv[Y] - rev->bounds[2]) / (rev->bounds[3] - rev->bounds[2]));
1129  break;
1130  case HORIZ_SURF:
1131  hitpoint[Z] = 0;
1132 
1133  /* Y is the angle: [0, 2pi] */
1134  uvp->uv_u = hitp->hit_vpriv[Y] / rev->ang;
1135 
1136  /* X is the coord of the endpoint that we're connecting to the revolve axis */
1137  uvp->uv_v = fabs((MAGNITUDE(hitpoint) - hitp->hit_vpriv[Z])
1138  / (hitp->hit_vpriv[X]- hitp->hit_vpriv[Z]));
1139  /* bu_log("\tmin: %3.2f\tmax: %3.2f\n", hitp->hit_vpriv[Z], hitp->hit_vpriv[X]); */
1140  break;
1141  default:
1142  angle = atan2(hitp->hit_vpriv[Y], hitp->hit_vpriv[X]);
1143  if (angle < 0) angle += M_2PI;
1144  uvp->uv_u = angle / rev->ang;
1145 
1146  lng = (uint32_t *)rev->skt->curve.segment[hitp->hit_surfno];
1147 
1148  switch (*lng) {
1149  case CURVE_LSEG_MAGIC:
1150  lsg = (struct line_seg *)lng;
1151  if (ZERO(1.0/hitp->hit_vpriv[Z])) {
1152  /* use hitpoint radius and sketch's X values */
1153  hitpoint[Z] = 0;
1154  uvp->uv_v = (MAGNITUDE(hitpoint) - rev->skt->verts[lsg->end][X]) /
1155  (rev->skt->verts[lsg->start][X] - rev->skt->verts[lsg->end][X]);
1156  } else {
1157  /* use hitpoint Z and sketch's Y values */
1158  uvp->uv_v = (hitpoint[Z] - rev->skt->verts[lsg->end][Y]) /
1159  (rev->skt->verts[lsg->start][Y] - rev->skt->verts[lsg->end][Y]);
1160  }
1161  break;
1162  case CURVE_CARC_MAGIC:
1163  /* csg = (struct carc_seg *)lng; */
1164  break;
1165  case CURVE_BEZIER_MAGIC:
1166  /* bsg = (struct bezier_seg *)lng; */
1167  break;
1168  case CURVE_NURB_MAGIC:
1169  /* nsg = (struct nurb_seg *)lng; */
1170  break;
1171  default:
1172  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
1173  break;
1174  }
1175 
1176  break;
1177  }
1178  if (uvp->uv_v > 1 || uvp->uv_v < 0 || uvp->uv_u > 1 || uvp->uv_u < 0) {
1179  bu_log("UV error:\t%d\t%2.2f\t%2.2f\t", hitp->hit_surfno, uvp->uv_u, uvp->uv_v);
1180  bu_log("\tX: (%3.2f, %3.2f)\tY: (%3.2f, %3.2f)\n", rev->bounds[0], rev->bounds[1], rev->bounds[2], rev->bounds[3]);
1181  }
1182  /* sanity checks */
1183  if (uvp->uv_u < 0.0)
1184  uvp->uv_u = 0.0;
1185  else if (uvp->uv_u > 1.0)
1186  uvp->uv_u = 1.0;
1187  if (uvp->uv_v < 0.0)
1188  uvp->uv_v = 0.0;
1189  else if (uvp->uv_v > 1.0)
1190  uvp->uv_v = 1.0;
1191 }
1192 
1193 
1194 void
1196 {
1197  struct revolve_specific *revolve =
1198  (struct revolve_specific *)stp->st_specific;
1199  bu_free(revolve->ends, "endcount");
1200  BU_PUT(revolve, struct revolve_specific);
1201 }
1202 
1203 
1204 int
1205 rt_revolve_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))
1206 {
1207  struct rt_revolve_internal *rip;
1208 
1209  size_t nvert, narc, nadd, nseg, i, j, k;
1210  point2d_t *verts;
1211  struct rt_curve *crv;
1212 
1213  vect_t ell[16], cir[16], ucir[16], height, xdir, ydir, ux, uy, uz, rEnd, xEnd, yEnd;
1214  fastf_t cos22_5 = 0.9238795325112867385;
1215  fastf_t cos67_5 = 0.3826834323650898373;
1216  int *endcount = NULL, ang_sign;
1217  point_t add, add2, add3;
1218 
1219  BU_CK_LIST_HEAD(vhead);
1220  RT_CK_DB_INTERNAL(ip);
1221  rip = (struct rt_revolve_internal *)ip->idb_ptr;
1222  RT_REVOLVE_CK_MAGIC(rip);
1223 
1224  nvert = rip->skt->vert_count;
1225  verts = rip->skt->verts;
1226  crv = &rip->skt->curve;
1227 
1228  if (rip->ang < M_2PI) {
1229  narc = ceil(fabs(rip->ang * 8 * M_1_PI));
1230  } else {
1231  narc = 16;
1232  }
1233  VSCALE(xEnd, rip->r, cos(rip->ang));
1234  VCROSS(rEnd, rip->axis3d, rip->r); /* using rEnd for temp storage */
1235  VSCALE(yEnd, rEnd, sin(rip->ang));
1236  VADD2(rEnd, xEnd, yEnd);
1237 
1238  VMOVE(uz, rip->axis3d);
1239  VMOVE(ux, rip->r);
1240  VCROSS(uy, uz, ux);
1241 
1242  VUNITIZE(ux);
1243  VUNITIZE(uy);
1244  VUNITIZE(uz);
1245 
1246  /* setup unit circle to be scaled */
1247  ang_sign = rip->ang < 0 ? -1 : 1;
1248  VMOVE(ucir[ 0], ux);
1249  VREVERSE(ucir[ 8], ucir[0]);
1250 
1251  VSCALE(xdir, ux, cos22_5);
1252  VSCALE(ydir, uy, ang_sign * cos67_5);
1253  VADD2(ucir[ 1], xdir, ydir);
1254  VREVERSE(ucir[ 9], ucir[1]);
1255  VREVERSE(xdir, xdir);
1256  VADD2(ucir[ 7], xdir, ydir);
1257  VREVERSE(ucir[15], ucir[7]);
1258 
1259  VSCALE(xdir, ux, M_SQRT1_2);
1260  VSCALE(ydir, uy, ang_sign * M_SQRT1_2);
1261  VADD2(ucir[ 2], xdir, ydir);
1262  VREVERSE(ucir[10], ucir[2]);
1263  VREVERSE(xdir, xdir);
1264  VADD2(ucir[ 6], xdir, ydir);
1265  VREVERSE(ucir[14], ucir[6]);
1266 
1267 
1268  VSCALE(xdir, ux, cos67_5);
1269  VSCALE(ydir, uy, ang_sign * cos22_5);
1270  VADD2(ucir[ 3], xdir, ydir);
1271  VREVERSE(ucir[11], ucir[3]);
1272  VREVERSE(xdir, xdir);
1273  VADD2(ucir[ 5], xdir, ydir);
1274  VREVERSE(ucir[13], ucir[5]);
1275 
1276  VSCALE(ydir, uy, ang_sign);
1277  VMOVE(ucir[ 4], ydir);
1278  VREVERSE(ucir[12], ucir[4]);
1279 
1280  /* find open endpoints, and determine which points are used */
1281  if (nvert)
1282  endcount = (int *)bu_calloc(nvert, sizeof(int), "endcount");
1283 
1284  nseg = rip->skt->curve.count;
1285 
1286  for (i=0; i<nseg; i++) {
1287  uint32_t *lng;
1288  struct line_seg *lsg;
1289  struct carc_seg *csg;
1290  struct nurb_seg *nsg;
1291  struct bezier_seg *bsg;
1292 
1293  lng = (uint32_t *)rip->skt->curve.segment[i];
1294 
1295  switch (*lng) {
1296  case CURVE_LSEG_MAGIC:
1297  lsg = (struct line_seg *)lng;
1298  endcount[lsg->start]++;
1299  endcount[lsg->end]++;
1300  break;
1301  case CURVE_CARC_MAGIC:
1302  csg = (struct carc_seg *)lng;
1303  if (csg->radius <= 0.0) break;
1304  endcount[csg->start]++;
1305  endcount[csg->end]++;
1306  break;
1307  case CURVE_BEZIER_MAGIC:
1308  bsg = (struct bezier_seg *)lng;
1309  endcount[bsg->ctl_points[0]]++;
1310  endcount[bsg->ctl_points[bsg->degree]]++;
1311  break;
1312  case CURVE_NURB_MAGIC:
1313  nsg = (struct nurb_seg *)lng;
1314  endcount[nsg->ctl_points[0]]++;
1315  endcount[nsg->ctl_points[nsg->c_size-1]]++;
1316  break;
1317  default:
1318  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
1319  break;
1320  }
1321  }
1322 
1323  /* draw circles */
1324  for (i=0; i<nvert; i++) {
1325  if (endcount[i] == 0) continue;
1326  VSCALE(height, uz, verts[i][Y]);
1327  for (j=0; j<narc; j++) {
1328  VSCALE(cir[j], ucir[j], verts[i][X]);
1329  VADD3(ell[j], rip->v3d, cir[j], height);
1330  }
1331  RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_MOVE);
1332  for (j=1; j<narc; j++) {
1333  RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
1334  }
1335  if (narc < 16) {
1336  VSCALE(cir[narc], rEnd, verts[i][X]);
1337  VADD3(ell[narc], rip->v3d, cir[narc], height);
1338  RT_ADD_VLIST(vhead, ell[narc], BN_VLIST_LINE_DRAW);
1339  } else {
1340  RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_DRAW);
1341  }
1342  }
1343 
1344  /* convert endcounts to store which endpoints are odd */
1345  for (i=0, j=0; i<rip->skt->vert_count; i++) {
1346  if (endcount[i] % 2 != 0) {
1347  /* add 'i' to list, insertion sort by vert[i][Y] */
1348  for (k=j; k>0; k--) {
1349  if ((ZERO(verts[i][Y] - verts[endcount[k-1]][Y])
1350  && verts[i][X] > verts[endcount[k-1]][X])
1351  || (!ZERO(verts[i][Y] - verts[endcount[k-1]][Y])
1352  && verts[i][Y] < verts[endcount[k-1]][Y])) {
1353  endcount[k] = endcount[k-1];
1354  } else {
1355  break;
1356  }
1357  }
1358  endcount[k] = i;
1359  j++;
1360  }
1361  }
1362  nadd = j;
1363  while (j < rip->skt->vert_count) {
1364  endcount[j++] = -1;
1365  }
1366 
1367  /* draw sketch outlines */
1368  for (i=0; i<narc; i++) {
1369  curve_to_vlist(vhead, ttol, rip->v3d, ucir[i], uz, rip->skt, crv);
1370  for (j=0; j<nadd; j++) {
1371  if (j+1 < nadd &&
1372  ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
1373  VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
1374  VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
1375  VJOIN1(add3, add, verts[endcount[j+1]][X], ucir[i]);
1376  RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
1377  RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
1378  j++;
1379  } else {
1380  VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
1381  VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
1382  RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
1383  RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
1384  }
1385  }
1386  }
1387  if (narc < 16) {
1388  curve_to_vlist(vhead, ttol, rip->v3d, rEnd, uz, rip->skt, crv);
1389  for (j=0; j<nadd; j++) {
1390  if (j+1 < nadd &&
1391  ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
1392  VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
1393  VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
1394  VJOIN1(add3, add, verts[endcount[j+1]][X], rEnd);
1395  RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
1396  RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
1397  j++;
1398  } else {
1399  VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
1400  VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
1401  RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
1402  RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
1403  }
1404  }
1405  for (j=0; j<nadd; j+=2) {
1406  if (!ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
1407  VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
1408  VJOIN1(add2, rip->v3d, verts[endcount[j+1]][Y], rip->axis3d);
1409  RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
1410  RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
1411  }
1412  }
1413  }
1414 
1415  if (nvert)
1416  bu_free(endcount, "endcount");
1417  return 0;
1418 }
1419 
1420 
1421 /**
1422  * Returns -
1423  * -1 failure
1424  * 0 OK. *r points to nmgregion that holds this tessellation.
1425  */
1426 int
1427 rt_revolve_tess(struct nmgregion **UNUSED(r), struct model *UNUSED(m), struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol))
1428 {
1429  struct rt_revolve_internal *rip = NULL;
1430  struct rt_sketch_internal *sketch_ip = NULL;
1431  struct rt_curve *crv = NULL;
1432 
1433  RT_CK_DB_INTERNAL(ip);
1434  rip = (struct rt_revolve_internal *)ip->idb_ptr;
1435  RT_REVOLVE_CK_MAGIC(rip);
1436 
1437  if (!rip->skt) {
1438  bu_log("rt_revolve_tess: ERROR: no sketch for revolve!\n");
1439  return -1;
1440  }
1441 
1442  sketch_ip = rip->skt;
1443 
1444  RT_SKETCH_CK_MAGIC(sketch_ip);
1445 
1446  crv = &sketch_ip->curve;
1447 
1448  if (crv->count < 1)
1449  return 0;
1450 
1451  /* FIXME: unimplemented */
1452  bu_log("Sorry, tessellation of revolve primitives is not yet implemented.\n");
1453 
1454  return -1;
1455 }
1456 
1457 
1458 /**
1459  * Import an REVOLVE from the database format to the internal format.
1460  * Note that the data read will be in network order. This means
1461  * Big-Endian integers and IEEE doubles for floating point.
1462  *
1463  * Apply modeling transformations as well.
1464  */
1465 int
1466 rt_revolve_import5(struct rt_db_internal *ip, const struct bu_external *ep, const mat_t mat, const struct db_i *dbip, struct resource *resp)
1467 {
1468  struct rt_revolve_internal *rip;
1469 
1470  /* must be double for import and export */
1471  double vv[ELEMENTS_PER_VECT*3 + 1];
1472 
1473  char *sketch_name;
1474  unsigned char *ptr;
1475  struct directory *dp;
1476  struct rt_db_internal tmp_ip;
1477 
1478  if (dbip) RT_CK_DBI(dbip);
1479 
1480  RT_CK_DB_INTERNAL(ip);
1481  BU_CK_EXTERNAL(ep);
1482 
1483  /* set up the internal structure */
1484  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
1485  ip->idb_type = ID_REVOLVE;
1486  ip->idb_meth = &OBJ[ID_REVOLVE];
1487  BU_ALLOC(ip->idb_ptr, struct rt_revolve_internal);
1488 
1489  rip = (struct rt_revolve_internal *)ip->idb_ptr;
1490  rip->magic = RT_REVOLVE_INTERNAL_MAGIC;
1491 
1492  /* Convert the data in ep->ext_buf into internal format. Note the
1493  * conversion from network data (Big Endian ints, IEEE double
1494  * floating point) to host local data representations.
1495  */
1496 
1497  ptr = (unsigned char *)ep->ext_buf;
1498  sketch_name = (char *)ptr + (ELEMENTS_PER_VECT*3 + 1)*SIZEOF_NETWORK_DOUBLE;
1499  if (!dbip)
1500  rip->skt = (struct rt_sketch_internal *)NULL;
1501  else if ((dp=db_lookup(dbip, sketch_name, LOOKUP_NOISY)) == RT_DIR_NULL) {
1502  bu_log("ERROR: Cannot find sketch (%s) for extrusion\n",
1503  sketch_name);
1504  rip->skt = (struct rt_sketch_internal *)NULL;
1505  } else {
1506  if (rt_db_get_internal(&tmp_ip, dp, dbip, bn_mat_identity, resp) != ID_SKETCH) {
1507  bu_log("ERROR: Cannot import sketch (%s) for extrusion\n",
1508  sketch_name);
1509  bu_free(ip->idb_ptr, "extrusion");
1510  return -1;
1511  } else
1512  rip->skt = (struct rt_sketch_internal *)tmp_ip.idb_ptr;
1513  }
1514 
1515  bu_cv_ntohd((unsigned char *)&vv, (unsigned char *)ep->ext_buf, ELEMENTS_PER_VECT*3 + 1);
1516 
1517  /* Apply the modeling transformation */
1518  if (mat == NULL) mat = bn_mat_identity;
1519  MAT4X3PNT(rip->v3d, mat, &vv[0*3]);
1520  MAT4X3PNT(rip->axis3d, mat, &vv[1*3]);
1521  MAT4X3PNT(rip->r, mat, &vv[2*3]);
1522  rip->ang = vv[9];
1523 
1524  /* convert name of data location */
1525  bu_vls_init(&rip->sketch_name);
1526  bu_vls_strcpy(&rip->sketch_name, (char *)ep->ext_buf + (ELEMENTS_PER_VECT * 3 + 1) * SIZEOF_NETWORK_DOUBLE);
1527 
1528  return 0; /* OK */
1529 }
1530 
1531 
1532 /**
1533  * Apply a transformation matrix to the specified 'ip' input revolve
1534  * object, storing the results in the specified 'op' out pointer or
1535  * creating a copy if NULL.
1536  */
1537 int
1539  struct rt_db_internal *op,
1540  const mat_t mat,
1541  struct rt_db_internal *ip,
1542  int release,
1543  struct db_i *dbip,
1544  struct resource *resp)
1545 {
1546  struct rt_revolve_internal *rip, *rop;
1547  point_t tmp_vec;
1548 
1549  if (dbip) RT_CK_DBI(dbip);
1550  RT_CK_DB_INTERNAL(ip);
1551  RT_CK_RESOURCE(resp);
1552  rip = (struct rt_revolve_internal *)ip->idb_ptr;
1553  RT_REVOLVE_CK_MAGIC(rip);
1554 
1556  bu_log("Barrier check at start of revolve_xform():\n");
1558  }
1559 
1560  if (op != ip) {
1561  RT_DB_INTERNAL_INIT(op);
1562  BU_ALLOC(rop, struct rt_revolve_internal);
1563  rop->magic = RT_REVOLVE_INTERNAL_MAGIC;
1564  bu_vls_init(&rop->sketch_name);
1565  bu_vls_vlscat(&rop->sketch_name, &rip->sketch_name);
1566  op->idb_ptr = (void *)rop;
1567  op->idb_meth = &OBJ[ID_REVOLVE];
1568  op->idb_major_type = DB5_MAJORTYPE_BRLCAD;
1569  op->idb_type = ID_REVOLVE;
1570  if (ip->idb_avs.magic == BU_AVS_MAGIC) {
1571  bu_avs_init(&op->idb_avs, ip->idb_avs.count, "avs");
1572  bu_avs_merge(&op->idb_avs, &ip->idb_avs);
1573  }
1574  } else {
1575  rop = (struct rt_revolve_internal *)ip->idb_ptr;
1576  }
1577  MAT4X3PNT(tmp_vec, mat, rip->v3d);
1578  VMOVE(rop->v3d, tmp_vec);
1579  MAT4X3VEC(tmp_vec, mat, rip->axis3d);
1580  VMOVE(rop->axis3d, tmp_vec);
1581  V2MOVE(rop->v2d, rip->v2d);
1582  V2MOVE(rop->axis2d, rip->axis2d);
1583 
1584  if (release && ip != op) {
1585  rop->skt = rip->skt;
1586  rip->skt = (struct rt_sketch_internal *)NULL;
1587  rt_db_free_internal(ip);
1588  } else if (rip->skt) {
1589  rop->skt = rt_copy_sketch(rip->skt);
1590  } else {
1591  rop->skt = (struct rt_sketch_internal *)NULL;
1592  }
1593 
1594  if (bu_debug&BU_DEBUG_MEM_CHECK) {
1595  bu_log("Barrier check at end of revolve_xform():\n");
1597  }
1598 
1599  return 0;
1600 }
1601 
1602 
1603 /**
1604  * Export an REVOLVE from internal form to external format. Note that
1605  * this means converting all integers to Big-Endian format and
1606  * floating point data to IEEE double.
1607  *
1608  * Apply the transformation to mm units as well.
1609  */
1610 int
1611 rt_revolve_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
1612 {
1613  struct rt_revolve_internal *rip;
1614 
1615  /* must be double for import and export */
1616  double vec[ELEMENTS_PER_VECT*3 + 1];
1617 
1618  unsigned char *ptr;
1619 
1620  if (dbip) RT_CK_DBI(dbip);
1621 
1622  RT_CK_DB_INTERNAL(ip);
1623  if (ip->idb_type != ID_REVOLVE) return -1;
1624  rip = (struct rt_revolve_internal *)ip->idb_ptr;
1625  RT_REVOLVE_CK_MAGIC(rip);
1626 
1627  BU_CK_EXTERNAL(ep);
1628  ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * (ELEMENTS_PER_VECT*3 + 1) + bu_vls_strlen(&rip->sketch_name) + 1;
1629  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "revolve external");
1630 
1631  ptr = (unsigned char *)ep->ext_buf;
1632 
1633  /* Since libwdb users may want to operate in units other than mm,
1634  * we offer the opportunity to scale the solid (to get it into mm)
1635  * on the way out.
1636  */
1637  VSCALE(&vec[0*3], rip->v3d, local2mm);
1638  VSCALE(&vec[1*3], rip->axis3d, local2mm);
1639  VSCALE(&vec[2*3], rip->r, local2mm);
1640  vec[9] = rip->ang;
1641 
1642  bu_cv_htond(ptr, (unsigned char *)vec, ELEMENTS_PER_VECT*3 + 1);
1643  ptr += (ELEMENTS_PER_VECT*3 + 1) * SIZEOF_NETWORK_DOUBLE;
1644 
1645  bu_strlcpy((char *)ptr, bu_vls_addr(&rip->sketch_name), bu_vls_strlen(&rip->sketch_name) + 1);
1646 
1647  return 0;
1648 }
1649 
1650 
1651 /**
1652  * Make human-readable formatted presentation of this solid. First
1653  * line describes type of solid. Additional lines are indented one
1654  * tab, and give parameter values.
1655  */
1656 int
1657 rt_revolve_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
1658 {
1659  struct rt_revolve_internal *rip =
1660  (struct rt_revolve_internal *)ip->idb_ptr;
1661  char buf[256];
1662 
1663  RT_REVOLVE_CK_MAGIC(rip);
1664  bu_vls_strcat(str, "truncated general revolve (REVOLVE)\n");
1665 
1666  if (!verbose)
1667  return 0;
1668 
1669  sprintf(buf, "\tV (%g, %g, %g)\n",
1670  INTCLAMP(rip->v3d[X] * mm2local),
1671  INTCLAMP(rip->v3d[Y] * mm2local),
1672  INTCLAMP(rip->v3d[Z] * mm2local));
1673  bu_vls_strcat(str, buf);
1674 
1675  sprintf(buf, "\tAxis (%g, %g, %g)\n",
1676  INTCLAMP(rip->axis3d[X] * mm2local),
1677  INTCLAMP(rip->axis3d[Y] * mm2local),
1678  INTCLAMP(rip->axis3d[Z] * mm2local));
1679  bu_vls_strcat(str, buf);
1680 
1681  sprintf(buf, "\tR (%g, %g, %g)\n",
1682  INTCLAMP(rip->r[X] * mm2local),
1683  INTCLAMP(rip->r[Y] * mm2local),
1684  INTCLAMP(rip->r[Z] * mm2local));
1685  bu_vls_strcat(str, buf);
1686 
1687  sprintf(buf, "\tAngle=%g\n", INTCLAMP(rip->ang * RAD2DEG));
1688  bu_vls_strcat(str, buf);
1689 
1690  sprintf(buf, "\tsketch name: ");
1691  bu_vls_strcat(str, buf);
1692  bu_vls_vlscat(str, &rip->sketch_name);
1693 
1694  return 0;
1695 }
1696 
1697 
1698 /**
1699  * Free the storage associated with the rt_db_internal version of this
1700  * solid.
1701  */
1702 void
1704 {
1705  struct rt_revolve_internal *revolve_ip;
1706 
1707  RT_CK_DB_INTERNAL(ip);
1708 
1709  revolve_ip = (struct rt_revolve_internal *)ip->idb_ptr;
1710  RT_REVOLVE_CK_MAGIC(revolve_ip);
1711  revolve_ip->magic = 0; /* sanity */
1712 
1713  if (BU_VLS_IS_INITIALIZED(&revolve_ip->sketch_name))
1714  bu_vls_free(&revolve_ip->sketch_name);
1715  else
1716  bu_log("Freeing bogus revolve, VLS string not initialized\n");
1717 
1718  bu_free((char *)revolve_ip, "revolve ifree");
1719  ip->idb_ptr = ((void *)0); /* sanity */
1720 }
1721 
1722 
1723 /*
1724  * Local Variables:
1725  * mode: C
1726  * tab-width: 8
1727  * indent-tabs-mode: t
1728  * c-file-style: "stroustrup"
1729  * End:
1730  * ex: shiftwidth=4 tabstop=8
1731  */
void bu_vls_init(struct bu_vls *vp)
Definition: vls.c:56
void rt_revolve_ifree(struct rt_db_internal *ip)
Definition: revolve.c:1703
char * d_namep
pointer to name string
Definition: raytrace.h:859
Definition: raytrace.h:800
fastf_t cf[BN_MAX_POLY_DEGREE+1]
Definition: poly.h:50
#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_db_get_internal(struct rt_db_internal *ip, const struct directory *dp, const struct db_i *dbip, const mat_t mat, struct resource *resp)
Definition: dir.c:76
struct bn_poly * bn_poly_sub(struct bn_poly *diff, const struct bn_poly *poly1, const struct bn_poly *poly2)
subtract two polynomials
#define SIZEOF_NETWORK_DOUBLE
Definition: cv.h:48
#define BU_AVS_MAGIC
Definition: magic.h:46
#define END_FACE_NEG
Definition: revolve.c:50
Definition: list.h:118
const struct directory * st_dp
Directory entry of solid.
Definition: raytrace.h:436
#define BU_DEBUG_MEM_CHECK
Definition: debug.h:54
#define RT_DOT_TOL
Definition: raytrace.h:170
#define SMALL
Definition: defines.h:351
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
#define RT_CK_RTI(_p)
Definition: raytrace.h:1833
#define BU_VLS_IS_INITIALIZED(_vp)
Definition: vls.h:92
void rt_revolve_make(const struct rt_functab *ftp, struct rt_db_internal *intern)
Definition: revolve.c:65
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
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)
void bu_avs_merge(struct bu_attribute_value_set *dest, const struct bu_attribute_value_set *src)
Definition: avs.c:154
#define M_PI
Definition: fft.h:35
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
Definition: raytrace.h:368
#define CURVE_CARC_MAGIC
Definition: magic.h:198
Definition: raytrace.h:248
int rt_sketch_contains(struct rt_sketch_internal *, point2d_t)
Definition: sketch.c:253
fastf_t st_aradius
Radius of APPROXIMATING sphere.
Definition: raytrace.h:433
fastf_t bounds[4]
2D sketch bounds
Definition: revolve.h:46
int rt_revolve_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: revolve.c:1427
Header file for the BRL-CAD common definitions.
double add(double a, double b)
Definition: vm_test.cpp:38
Definition: poly.h:47
struct rt_sketch_internal * skt
pointer to sketch
Definition: revolve.h:44
struct bn_poly * bn_poly_mul(struct bn_poly *product, const struct bn_poly *m1, const struct bn_poly *m2)
multiply two polynomials
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
#define CURVE_NURB_MAGIC
Definition: magic.h:200
#define BU_ASSERT(_equation)
Definition: defines.h:216
void bu_cv_htond(unsigned char *out, const unsigned char *in, size_t count)
#define MAX_FASTF
Definition: defines.h:340
void rt_revolve_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
Definition: revolve.c:1082
int rt_revolve_xform(struct rt_db_internal *op, const mat_t mat, struct rt_db_internal *ip, int release, struct db_i *dbip, struct resource *resp)
Definition: revolve.c:1538
#define CURVE_BEZIER_MAGIC
Definition: magic.h:197
struct bu_list l
Definition: raytrace.h:369
#define END_FACE_POS
Definition: revolve.c:49
if(share_geom)
Definition: nmg_mod.c:3829
int idb_major_type
Definition: raytrace.h:192
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
void rt_sketch_bounds(struct rt_sketch_internal *, fastf_t *)
Definition: sketch.c:355
size_t dgr
Definition: poly.h:49
Definition: color.c:49
#define MAX_HITS
Definition: revolve.c:53
vect_t hit_vpriv
PRIVATE vector for xxx_*()
Definition: raytrace.h:253
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
void rt_revolve_free(struct soltab *stp)
Definition: revolve.c:1195
#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_revolve_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
Definition: revolve.c:1011
fastf_t crv_c2
curvature in other direction
Definition: raytrace.h:309
#define RT_CK_HIT(_p)
Definition: raytrace.h:259
struct bn_poly * bn_poly_scale(struct bn_poly *eqn, double factor)
scale a polynomial
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
#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
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
struct bu_attribute_value_set idb_avs
Definition: raytrace.h:196
struct bn_poly * bn_poly_add(struct bn_poly *sum, const struct bn_poly *poly1, const struct bn_poly *poly2)
add two polynomials
int rt_revolve_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
Definition: revolve.c:1657
struct xray * hit_rayp
pointer to defining ray
Definition: raytrace.h:256
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
point_t v3d
vertex in 3d space
Definition: revolve.h:37
#define HORIZ_SURF
Definition: revolve.c:51
#define UNUSED(parameter)
Definition: common.h:239
#define BU_PUT(_ptr, _type)
Definition: malloc.h:215
uint32_t magic
Definition: avs.h:84
goto out
Definition: nmg_mod.c:3846
Support for uniform tolerances.
Definition: tol.h:71
void bu_avs_init(struct bu_attribute_value_set *avp, size_t len, const char *str)
Definition: avs.c:47
vect_t rEnd
Definition: revolve.h:41
#define START_FACE_NEG
Definition: revolve.c:48
void rt_revolve_print(const struct soltab *stp)
Definition: revolve.c:343
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
vect_t zUnit
revolve axis in 3d space, y axis
Definition: revolve.h:38
int bu_mem_barriercheck(void)
Definition: malloc.c:660
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
int rt_revolve_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: revolve.c:1205
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
#define RT_GET_SEG(p, res)
Definition: raytrace.h:379
int * ends
indices of points at end of continuous path
Definition: revolve.h:45
#define ZERO(val)
Definition: units.c:38
int bu_debug
Definition: globals.c:87
struct rt_sketch_internal * rt_copy_sketch(const struct rt_sketch_internal *sketch_ip)
Definition: sketch.c:2246
void * idb_ptr
Definition: raytrace.h:195
int rt_revolve_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: revolve.c:1611
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
int rt_revolve_import5(struct rt_db_internal *ip, const struct bu_external *ep, const mat_t mat, const struct db_i *dbip, struct resource *resp)
Definition: revolve.c:1466
void bu_cv_ntohd(unsigned char *out, const unsigned char *in, size_t count)
const struct rt_functab OBJ[]
Definition: table.c:159
#define RT_CK_RESOURCE(_p)
Definition: raytrace.h:1490
int rt_poly_roots(bn_poly_t *eqn, bn_complex_t roots[], const char *name)
int rt_revolve_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
Definition: revolve.c:366
int curve_to_vlist(struct bu_list *vhead, const struct rt_tess_tol *ttol, point_t V, vect_t u_vec, vect_t v_vec, struct rt_sketch_internal *sketch_ip, struct rt_curve *crv)
void bn_vec_ortho(vect_t out, const vect_t in)
#define FMAX(a, b)
Definition: common.h:102
#define RT_CK_SOLTAB(_p)
Definition: raytrace.h:453
#define RT_DIR_NULL
Definition: raytrace.h:875
#define LOOKUP_NOISY
Definition: raytrace.h:892
char * sketch_name
name of sketch
Definition: revolve.h:43
#define ID_REVOLVE
Solid of Revolution.
Definition: raytrace.h:511
void * st_specific
-> ID-specific (private) struct
Definition: raytrace.h:435
vect_t yUnit
Definition: revolve.h:40
#define RT_REVOLVE_INTERNAL_MAGIC
Definition: magic.h:105
fastf_t crv_c1
curvature in principle dir
Definition: raytrace.h:308
Definition: color.c:51
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
int hit_surfno
solid-specific surface indicator
Definition: raytrace.h:255
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 BU_CK_EXTERNAL(_p)
Definition: parse.h:224
Complex numbers.
Definition: complex.h:39
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
vect_t xUnit
vector in start plane, x axis
Definition: revolve.h:39
#define CURVE_LSEG_MAGIC
Definition: magic.h:199
void bu_vls_vlscat(struct bu_vls *dest, const struct bu_vls *src)
Definition: vls.c:415
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
void rt_revolve_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
Definition: revolve.c:1103
#define M_SQRT1_2
Definition: fft.h:38
double fastf_t
Definition: defines.h:300
#define START_FACE_POS
Definition: revolve.c:47
#define VPRINT(a, b)
Definition: raytrace.h:1881
fastf_t ang
angle to revolve
Definition: revolve.h:42
#define ID_SKETCH
2D sketch
Definition: raytrace.h:484
int rt_revolve_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: revolve.c:208
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
Definition: color.c:50
fastf_t uv_v
Range 0..1.
Definition: raytrace.h:342
point_t st_center
Centroid of solid.
Definition: raytrace.h:432
#define FMIN(a, b)
Definition: common.h:105
#define RT_HIT_MAGIC
Definition: magic.h:161
int rt_revolve_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *tol)
Definition: revolve.c:88
#define BU_VLS_INIT(_vp)
Definition: vls.h:74