BRL-CAD
ars.c
Go to the documentation of this file.
1 /* A R S . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1985-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/ars/ars.c
23  *
24  * Intersect a ray with an ARS (Arbitrary faceted solid).
25  *
26  */
27 
28 #include "common.h"
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <math.h>
34 #include <ctype.h>
35 #include "bnetwork.h"
36 
37 #include "tcl.h"
38 #include "bu/cv.h"
39 #include "vmath.h"
40 #include "db.h"
41 #include "nmg.h"
42 #include "rtgeom.h"
43 #include "raytrace.h"
44 #include "bot.h"
45 
46 #include "../../librt_private.h"
47 
48 
49 #define TRI_NULL ((struct tri_specific *)0)
50 
51 #define IJ(ii, jj) (((i+(ii))*(arip->pts_per_curve+1))+(j+(jj)))
52 #define ARS_PT(ii, jj) (&arip->curves[i+(ii)][(j+(jj))*ELEMENTS_PER_VECT])
53 #define FIND_IJ(a, b) \
54  if (!(verts[IJ(a, b)])) { \
55  verts[IJ(a, b)] = \
56  nmg_find_pt_in_shell(s, ARS_PT(a, b), tol); \
57  }
58 #define ASSOC_GEOM(corn, a, b) \
59  if (!((*corners[corn])->vg_p)) { \
60  nmg_vertex_gv(*(corners[corn]), ARS_PT(a, b)); \
61  }
62 
63 
64 /* Describe algorithm here */
65 
66 /* from g_bot.c */
67 extern int rt_bot_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip);
68 extern void rt_bot_ifree(struct rt_db_internal *ip);
69 
70 
71 void
72 rt_ars_free(register struct soltab *stp)
73 {
74  register struct tri_specific *trip =
75  (struct tri_specific *)stp->st_specific;
76 
77  if (trip == TRI_NULL)
78  bu_bomb("rt_ars_free s/b rt_bot_free\n");
79 }
80 
81 
82 int
83 rt_ars_class(const struct soltab *stp,
84  const vect_t UNUSED(min),
85  const vect_t UNUSED(max),
86  const struct bn_tol *UNUSED(tol))
87 {
88  register struct tri_specific *trip =
89  (struct tri_specific *)stp->st_specific;
90 
91  if (trip == TRI_NULL)
92  bu_bomb("rt_ars_class s/b rt_bot_class\n");
93 
94  return 0;
95 }
96 
97 
98 /**
99  * reads a set of ARS B records and returns a pointer to memory
100  * allocated for holding the curve's fastf_t values.
101  */
102 HIDDEN fastf_t *
103 ars_rd_curve(union record *rp, int npts, int flip)
104 {
105  int lim;
106  fastf_t *base;
107  register fastf_t *fp; /* pointer to temp vector */
108  register int i;
109  union record *rr;
110  int rec;
111 
112  /* Leave room for first point to be repeated */
113  base = fp = (fastf_t *)bu_malloc(
114  (npts+1) * sizeof(fastf_t) * ELEMENTS_PER_VECT,
115  "ars curve");
116 
117  rec = 0;
118  for (; npts > 0; npts -= 8) {
119  rr = &rp[rec++];
120  if (rr->b.b_id != ID_ARS_B) {
121  bu_log("ars_rd_curve(npts=%d): non-ARS_B record [%d]!\n", npts, rr->b.b_id);
122  break;
123  }
124  lim = (npts>8) ? 8 : npts;
125  for (i = 0; i < lim; i++) {
126  vect_t vec;
127 
128  /* cvt from dbfloat_t */
129  flip_fastf_float(vec, (&(rr->b.b_values[i*3])), 1, flip);
130  VMOVE(fp, vec);
131 
132  fp += ELEMENTS_PER_VECT;
133  }
134  }
135  return base;
136 }
137 
138 
139 /**
140  * Read all the curves in as a two dimensional array. The caller is
141  * responsible for freeing the dynamic memory.
142  *
143  * Note that in each curve array, the first point is replicated as the
144  * last point, to make processing the data easier.
145  */
146 int
147 rt_ars_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
148 {
149  struct rt_ars_internal *ari;
150  union record *rp;
151  register size_t i, j;
152  vect_t base_vect;
153  int currec;
154 
155  VSETALL(base_vect, 0);
156 
157  if (dbip) RT_CK_DBI(dbip);
158 
159  BU_CK_EXTERNAL(ep);
160  rp = (union record *)ep->ext_buf;
161  if (rp->u_id != ID_ARS_A) {
162  bu_log("rt_ars_import4: defective record\n");
163  return -1;
164  }
165 
166  RT_CK_DB_INTERNAL(ip);
167  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
168  ip->idb_type = ID_ARS;
169  ip->idb_meth = &OBJ[ID_ARS];
170  BU_ALLOC(ip->idb_ptr, struct rt_ars_internal);
171 
172  ari = (struct rt_ars_internal *)ip->idb_ptr;
173  ari->magic = RT_ARS_INTERNAL_MAGIC;
174 
175  if (dbip->dbi_version < 0) {
176  ari->ncurves = flip_short(rp[0].a.a_m);
177  ari->pts_per_curve = flip_short(rp[0].a.a_n);
178  } else {
179  ari->ncurves = rp[0].a.a_m;
180  ari->pts_per_curve = rp[0].a.a_n;
181  }
182 
183  /*
184  * Read all the curves into internal form.
185  */
186  ari->curves = (fastf_t **)bu_malloc(
187  (ari->ncurves+1) * sizeof(fastf_t *), "ars curve ptrs");
188 
189  currec = 1;
190  for (i = 0; i < ari->ncurves; i++) {
191  ari->curves[i] = ars_rd_curve(&rp[currec], ari->pts_per_curve, dbip->dbi_version < 0 ? 1 : 0);
192  currec += (ari->pts_per_curve+7)/8;
193  }
194 
195  /* Convert from vector to point notation IN PLACE by rotating
196  * vectors and adding base vector. Observe special treatment for
197  * base vector.
198  */
199  if (mat == NULL) mat = bn_mat_identity;
200  for (i = 0; i < ari->ncurves; i++) {
201  register fastf_t *v;
202 
203  v = ari->curves[i];
204  for (j = 0; j < ari->pts_per_curve; j++) {
205  vect_t homog;
206 
207  if (i == 0 && j == 0) {
208  /* base vector */
209  VMOVE(homog, v);
210  MAT4X3PNT(base_vect, mat, homog);
211  VMOVE(v, base_vect);
212  } else {
213  MAT4X3VEC(homog, mat, v);
214  VADD2(v, base_vect, homog);
215  }
216  v += ELEMENTS_PER_VECT;
217  }
218  VMOVE(v, ari->curves[i]); /* replicate first point */
219  }
220  return 0;
221 }
222 
223 
224 /**
225  * The name will be added by the caller. Generally, only libwdb will
226  * set conv2mm != 1.0
227  */
228 int
229 rt_ars_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
230 {
231  struct rt_ars_internal *arip;
232  union record *rec;
233  point_t base_pt;
234  size_t per_curve_grans;
235  size_t cur; /* current curve number */
236  size_t gno; /* current granule number */
237 
238  RT_CK_DB_INTERNAL(ip);
239  if (dbip) RT_CK_DBI(dbip);
240 
241  if (ip->idb_type != ID_ARS) return -1;
242  arip = (struct rt_ars_internal *)ip->idb_ptr;
243  RT_ARS_CK_MAGIC(arip);
244 
245  per_curve_grans = (arip->pts_per_curve+7)/8;
246 
247  BU_CK_EXTERNAL(ep);
248  ep->ext_nbytes = (1 + per_curve_grans * arip->ncurves) *
249  sizeof(union record);
250  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "ars external");
251  rec = (union record *)ep->ext_buf;
252 
253  rec[0].a.a_id = ID_ARS_A;
254  rec[0].a.a_type = ARS; /* obsolete? */
255  rec[0].a.a_m = arip->ncurves;
256  rec[0].a.a_n = arip->pts_per_curve;
257  rec[0].a.a_curlen = per_curve_grans;
258  rec[0].a.a_totlen = per_curve_grans * arip->ncurves;
259 
260  VMOVE(base_pt, &arip->curves[0][0]);
261  gno = 1;
262  for (cur = 0; cur < arip->ncurves; cur++) {
263  register fastf_t *fp;
264  size_t npts;
265  int left;
266 
267  fp = arip->curves[cur];
268  left = arip->pts_per_curve;
269  for (npts = 0; npts < arip->pts_per_curve; npts+=8, left -= 8) {
270  register int el;
271  register int lim;
272  register struct ars_ext *bp = &rec[gno].b;
273 
274  bp->b_id = ID_ARS_B;
275  bp->b_type = ARSCONT; /* obsolete? */
276  bp->b_n = cur+1; /* obsolete? */
277  bp->b_ngranule = (npts/8)+1; /* obsolete? */
278 
279  lim = (left > 8) ? 8 : left;
280  for (el = 0; el < lim; el++) {
281  vect_t diff;
282  if (cur == 0 && npts == 0 && el == 0) {
283  VSCALE(diff, fp, local2mm);
284  } else {
285  VSUB2SCALE(diff, fp, base_pt, local2mm);
286  }
287  /* NOTE: also type converts to dbfloat_t */
288  VMOVE(&(bp->b_values[el*3]), diff);
289  fp += ELEMENTS_PER_VECT;
290  }
291  gno++;
292  }
293  }
294  return 0;
295 }
296 
297 
298 /**
299  * Read all the curves in as a two dimensional array. The caller is
300  * responsible for freeing the dynamic memory.
301  *
302  * Note that in each curve array, the first point is replicated as the
303  * last point, to make processing the data easier.
304  */
305 int
306 rt_ars_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
307 {
308  struct rt_ars_internal *ari;
309  register size_t i, j;
310  register unsigned char *cp;
311  register fastf_t *fp;
312 
313  /* must be double for import and export */
314  double tmp_pnt[ELEMENTS_PER_POINT];
315 
316  RT_CK_DB_INTERNAL(ip);
317  BU_CK_EXTERNAL(ep);
318  if (dbip) RT_CK_DBI(dbip);
319 
320  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
321  ip->idb_type = ID_ARS;
322  ip->idb_meth = &OBJ[ID_ARS];
323  BU_ALLOC(ip->idb_ptr, struct rt_ars_internal);
324 
325  ari = (struct rt_ars_internal *)ip->idb_ptr;
326  ari->magic = RT_ARS_INTERNAL_MAGIC;
327 
328  cp = (unsigned char *)ep->ext_buf;
329  ari->ncurves = ntohl(*(uint32_t *)cp);
330  cp += SIZEOF_NETWORK_LONG;
331  ari->pts_per_curve = ntohl(*(uint32_t *)cp);
332  cp += SIZEOF_NETWORK_LONG;
333 
334  /*
335  * Read all the curves into internal form.
336  */
337  ari->curves = (fastf_t **)bu_calloc(
338  (ari->ncurves+1), sizeof(fastf_t *), "ars curve ptrs");
339  if (mat == NULL) mat = bn_mat_identity;
340  for (i = 0; i < ari->ncurves; i++) {
341  ari->curves[i] = (fastf_t *)bu_calloc((ari->pts_per_curve + 1) * ELEMENTS_PER_POINT,
342  sizeof(fastf_t), "ARS points");
343  fp = ari->curves[i];
344  for (j = 0; j < ari->pts_per_curve; j++) {
345  bu_cv_ntohd((unsigned char *)tmp_pnt, cp, ELEMENTS_PER_POINT);
346  MAT4X3PNT(fp, mat, tmp_pnt);
347  cp += ELEMENTS_PER_POINT * SIZEOF_NETWORK_DOUBLE;
348  fp += ELEMENTS_PER_POINT;
349  }
350  VMOVE(fp, ari->curves[i]); /* duplicate first point */
351  }
352  return 0;
353 }
354 
355 
356 /**
357  * The name will be added by the caller. Generally, only libwdb will
358  * set conv2mm != 1.0
359  */
360 int
361 rt_ars_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
362 {
363  struct rt_ars_internal *arip;
364  unsigned char *cp;
365  size_t cur; /* current curve number */
366 
367  /* must be double for import and export */
368  double tmp_pnt[ELEMENTS_PER_POINT];
369 
370  RT_CK_DB_INTERNAL(ip);
371  if (ip->idb_type != ID_ARS) return -1;
372  arip = (struct rt_ars_internal *)ip->idb_ptr;
373  RT_ARS_CK_MAGIC(arip);
374 
375  if (dbip) RT_CK_DBI(dbip);
376 
377  BU_CK_EXTERNAL(ep);
378  ep->ext_nbytes = 2 * SIZEOF_NETWORK_LONG + ELEMENTS_PER_POINT * arip->ncurves * arip->pts_per_curve * SIZEOF_NETWORK_DOUBLE;
379  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "ars external");
380  cp = (unsigned char *)ep->ext_buf;
381 
382  *(uint32_t *)cp = htonl(arip->ncurves);
383  cp += SIZEOF_NETWORK_LONG;
384  *(uint32_t *)cp = htonl(arip->pts_per_curve);
385  cp += SIZEOF_NETWORK_LONG;
386 
387  for (cur = 0; cur < arip->ncurves; cur++) {
388  register fastf_t *fp;
389  size_t npts;
390 
391  fp = arip->curves[cur];
392  for (npts = 0; npts < arip->pts_per_curve; npts++) {
393  VSCALE(tmp_pnt, fp, local2mm);
394  bu_cv_htond(cp, (unsigned char *)tmp_pnt, ELEMENTS_PER_POINT);
395  cp += ELEMENTS_PER_POINT * SIZEOF_NETWORK_DOUBLE;
396  fp += ELEMENTS_PER_POINT;
397  }
398  }
399  return 0;
400 }
401 
402 
403 /**
404  * Make human-readable formatted presentation of this solid. First
405  * line describes type of solid. Additional lines are indented one
406  * tab, and give parameter values.
407  */
408 int
409 rt_ars_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
410 {
411  register size_t i, j;
412  register struct rt_ars_internal *arip =
413  (struct rt_ars_internal *)ip->idb_ptr;
414  char buf[256];
415 
416  RT_ARS_CK_MAGIC(arip);
417  bu_vls_strcat(str, "arbitrary rectangular solid (ARS)\n");
418 
419  sprintf(buf, "\t%lu curves, %lu points per curve\n", (long unsigned)arip->ncurves, (long unsigned)arip->pts_per_curve);
420  bu_vls_strcat(str, buf);
421 
422  if (arip->ncurves > 0) {
423  sprintf(buf, "\tV (%g, %g, %g)\n",
424  INTCLAMP(arip->curves[0][X] * mm2local),
425  INTCLAMP(arip->curves[0][Y] * mm2local),
426  INTCLAMP(arip->curves[0][Z] * mm2local));
427  bu_vls_strcat(str, buf);
428  }
429 
430  if (!verbose) return 0;
431 
432  /* Print out all the points */
433  for (i = 0; i < arip->ncurves; i++) {
434  register fastf_t *v = arip->curves[i];
435 
436  sprintf(buf, "\tCurve %lu:\n", (long unsigned)i);
437  bu_vls_strcat(str, buf);
438  for (j = 0; j < arip->pts_per_curve; j++) {
439  sprintf(buf, "\t\t(%g, %g, %g)\n",
440  INTCLAMP(v[X] * mm2local),
441  INTCLAMP(v[Y] * mm2local),
442  INTCLAMP(v[Z] * mm2local));
443  bu_vls_strcat(str, buf);
444  v += ELEMENTS_PER_VECT;
445  }
446  }
447 
448  return 0;
449 }
450 
451 
452 /**
453  * Free the storage associated with the rt_db_internal version of this
454  * solid.
455  */
456 void
458 {
459  register struct rt_ars_internal *arip;
460  register size_t i;
461 
462  RT_CK_DB_INTERNAL(ip);
463  arip = (struct rt_ars_internal *)ip->idb_ptr;
464  RT_ARS_CK_MAGIC(arip);
465 
466  /*
467  * Free storage for faces
468  */
469  for (i = 0; i < arip->ncurves; i++) {
470  bu_free((char *)arip->curves[i], "ars curve");
471  }
472  bu_free((char *)arip->curves, "ars curve ptrs");
473  arip->magic = 0; /* sanity */
474  arip->ncurves = 0;
475  bu_free((char *)arip, "ars ifree");
476  ip->idb_ptr = ((void *)0); /* sanity */
477 }
478 
479 
480 int
481 rt_ars_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol)
482 {
483  register size_t i;
484  register size_t j;
485  register size_t k;
486  struct rt_ars_internal *arip;
487  struct shell *s;
488  struct vertex **verts;
489  struct faceuse *fu;
490  struct bu_ptbl kill_fus;
491  int bad_ars = 0;
492 
493  RT_CK_DB_INTERNAL(ip);
494  arip = (struct rt_ars_internal *)ip->idb_ptr;
495  RT_ARS_CK_MAGIC(arip);
496 
497  /* Check for a legal ARS */
498  for (i = 0; i < arip->ncurves-1; i++) {
499  for (j = 2; j < arip->pts_per_curve; j++) {
500  fastf_t dist;
501  vect_t pca;
502  int code;
503 
504  if (VNEAR_EQUAL(ARS_PT(0, -2), ARS_PT(0, -1), tol->dist))
505  continue;
506 
507  code = bn_dist_pt3_lseg3(&dist, pca, ARS_PT(0, -2), ARS_PT(0, -1), ARS_PT(0, 0), tol);
508 
509  if (code < 2) {
510  bu_log("ARS curve backtracks on itself!!!\n");
511  bu_log("\tCurve #%zu, points #%zu through %zu are:\n", i, j-2, j);
512  bu_log("\t\t%zu (%f %f %f)\n", j-2, V3ARGS(ARS_PT(0, -2)));
513  bu_log("\t\t%zu (%f %f %f)\n", j-1, V3ARGS(ARS_PT(0, -1)));
514  bu_log("\t\t%zu (%f %f %f)\n", j, V3ARGS(ARS_PT(0, 0)));
515  bad_ars = 1;
516  j++;
517  }
518  }
519  }
520 
521  if (bad_ars) {
522  bu_log("TESSELLATION FAILURE: This ARS solid has not been tessellated.\n\tAny result you may obtain is incorrect.\n");
523  return -1;
524  }
525 
526  bu_ptbl_init(&kill_fus, 64, " &kill_fus");
527 
528  /* Build the topology of the ARS. Start by allocating storage */
529 
530  *r = nmg_mrsv(m); /* Make region, empty shell, vertex */
531  s = BU_LIST_FIRST(shell, &(*r)->s_hd);
532 
533  verts = (struct vertex **)bu_calloc(arip->ncurves * (arip->pts_per_curve+1),
534  sizeof(struct vertex *),
535  "rt_ars_tess *verts[]");
536 
537  /*
538  * Draw the "waterlines", by tracing each curve. n+1th point is
539  * first point replicated by import code.
540  */
541  k = arip->pts_per_curve-2; /* next to last point on curve */
542  for (i = 0; i < arip->ncurves-1; i++) {
543  int double_ended;
544 
545  if (k != 1
546  && VNEAR_EQUAL(&arip->curves[i][1*ELEMENTS_PER_VECT], &arip->curves[i][k*ELEMENTS_PER_VECT], tol->dist))
547  {
548  double_ended = 1;
549  } else {
550  double_ended = 0;
551  }
552 
553  for (j = 0; j < arip->pts_per_curve; j++) {
554  struct vertex **corners[3];
555 
556 
557  if (double_ended &&
558  i != 0 &&
559  (j == 0 || j == k || j == arip->pts_per_curve-1))
560  continue;
561 
562  /*
563  * First triangular face
564  */
565  if (bn_3pts_distinct(ARS_PT(0, 0), ARS_PT(1, 1), ARS_PT(0, 1), tol)
566  && !bn_3pts_collinear(ARS_PT(0, 0), ARS_PT(1, 1), ARS_PT(0, 1), tol))
567  {
568  /* Locate these points, if previously mentioned */
569  FIND_IJ(0, 0);
570  FIND_IJ(1, 1);
571  FIND_IJ(0, 1);
572 
573  /* Construct first face topology, CCW order */
574  corners[0] = &verts[IJ(0, 0)];
575  corners[1] = &verts[IJ(0, 1)];
576  corners[2] = &verts[IJ(1, 1)];
577 
578  if ((fu = nmg_cmface(s, corners, 3)) == (struct faceuse *)0) {
579  bu_log("rt_ars_tess() nmg_cmface failed, skipping face a[%zu][%zu]\n",
580  i, j);
581  }
582 
583  /* Associate vertex geometry, if new */
584  ASSOC_GEOM(0, 0, 0);
585  ASSOC_GEOM(1, 0, 1);
586  ASSOC_GEOM(2, 1, 1);
587  if (nmg_calc_face_g(fu)) {
588  bu_log("Degenerate face created, will kill it later\n");
589  bu_ptbl_ins(&kill_fus, (long *)fu);
590  }
591  }
592 
593  /*
594  * Second triangular face
595  */
596  if (bn_3pts_distinct(ARS_PT(1, 0), ARS_PT(1, 1), ARS_PT(0, 0), tol)
597  && !bn_3pts_collinear(ARS_PT(1, 0), ARS_PT(1, 1), ARS_PT(0, 0), tol))
598  {
599  /* Locate these points, if previously mentioned */
600  FIND_IJ(1, 0);
601  FIND_IJ(1, 1);
602  FIND_IJ(0, 0);
603 
604  /* Construct second face topology, CCW */
605  corners[0] = &verts[IJ(1, 0)];
606  corners[1] = &verts[IJ(0, 0)];
607  corners[2] = &verts[IJ(1, 1)];
608 
609  if ((fu = nmg_cmface(s, corners, 3)) == (struct faceuse *)0) {
610  bu_log("rt_ars_tess() nmg_cmface failed, skipping face b[%zu][%zu]\n",
611  i, j);
612  }
613 
614  /* Associate vertex geometry, if new */
615  ASSOC_GEOM(0, 1, 0);
616  ASSOC_GEOM(1, 0, 0);
617  ASSOC_GEOM(2, 1, 1);
618  if (nmg_calc_face_g(fu)) {
619  bu_log("Degenerate face created, will kill it later\n");
620  bu_ptbl_ins(&kill_fus, (long *)fu);
621  }
622  }
623  }
624  }
625 
626  bu_free((char *)verts, "rt_ars_tess *verts[]");
627 
628  /* kill any degenerate faces that may have been created */
629  for (i = 0; i < (size_t)BU_PTBL_END(&kill_fus); i++) {
630  fu = (struct faceuse *)BU_PTBL_GET(&kill_fus, i);
631  NMG_CK_FACEUSE(fu);
632  (void)nmg_kfu(fu);
633  }
634 
635  /* ARS solids are often built with incorrect face normals. Don't
636  * depend on them to be correct.
637  */
638  nmg_fix_normals(s, tol);
639 
640  /* set edge's is_real flag */
641  nmg_mark_edges_real(&s->l.magic);
642 
643  /* Compute "geometry" for region and shell */
644  nmg_region_a(*r, tol);
645 
648 
649  return 0;
650 }
651 
652 
653 /**
654  * TODO: produces bboxes that are waaay too big.
655  */
656 int
657 rt_ars_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol))
658 {
659  register size_t i;
660  register size_t j;
661  struct rt_ars_internal *arip;
662 
663  RT_CK_DB_INTERNAL(ip);
664  arip = (struct rt_ars_internal *)ip->idb_ptr;
665  RT_ARS_CK_MAGIC(arip);
666 
667  VSETALL((*min), INFINITY);
668  VSETALL((*max), -INFINITY);
669 
670  /*
671  * Iterate over the curves.
672  */
673  for (i = 0; i < arip->ncurves; i++) {
674  register fastf_t *v1;
675 
676  v1 = arip->curves[i];
677  VMINMAX((*min), (*max), v1);
678  v1 += ELEMENTS_PER_VECT;
679  for (j = 1; j <= arip->pts_per_curve; j++, v1 += ELEMENTS_PER_VECT)
680  VMINMAX((*min), (*max), v1);
681  }
682 
683  return 0;
684 }
685 
686 
687 /**
688  * This routine is used to prepare a list of planar faces for being
689  * shot at by the ars routines.
690  *
691  * Process an ARS, which is represented as a vector from the origin to
692  * the first point, and many vectors from the first point to the
693  * remaining points.
694  *
695  * This routine is unusual in that it has to read additional database
696  * records to obtain all the necessary information.
697  */
698 int
699 rt_ars_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
700 {
701  struct rt_db_internal intern;
702  struct rt_bot_internal *bot;
703  struct model *m;
704  struct nmgregion *r;
705  struct shell *s;
706  int ret;
707 
708  /*point_t min, max;*/
709  /*if (rt_ars_bbox(ip, &min, &max, &rtip->rti_tol)) return -1;*/
710 
711  m = nmg_mm();
712  r = BU_LIST_FIRST(nmgregion, &m->r_hd);
713 
714  if (rt_ars_tess(&r, m, ip, &rtip->rti_ttol, &rtip->rti_tol)) {
715  bu_log("Failed to tessellate ARS (%s)\n", stp->st_dp->d_namep);
716  nmg_km(m);
717  return -1;
718  }
719  rt_ars_ifree(ip);
720 
721  s = BU_LIST_FIRST(shell, &r->s_hd);
722  bot = nmg_bot(s, &rtip->rti_tol);
723 
724  if (!bot) {
725  bu_log("Failed to convert ARS to BOT (%s)\n", stp->st_dp->d_namep);
726  nmg_km(m);
727  return -1;
728  }
729 
730  nmg_km(m);
731 
733  intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
734  intern.idb_minor_type = ID_BOT;
735  intern.idb_meth = &OBJ[ID_BOT];
736  intern.idb_ptr = (void *)bot;
737  bu_avs_init(&intern.idb_avs, 0, "ARS to a BOT for prep");
738 
739  ret = rt_bot_prep(stp, &intern, rtip);
740 
741  rt_bot_ifree(&intern);
742 
743  /* Use the ars bbox results, rather than the BoT results */
744  /*VMOVE(stp->st_min, min);
745  VMOVE(stp->st_max, max);*/
746 
747  return ret;
748 }
749 
750 
751 void
752 rt_ars_print(register const struct soltab *stp)
753 {
754  register struct tri_specific *trip =
755  (struct tri_specific *)stp->st_specific;
756 
757  if (trip == TRI_NULL) {
758  bu_log("ars(%s): no faces\n", stp->st_name);
759  return;
760  }
761  do {
762  VPRINT("A", trip->tri_A);
763  VPRINT("B-A", trip->tri_BA);
764  VPRINT("C-A", trip->tri_CA);
765  VPRINT("BA x CA", trip->tri_wn);
766  VPRINT("Normal", trip->tri_N);
767  bu_log("\n");
768  trip = trip->tri_forw;
769  } while (trip);
770 }
771 
772 
773 /**
774  * Shoot a ray at an ARS.
775  *
776  * Returns -
777  * 0 MISS
778  * !0 HIT
779  */
780 int
781 rt_ars_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
782 {
783  register struct tri_specific *trip =
784  (struct tri_specific *)stp->st_specific;
785 #define RT_ARS_MAXHITS 128 /* # surfaces hit, must be even */
786  struct hit hits[RT_ARS_MAXHITS];
787  register struct hit *hp;
788  int nhits;
789 
790  nhits = 0;
791  hp = &hits[0];
792 
793  /* consider each face */
794  for (; trip; trip = trip->tri_forw) {
795  fastf_t dn; /* Direction dot Normal */
796  fastf_t abs_dn;
797  fastf_t k;
798  fastf_t alpha, beta;
799  fastf_t ds;
800  vect_t wxb; /* vertex - ray_start */
801  vect_t xp; /* wxb cross ray_dir */
802 
803  /* Ray Direction dot N. (wn is inward pointing normal) */
804  dn = VDOT(trip->tri_wn, rp->r_dir);
805  if (RT_G_DEBUG & DEBUG_ARB8)
806  bu_log("N.Dir=%g ", dn);
807 
808  /* If ray lies directly along the face, drop this face. */
809  abs_dn = dn >= 0.0 ? dn : (-dn);
810  if (abs_dn < 1.0e-10)
811  continue;
812  VSUB2(wxb, trip->tri_A, rp->r_pt);
813  VCROSS(xp, wxb, rp->r_dir);
814 
815  /* Check for exceeding along the one side */
816  alpha = VDOT(trip->tri_CA, xp);
817  if (dn < 0.0) alpha = -alpha;
818  if (alpha < 0.0 || alpha > abs_dn)
819  continue;
820 
821  /* Check for exceeding along the other side */
822  beta = VDOT(trip->tri_BA, xp);
823  if (dn > 0.0) beta = -beta;
824  if (beta < 0.0 || beta > abs_dn)
825  continue;
826  if (alpha+beta > abs_dn)
827  continue;
828  ds = VDOT(wxb, trip->tri_wn);
829  k = ds / dn; /* shot distance */
830 
831  /* For hits other than the first one, might check to see it
832  * this is approx. equal to previous one
833  */
834 
835  /* If dn < 0, we should be entering the solid. However, we
836  * just assume in/out sorting later will work.
837  */
838  hp->hit_magic = RT_HIT_MAGIC;
839  hp->hit_dist = k;
840  hp->hit_private = (char *)trip;
841  hp->hit_vpriv[X] = dn;
842  hp->hit_rayp = rp;
843  hp->hit_surfno = trip->tri_surfno;
844 
845  if (RT_G_DEBUG&DEBUG_ARB8) bu_log("ars: dist k=%g, ds=%g, dn=%g\n", k, ds, dn);
846 
847  /* Bug fix: next line was "nhits++". This caused rt_hitsort
848  * to exceed bounds of "hits" array by one member and clobber
849  * some stack variables i.e. "stp" -- GSM
850  */
851  if (++nhits >= RT_ARS_MAXHITS) {
852  bu_log("ars(%s): too many hits\n", stp->st_name);
853  break;
854  }
855  hp++;
856  }
857  if (nhits == 0)
858  return 0; /* MISS */
859 
860  /* Sort hits, Near to Far */
861  rt_hitsort(hits, nhits);
862 
863  /* Remove duplicate hits.
864  * We remove one of a pair of hits when they are
865  * 1) close together, and
866  * 2) both "entry" or both "exit" occurrences.
867  *
868  * Two immediate "entry" or two immediate "exit" hits suggest that
869  * we hit both of two joined faces, while we want to hit only one.
870  * An "entry" followed by an "exit" (or vice versa) suggests that
871  * we grazed an edge, and thus we should leave both in the hit
872  * list.
873  */
874  {
875  register int i, j;
876 
877  if (nhits) {
878  RT_HIT_NORMAL(NULL, &hits[0], stp, 0, 0);
879  }
880 
881  for (i = 0; i < nhits - 1; i++) {
882  RT_HIT_NORMAL(NULL, &hits[i+1], stp, 0, 0);
883  if (NEAR_EQUAL(hits[i].hit_dist, hits[i+1].hit_dist, ap->a_rt_i->rti_tol.dist) &&
884  VDOT(hits[i].hit_normal, rp->r_dir) *
885  VDOT(hits[i+1].hit_normal, rp->r_dir) > 0) {
886  for (j = i; j < nhits-1; j++)
887  hits[j] = hits[j+1];
888  nhits--;
889  i--;
890  }
891  }
892  }
893 
894  if (nhits&1) {
895  register int i;
896  /*
897  * If this condition exists, it is almost certainly due to the
898  * dn==0 check above. Just log error.
899  */
900  bu_log("ERROR: ars(%s): %d hits odd, skipping solid\n",
901  stp->st_name, nhits);
902  for (i = 0; i < nhits; i++)
903  bu_log("k=%g dn=%g\n",
904  hits[i].hit_dist, hp->hit_vpriv[X]);
905  return 0; /* MISS */
906  }
907 
908  /* nhits is even, build segments */
909  {
910  register struct seg *segp;
911  register int i, j;
912 
913  /* Check in/out properties */
914  for (i=nhits; i > 0; i -= 2) {
915  if (hits[i-2].hit_vpriv[X] >= 0)
916  continue; /* seg_in */
917  if (hits[i-1].hit_vpriv[X] <= 0)
918  continue; /* seg_out */
919 
920 #ifndef CONSERVATIVE
921  /* if this segment is small enough, just swap the in/out hits */
922  if ((hits[i-1].hit_dist - hits[i-2].hit_dist) < 200.0*RT_LEN_TOL) {
923  struct hit temp;
924  fastf_t temp_dist;
925 
926  temp_dist = hits[i-1].hit_dist;
927  hits[i-1].hit_dist = hits[i-2].hit_dist;
928  hits[i-2].hit_dist = temp_dist;
929 
930  temp = hits[i-1]; /* struct copy */
931  hits[i-1] = hits[i-2]; /* struct copy */
932  hits[i-2] = temp; /* struct copy */
933  continue;
934  }
935 #endif
936  bu_log("ars(%s): in/out error\n", stp->st_name);
937  for (j=nhits-1; j >= 0; j--) {
938  bu_log("%d %s dist=%g dn=%g\n",
939  j,
940  ((hits[j].hit_vpriv[X] > 0) ?
941  " In" : "Out"),
942  hits[j].hit_dist,
943  hits[j].hit_vpriv[X]);
944  if (j>0)
945  bu_log("\tseg length = %g\n", hits[j].hit_dist - hits[j-1].hit_dist);
946  }
947 #ifdef CONSERVATIVE
948  return 0;
949 #else
950  /* For now, just chatter, and return *something* */
951  break;
952 #endif
953  }
954 
955  for (i=nhits; i > 0; i -= 2) {
956  RT_GET_SEG(segp, ap->a_resource);
957  segp->seg_stp = stp;
958  segp->seg_in = hits[i-2]; /* struct copy */
959  segp->seg_out = hits[i-1]; /* struct copy */
960  BU_LIST_INSERT(&(seghead->l), &(segp->l));
961  }
962  }
963  return nhits; /* HIT */
964 }
965 
966 
967 /**
968  * Sort an array of hits into ascending order.
969  */
970 void
971 rt_hitsort(register struct hit *h, register int nh)
972 {
973  register int i, j;
974  struct hit temp;
975 
976  for (i = 0; i < nh-1; i++) {
977  for (j = i + 1; j < nh; j++) {
978  if (h[i].hit_dist <= h[j].hit_dist)
979  continue;
980  temp = h[j]; /* struct copy */
981  h[j] = h[i]; /* struct copy */
982  h[i] = temp; /* struct copy */
983  }
984  }
985 }
986 
987 
988 /**
989  * Given ONE ray distance, return the normal and entry/exit point.
990  */
991 void
992 rt_ars_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
993 {
994  struct tri_specific *trip = (struct tri_specific *)stp->st_specific;
995  if (!trip)
996  return;
997 
998  VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
999  VMOVE(hitp->hit_normal, trip->tri_N);
1000 }
1001 
1002 
1003 /**
1004  * Return the "curvature" of the ARB face. Pick a principle direction
1005  * orthogonal to normal, and indicate no curvature.
1006  */
1007 void
1008 rt_ars_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
1009 {
1010  struct tri_specific *trip = (struct tri_specific *)stp->st_specific;
1011  if (!trip)
1012  return;
1013 
1014  bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal);
1015  cvp->crv_c1 = cvp->crv_c2 = 0;
1016 }
1017 
1018 
1019 /**
1020  * For a hit on a face of an ARB, return the (u, v) coordinates of the
1021  * hit point. 0 <= u, v <= 1.
1022  *
1023  * u extends along the Xbasis direction defined by B-A,
1024  * v extends along the "Ybasis" direction defined by (B-A)xN.
1025  */
1026 void
1027 rt_ars_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
1028 {
1029  vect_t P_A;
1030  fastf_t r;
1031  fastf_t xxlen, yylen;
1032 
1033  struct tri_specific *trip = (struct tri_specific *)stp->st_specific;
1034  if (!trip)
1035  return;
1036 
1037  xxlen = MAGNITUDE(trip->tri_BA);
1038  yylen = MAGNITUDE(trip->tri_CA);
1039 
1040  VSUB2(P_A, hitp->hit_point, trip->tri_A);
1041  /* Flipping v is an artifact of how the faces are built */
1042  uvp->uv_u = VDOT(P_A, trip->tri_BA) * xxlen;
1043  uvp->uv_v = 1.0 - (VDOT(P_A, trip->tri_CA) * yylen);
1044  if (uvp->uv_u < 0 || uvp->uv_v < 0) {
1045  if (RT_G_DEBUG)
1046  bu_log("rt_ars_uv: bad uv=%g, %g\n", uvp->uv_u, uvp->uv_v);
1047  /* Fix it up */
1048  if (uvp->uv_u < 0) uvp->uv_u = (-uvp->uv_u);
1049  if (uvp->uv_v < 0) uvp->uv_v = (-uvp->uv_v);
1050  }
1051  r = ap->a_rbeam + ap->a_diverge * hitp->hit_dist;
1052  uvp->uv_du = r * xxlen;
1053  uvp->uv_dv = r * yylen;
1054 }
1055 
1056 
1057 int
1058 rt_ars_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
1059 {
1060  register size_t i;
1061  register size_t j;
1062  struct rt_ars_internal *arip;
1063 
1064  BU_CK_LIST_HEAD(vhead);
1065  RT_CK_DB_INTERNAL(ip);
1066  arip = (struct rt_ars_internal *)ip->idb_ptr;
1067  RT_ARS_CK_MAGIC(arip);
1068 
1069  /*
1070  * Draw the "waterlines", by tracing each curve. n+1th point is
1071  * first point replicated by code above.
1072  */
1073  for (i = 0; i < arip->ncurves; i++) {
1074  register fastf_t *v1;
1075 
1076  v1 = arip->curves[i];
1077  RT_ADD_VLIST(vhead, v1, BN_VLIST_LINE_MOVE);
1078  v1 += ELEMENTS_PER_VECT;
1079  for (j = 1; j <= arip->pts_per_curve; j++, v1 += ELEMENTS_PER_VECT)
1080  RT_ADD_VLIST(vhead, v1, BN_VLIST_LINE_DRAW);
1081  }
1082 
1083  /* Connect the Ith points on each curve, to make a mesh. */
1084  for (i = 0; i < arip->pts_per_curve; i++) {
1085  RT_ADD_VLIST(vhead, &arip->curves[0][i*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
1086  for (j = 1; j < arip->ncurves; j++)
1087  RT_ADD_VLIST(vhead, &arip->curves[j][i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
1088  }
1089 
1090  return 0;
1091 }
1092 
1093 
1094 int
1095 rt_ars_get(struct bu_vls *logstr, const struct rt_db_internal *intern, const char *attr)
1096 {
1097  register struct rt_ars_internal *ars = (struct rt_ars_internal *)intern->idb_ptr;
1098  size_t i, j;
1099 
1100  RT_ARS_CK_MAGIC(ars);
1101 
1102  if (attr == (char *)NULL) {
1103  bu_vls_strcpy(logstr, "ars");
1104  bu_vls_printf(logstr, " NC %zu PPC %zu", ars->ncurves, ars->pts_per_curve);
1105  for (i = 0; i < ars->ncurves; i++) {
1106  bu_vls_printf(logstr, " C%zu {", i);
1107  for (j = 0; j < ars->pts_per_curve; j++) {
1108  bu_vls_printf(logstr, " { %.25g %.25g %.25g }",
1109  V3ARGS(&ars->curves[i][j*3]));
1110  }
1111  bu_vls_printf(logstr, " }");
1112  }
1113  } else if (BU_STR_EQUAL(attr, "NC")) {
1114  bu_vls_printf(logstr, "%zu", ars->ncurves);
1115  } else if (BU_STR_EQUAL(attr, "PPC")) {
1116  bu_vls_printf(logstr, "%zu", ars->pts_per_curve);
1117  } else if (attr[0] == 'C') {
1118  const char *ptr;
1119 
1120  if (attr[1] == '\0') {
1121  /* all the curves */
1122  for (i = 0; i < ars->ncurves; i++) {
1123  bu_vls_printf(logstr, " C%zu {", i);
1124  for (j = 0; j < ars->pts_per_curve; j++) {
1125  bu_vls_printf(logstr, " { %.25g %.25g %.25g }",
1126  V3ARGS(&ars->curves[i][j*3]));
1127  }
1128  bu_vls_printf(logstr, " }");
1129  }
1130  } else if (!isdigit((int)attr[1])) {
1131  bu_vls_printf(logstr,
1132  "ERROR: illegal argument, must be NC, PPC, C, C#, or C#P#\n");
1133  return BRLCAD_ERROR;
1134  }
1135 
1136  ptr = strchr(attr, 'P');
1137  if (ptr) {
1138  /* a specific point on a specific curve */
1139  if (!isdigit((int)*(ptr+1))) {
1140  bu_vls_printf(logstr,
1141  "ERROR: illegal argument, must be NC, PPC, C, C#, or C#P#\n");
1142  return BRLCAD_ERROR;
1143  }
1144  j = atoi((ptr+1));
1145  /* FIXME: is this necessary? modifying a const char is illegal!
1146  *ptr = '\0';
1147  */
1148  i = atoi(&attr[1]);
1149  bu_vls_printf(logstr, "%.25g %.25g %.25g",
1150  V3ARGS(&ars->curves[i][j*3]));
1151  } else {
1152  /* the entire curve */
1153  i = atoi(&attr[1]);
1154  for (j = 0; j < ars->pts_per_curve; j++) {
1155  bu_vls_printf(logstr, " { %.25g %.25g %.25g }",
1156  V3ARGS(&ars->curves[i][j*3]));
1157  }
1158  }
1159  }
1160 
1161  return BRLCAD_OK;
1162 }
1163 
1164 
1165 int
1166 rt_ars_adjust(struct bu_vls *logstr, struct rt_db_internal *intern, int argc, const char **argv)
1167 {
1168  struct rt_ars_internal *ars;
1169  size_t i, j, k;
1170  int len;
1171  fastf_t *array;
1172 
1173  RT_CK_DB_INTERNAL(intern);
1174 
1175  ars = (struct rt_ars_internal *)intern->idb_ptr;
1176  RT_ARS_CK_MAGIC(ars);
1177 
1178  while (argc >= 2) {
1179  if (BU_STR_EQUAL(argv[0], "NC")) {
1180  /* change number of curves */
1181  i = atoi(argv[1]);
1182  if (i < ars->ncurves) {
1183  for (j=i; j<ars->ncurves; j++)
1184  bu_free((char *)ars->curves[j], "ars->curves[j]");
1185  ars->curves = (fastf_t **)bu_realloc(ars->curves,
1186  i*sizeof(fastf_t *), "ars->curves");
1187  ars->ncurves = i;
1188  } else if (i > ars->ncurves) {
1189  ars->curves = (fastf_t **)bu_realloc(ars->curves,
1190  i*sizeof(fastf_t *), "ars->curves");
1191  if (ars->pts_per_curve) {
1192  /* new curves are duplicates of the last */
1193  for (j=ars->ncurves; j<i; j++) {
1194  ars->curves[j] = (fastf_t *)bu_malloc(
1195  ars->pts_per_curve * 3 * sizeof(fastf_t),
1196  "ars->curves[j]");
1197  for (k = 0; k < ars->pts_per_curve; k++) {
1198  if (j) {
1199  VMOVE(&ars->curves[j][k*3],
1200  &ars->curves[j-1][k*3]);
1201  } else {
1202  VSETALL(&ars->curves[j][k*3], 0.0);
1203  }
1204  }
1205  }
1206  } else {
1207  for (j=ars->ncurves; j<i; j++) {
1208  ars->curves[j] = NULL;
1209  }
1210  }
1211  ars->ncurves = i;
1212  }
1213  } else if (BU_STR_EQUAL(argv[0], "PPC")) {
1214  /* change the number of points per curve */
1215  i = atoi(argv[1]);
1216  if (i < 3) {
1217  bu_vls_printf(logstr,
1218  "ERROR: must have at least 3 points per curve\n");
1219  return BRLCAD_ERROR;
1220  }
1221  if (i < ars->pts_per_curve) {
1222  for (j = 0; j < ars->ncurves; j++) {
1223  ars->curves[j] = (fastf_t *)bu_realloc(ars->curves[j],
1224  i * 3 * sizeof(fastf_t),
1225  "ars->curves[j]");
1226  }
1227  ars->pts_per_curve = i;
1228  } else if (i > ars->pts_per_curve) {
1229  for (j = 0; j < ars->ncurves; j++) {
1230  ars->curves[j] = (fastf_t *)bu_realloc(ars->curves[j],
1231  i * 3 * sizeof(fastf_t),
1232  "ars->curves[j]");
1233  /* new points are duplicates of last */
1234  for (k = ars->pts_per_curve; k < i; k++) {
1235  if (k) {
1236  VMOVE(&ars->curves[j][k*3],
1237  &ars->curves[j][(k-1)*3]);
1238  } else {
1239  VSETALL(&ars->curves[j][k*3], 0);
1240  }
1241  }
1242  }
1243  ars->pts_per_curve = i;
1244  }
1245  } else if (argv[0][0] == 'C') {
1246  if (isdigit((int)argv[0][1])) {
1247  const char *ptr;
1248 
1249  /* a specific curve */
1250  ptr = strchr(argv[0], 'P');
1251  if (ptr) {
1252  /* a specific point on this curve */
1253  i = atoi(&argv[0][1]);
1254  j = atoi(ptr+1);
1255  len = 3;
1256  array = &ars->curves[i][j*3];
1258  &array,
1259  &len)!= len) {
1260  bu_vls_printf(logstr,
1261  "WARNING: incorrect number of parameters provided for a point\n");
1262  }
1263  } else {
1264  char *dupstr;
1265  char *ptr2;
1266 
1267  /* one complete curve */
1268  i = atoi(&argv[0][1]);
1269  len = ars->pts_per_curve * 3;
1270  dupstr = bu_strdup(argv[1]);
1271  ptr2 = dupstr;
1272  while (*ptr2) {
1273  if (*ptr2 == '{' || *ptr2 == '}')
1274  *ptr2 = ' ';
1275  ptr2++;
1276  }
1277  if (!ars->curves[i]) {
1278  ars->curves[i] = (fastf_t *)bu_calloc(ars->pts_per_curve * 3, sizeof(fastf_t), "ars->curves[i]");
1279  }
1280  if (tcl_list_to_fastf_array(brlcad_interp, dupstr, &ars->curves[i], &len) != len) {
1281  bu_vls_printf(logstr, "WARNING: incorrect number of parameters provided for a curve\n");
1282  }
1283  bu_free(dupstr, "bu_strdup ars curve");
1284  }
1285  } else {
1286  bu_vls_printf(logstr, "ERROR: Illegal argument, must be NC, PPC, C#, or C#P#\n");
1287  return BRLCAD_ERROR;
1288  }
1289  } else {
1290  bu_vls_printf(logstr, "ERROR: Illegal argument, must be NC, PPC, C#, or C#P#\n");
1291  return BRLCAD_ERROR;
1292  }
1293  argc -= 2;
1294  argv += 2;
1295  }
1296 
1297  return BRLCAD_OK;
1298 }
1299 
1300 
1301 int
1302 rt_ars_params(struct pc_pc_set *UNUSED(ps), const struct rt_db_internal *ip)
1303 {
1304  RT_CK_DB_INTERNAL(ip);
1305 
1306  return 0; /* OK */
1307 }
1308 
1309 
1310 /** @} */
1311 /*
1312  * Local Variables:
1313  * mode: C
1314  * tab-width: 8
1315  * indent-tabs-mode: t
1316  * c-file-style: "stroustrup"
1317  * End:
1318  * ex: shiftwidth=4 tabstop=8
1319  */
void nmg_fix_normals(struct shell *s_orig, const struct bn_tol *tol)
Definition: nmg_misc.c:3505
int rt_ars_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: ars.c:229
char * d_namep
pointer to name string
Definition: raytrace.h:859
Definition: raytrace.h:800
#define ID_ARS
ARS.
Definition: raytrace.h:463
int rt_ars_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
Definition: ars.c:409
#define RT_LEN_TOL
Definition: raytrace.h:169
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_LIST_INSERT(old, new)
Definition: list.h:183
#define FIND_IJ(a, b)
Definition: ars.c:53
#define SIZEOF_NETWORK_DOUBLE
Definition: cv.h:48
struct hit seg_in
IN information.
Definition: raytrace.h:370
struct rt_bot_internal * nmg_bot(struct shell *s, const struct bn_tol *tol)
Definition: nmg_misc.c:10826
Definition: list.h:118
const struct directory * st_dp
Directory entry of solid.
Definition: raytrace.h:436
int rt_bot_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: bot.c:249
int nmg_kfu(struct faceuse *fu1)
Definition: nmg_mk.c:1207
#define RT_ARS_MAXHITS
int rt_ars_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: ars.c:361
int rt_ars_class(const struct soltab *stp, const vect_t min, const vect_t max, const struct bn_tol *tol)
Definition: ars.c:83
int rt_ars_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: ars.c:1058
double dist
>= 0
Definition: tol.h:73
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
struct soltab * seg_stp
pointer back to soltab
Definition: raytrace.h:372
if lu s
Definition: nmg_mod.c:3860
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
#define VSETALL(a, s)
Definition: color.c:54
Definition: raytrace.h:215
#define ID_BOT
Bag o' triangles.
Definition: raytrace.h:488
#define SIZEOF_NETWORK_LONG
Definition: cv.h:46
Definition: pc.h:108
Definition: raytrace.h:368
vect_t tri_CA
Definition: plane_struct.h:64
Definition: raytrace.h:248
HIDDEN fastf_t * ars_rd_curve(union record *rp, int npts, int flip)
Definition: ars.c:103
int rt_ars_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *tol)
Definition: ars.c:657
Header file for the BRL-CAD common definitions.
vect_t tri_wn
Definition: plane_struct.h:65
int rt_ars_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: ars.c:306
void flip_fastf_float(fastf_t *ff, const dbfloat_t *fp, int n, int flip)
Definition: db_flip.c:74
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
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)
#define IJ(ii, jj)
Definition: ars.c:51
#define HIDDEN
Definition: common.h:86
int nmg_calc_face_g(struct faceuse *fu)
Definition: nmg_misc.c:1786
struct bu_list l
Definition: raytrace.h:369
#define RT_DB_INTERNAL_MAGIC
Definition: magic.h:158
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
Definition: ptbl.h:62
#define ARS_PT(ii, jj)
Definition: ars.c:52
if(share_geom)
Definition: nmg_mod.c:3829
char * strchr(const char *sp, int c)
int idb_major_type
Definition: raytrace.h:192
Definition: color.c:49
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
#define RT_G_DEBUG
Definition: raytrace.h:1718
vect_t hit_vpriv
PRIVATE vector for xxx_*()
Definition: raytrace.h:253
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
void nmg_shell_coplanar_face_merge(struct shell *s, const struct bn_tol *tol, const int simplify)
Definition: nmg_mod.c:93
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
struct tri_specific * tri_forw
Definition: plane_struct.h:69
#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 crv_c2
curvature in other direction
Definition: raytrace.h:309
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
void rt_ars_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
Definition: ars.c:1008
int rt_ars_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: ars.c:699
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
fastf_t a_diverge
slope of beam divergence/mm
Definition: raytrace.h:1600
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
fastf_t uv_dv
delta in v
Definition: raytrace.h:344
#define V3ARGS(a)
Definition: color.c:56
#define BRLCAD_OK
Definition: defines.h:71
unsigned char * bp
Definition: rot.c:56
uint8_t * ext_buf
Definition: parse.h:216
void nmg_km(struct model *m)
Definition: nmg_mk.c:1634
point_t hit_point
DEPRECATED: Intersection point, use VJOIN1 hit_dist.
Definition: raytrace.h:251
struct hit seg_out
OUT information.
Definition: raytrace.h:371
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
struct bu_attribute_value_set idb_avs
Definition: raytrace.h:196
void * bu_realloc(void *ptr, size_t siz, const char *str)
#define UNUSED(parameter)
Definition: common.h:239
int nmg_mark_edges_real(const uint32_t *magic_p)
Definition: nmg_misc.c:846
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
uint32_t idb_magic
Definition: raytrace.h:191
struct nmgregion * nmg_mrsv(struct model *m)
Definition: nmg_mk.c:306
ustring alpha
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
struct bn_tol rti_tol
Math tolerances for this model.
Definition: raytrace.h:1765
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
#define RT_GET_SEG(p, res)
Definition: raytrace.h:379
vect_t tri_N
Definition: plane_struct.h:66
struct model * nmg_mm(void)
Definition: nmg_mk.c:235
int nmg_simplify_shell(struct shell *s)
Definition: nmg_mod.c:209
#define ASSOC_GEOM(corn, a, b)
Definition: ars.c:58
void * idb_ptr
Definition: raytrace.h:195
HIDDEN int code(fastf_t x, fastf_t y)
Definition: clip.c:43
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
void bu_cv_ntohd(unsigned char *out, const unsigned char *in, size_t count)
const struct rt_functab OBJ[]
Definition: table.c:159
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
int bn_3pts_collinear(point_t a, point_t b, point_t c, const struct bn_tol *tol)
Check to see if three points are collinear.
void bn_vec_ortho(vect_t out, const vect_t in)
int rt_ars_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
Definition: ars.c:781
short flip_short(short s)
Definition: db_flip.c:47
int rt_ars_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: ars.c:147
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
void * st_specific
-> ID-specific (private) struct
Definition: raytrace.h:435
void rt_ars_print(register const struct soltab *stp)
Definition: ars.c:752
void rt_ars_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
Definition: ars.c:1027
fastf_t uv_du
delta in u
Definition: raytrace.h:343
int bn_3pts_distinct(const point_t a, const point_t b, const point_t c, const struct bn_tol *tol)
int tcl_list_to_fastf_array(Tcl_Interp *interp, const char *char_list, fastf_t **array, int *array_len)
Definition: tcl.c:829
fastf_t crv_c1
curvature in principle dir
Definition: raytrace.h:308
int idb_minor_type
ID_xxx.
Definition: raytrace.h:193
int bn_dist_pt3_lseg3(fastf_t *dist, point_t pca, const point_t a, const point_t b, const point_t p, const struct bn_tol *tol)
Find the distance from a point P to a line segment described by the two endpoints A and B...
struct rt_tess_tol rti_ttol
Tessellation tolerance defaults.
Definition: raytrace.h:1766
Definition: color.c:51
int dbi_version
PRIVATE: use db_version()
Definition: raytrace.h:824
point_t tri_A
Definition: plane_struct.h:62
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
#define TRI_NULL
Definition: ars.c:49
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
fastf_t a_rbeam
initial beam radius (mm)
Definition: raytrace.h:1599
#define BU_CK_LIST_HEAD(_p)
Definition: list.h:142
int rt_ars_get(struct bu_vls *logstr, const struct rt_db_internal *intern, const char *attr)
Definition: ars.c:1095
#define BU_CK_EXTERNAL(_p)
Definition: parse.h:224
struct faceuse * nmg_cmface(struct shell *s, struct vertex ***verts, int n)
Definition: nmg_mod.c:979
void rt_ars_free(register struct soltab *stp)
Definition: ars.c:72
int rt_ars_adjust(struct bu_vls *logstr, struct rt_db_internal *intern, int argc, const char **argv)
Definition: ars.c:1166
#define RT_HIT_NORMAL(_normal, _hitp, _stp, _unused, _flipflag)
Definition: raytrace.h:273
size_t ext_nbytes
Definition: parse.h:210
void rt_ars_ifree(struct rt_db_internal *ip)
Definition: ars.c:457
void rt_bot_ifree(struct rt_db_internal *ip)
Definition: bot.c:1526
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
void rt_hitsort(register struct hit *h, register int nh)
Definition: ars.c:971
HIDDEN void verbose(struct human_data_t *dude)
Definition: human.c:2008
Definition: vls.h:56
#define BRLCAD_ERROR
Definition: defines.h:72
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
double fastf_t
Definition: defines.h:300
#define VPRINT(a, b)
Definition: raytrace.h:1881
void rt_ars_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
Definition: ars.c:992
Tcl_Interp * brlcad_interp
Definition: tcl.c:41
int rt_ars_params(struct pc_pc_set *ps, const struct rt_db_internal *ip)
Definition: ars.c:1302
Definition: color.c:50
#define RT_ARS_INTERNAL_MAGIC
Definition: magic.h:83
int rt_ars_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: ars.c:481
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
fastf_t uv_v
Range 0..1.
Definition: raytrace.h:342
#define bu_strdup(s)
Definition: str.h:71
vect_t tri_BA
Definition: plane_struct.h:63
#define RT_HIT_MAGIC
Definition: magic.h:161
#define DEBUG_ARB8
8 Print voluminous ARB8 details
Definition: raytrace.h:91
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
void nmg_region_a(struct nmgregion *r, const struct bn_tol *tol)
Definition: nmg_mk.c:2557