BRL-CAD
sketch.c
Go to the documentation of this file.
1 /* S K E T C H . 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/sketch/sketch.c
23  *
24  * Provide support for 2D sketches.
25  *
26  */
27 /** @} */
28 
29 #include "common.h"
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35 #include <ctype.h>
36 #include "bnetwork.h"
37 
38 #include "tcl.h"
39 #include "bu/debug.h"
40 #include "bu/cv.h"
41 #include "vmath.h"
42 #include "db.h"
43 #include "nmg.h"
44 #include "rtgeom.h"
45 #include "raytrace.h"
46 #include "nurb.h"
47 
48 #include "../../librt_private.h"
49 
50 
51 fastf_t rt_cnurb_par_edge(const struct edge_g_cnurb *crv, fastf_t epsilon);
52 extern void get_indices(void *seg, int *start, int *end); /* from g_extrude.c */
53 
54 
55 int
56 rt_check_curve(const struct rt_curve *crv, const struct rt_sketch_internal *skt, int noisy)
57 {
58  size_t i, j;
59  int ret=0;
60 
61  /* empty sketches are invalid */
62  if (crv->count == 0) {
63  if (noisy)
64  bu_log("sketch is empty\n");
65  return 1;
66  }
67 
68  for (i=0; i<crv->count; i++) {
69  const struct line_seg *lsg;
70  const struct carc_seg *csg;
71  const struct nurb_seg *nsg;
72  const struct bezier_seg *bsg;
73  const uint32_t *lng;
74 
75  lng = (uint32_t *)crv->segment[i];
76 
77  switch (*lng) {
78  case CURVE_LSEG_MAGIC:
79  lsg = (struct line_seg *)lng;
80  if ((size_t)lsg->start >= skt->vert_count ||
81  (size_t)lsg->end >= skt->vert_count)
82  ret++;
83  break;
84  case CURVE_CARC_MAGIC:
85  csg = (struct carc_seg *)lng;
86  if ((size_t)csg->start >= skt->vert_count ||
87  (size_t)csg->end >= skt->vert_count)
88  ret++;
89  break;
90  case CURVE_NURB_MAGIC:
91  nsg = (struct nurb_seg *)lng;
92  for (j=0; j<(size_t)nsg->c_size; j++) {
93  if ((size_t)nsg->ctl_points[j] >= skt->vert_count) {
94  ret++;
95  break;
96  }
97  }
98  break;
99  case CURVE_BEZIER_MAGIC:
100  bsg = (struct bezier_seg *)lng;
101  for (j=0; j<=(size_t)bsg->degree; j++) {
102  if ((size_t)bsg->ctl_points[j] >= skt->vert_count) {
103  ret++;
104  break;
105  }
106  }
107  break;
108  default:
109  ret++;
110  if (noisy)
111  bu_log("Unrecognized segment type in sketch\n");
112  break;
113  }
114  }
115 
116  if (ret && noisy)
117  bu_log("sketch references non-existent vertices!\n");
118  return ret;
119 }
120 
121 
122 /**
123  * Given a pointer to a GED database record, and a transformation
124  * matrix, determine if this is a valid SKETCH, and if so, precompute
125  * various terms of the formula.
126  *
127  * Returns -
128  * 0 SKETCH is OK
129  * !0 Error in description
130  *
131  * Implicit return -
132  * A struct sketch_specific is created, and its address is
133  * stored in stp->st_specific for use by sketch_shot().
134  */
135 int
136 rt_sketch_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
137 {
138  if (!stp)
139  return -1;
140  RT_CK_SOLTAB(stp);
141  if (ip) RT_CK_DB_INTERNAL(ip);
142  if (rtip) RT_CK_RTI(rtip);
143 
144  stp->st_specific = (void *)NULL;
145  return 0;
146 }
147 
148 
149 void
150 rt_sketch_print(const struct soltab *stp)
151 {
152  if (stp) RT_CK_SOLTAB(stp);
153 }
154 
155 
156 /**
157  * Intersect a ray with a sketch. If an intersection occurs, a struct
158  * seg will be acquired and filled in.
159  *
160  * Returns -
161  * 0 MISS
162  * >0 HIT
163  */
164 int
165 rt_sketch_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
166 {
167  if (!stp || !rp || !ap || !seghead)
168  return 0;
169 
170  RT_CK_SOLTAB(stp);
171  RT_CK_RAY(rp);
172  RT_CK_APPLICATION(ap);
173 
174  /* can't hit 'em as they're not solid geometry, so no surfno, not
175  * hit point, nada.
176  */
177 
178  return 0; /* MISS */
179 }
180 
181 
182 /**
183  * Given ONE ray distance, return the normal and entry/exit point.
184  */
185 void
186 rt_sketch_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
187 {
188  if (!hitp || !rp)
189  return;
190 
191  RT_CK_HIT(hitp);
192  if (stp) RT_CK_SOLTAB(stp);
193  RT_CK_RAY(rp);
194 
195  VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir);
196 }
197 
198 
199 /**
200  * Return the curvature of the sketch.
201  */
202 void
203 rt_sketch_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
204 {
205  if (!cvp || !hitp)
206  return;
207 
208  RT_CK_HIT(hitp);
209  if (stp) RT_CK_SOLTAB(stp);
210 
211  cvp->crv_c1 = cvp->crv_c2 = 0;
212 
213  /* any tangent direction */
214  bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal);
215 }
216 
217 
218 /**
219  * For a hit on the surface of an sketch, return the (u, v) coordinates
220  * of the hit point, 0 <= u, v <= 1.
221  *
222  * u = azimuth, v = elevation
223  */
224 void
225 rt_sketch_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
226 {
227  if (ap) RT_CK_APPLICATION(ap);
228  if (stp) RT_CK_SOLTAB(stp);
229  if (hitp) RT_CK_HIT(hitp);
230  if (!uvp)
231  return;
232 }
233 
234 
235 void
236 rt_sketch_free(struct soltab *stp)
237 {
238  if (stp) RT_CK_SOLTAB(stp);
239 }
240 
241 
242 /*
243  determine whether the 2D point 'pt' is within the bounds of the sketch
244  by counting the number of intersections between the curve and a line
245  starting at the given point pointing horizontally away from the y-axis.
246 
247  if the number of intersections is odd, the point is within the sketch,
248  and if it's even, the point is outside the sketch.
249 
250  return 1 if point 'pt' is within the sketch, 0 if not.
251 */
252 int
253 rt_sketch_contains(struct rt_sketch_internal *sk, point2d_t pt)
254 {
255  fastf_t nseg;
256  int i, hits;
257 
258  uint32_t *lng;
259  struct line_seg *lsg;
260  struct carc_seg *csg;
261 
262  point2d_t pt1, pt2, isec;
263  vect2d_t one, two;
264 
265  nseg = sk->curve.count;
266  hits = 0;
267  isec[Y] = pt[Y];
268 
269  for (i=0; i<nseg; i++) {
270  lng = (uint32_t *)sk->curve.segment[i];
271 
272  switch (*lng) {
273  case CURVE_LSEG_MAGIC:
274  lsg = (struct line_seg *)lng;
275  V2MOVE(pt1, sk->verts[lsg->start]);
276  V2MOVE(pt2, sk->verts[lsg->end]);
277  if (pt[Y] > FMAX(pt1[Y], pt2[Y]) || pt[Y] < FMIN(pt1[Y], pt2[Y])) {
278  continue;
279  }
280  isec[X] = pt1[X] + (isec[Y] - pt1[Y]) * ((pt1[X] - pt2[X]) / (pt1[Y] - pt2[Y]));
281  if ((pt[X] >= 0 && pt[X] < isec[X]) || (pt[X] < 0 && pt[X] > isec[X])) {
282  hits++;
283  }
284  break;
285  case CURVE_CARC_MAGIC:
286  csg = (struct carc_seg *)lng;
287  V2MOVE(pt1, sk->verts[csg->start]);
288  V2MOVE(pt2, sk->verts[csg->end]);
289  if (csg->radius <=0.0) {
290  vect2d_t r, dist;
291  V2SUB2(r, pt2, pt1);
292  V2SUB2(dist, r, pt);
293  if (MAG2SQ(dist) < MAG2SQ(r)) hits++;
294  } else {
295  vect2d_t r, dist, center;
296  V2SUB2(dist, pt2, pt1);
297  if (csg->center_is_left) {
298  r[X] = -dist[Y];
299  r[Y] = dist[X];
300  } else {
301  r[X] = dist[Y];
302  r[Y] = -dist[X];
303  }
304  V2SCALE(dist, dist, 0.5);
305  V2SCALE(r, r, sqrt((csg->radius*csg->radius - MAG2SQ(dist))/(MAG2SQ(r))));
306  V2ADD3(center, sk->verts[csg->start], dist, r);
307  V2SUB2(dist, center, pt);
308  if (MAG2SQ(dist) > (csg->radius*csg->radius)) {
309  /* outside the circle - if it passes between the endpoints, count it as a hit */
310  /* otherwise, it will hit either twice or not at all, and can be ignored */
311  if (pt[Y] > FMIN(pt1[Y], pt2[Y]) && pt[Y] <= FMAX(pt1[Y], pt2[Y])) {
312  if ((pt[X] >= 0 && pt[X] < FMIN(pt1[X], pt2[X]))
313  || (pt[X] < 0 && pt[X] > FMAX(pt1[X], pt2[X]))) hits++;
314  }
315  } else {
316  fastf_t angMin, angMax, angle;
317  V2SUB2(one, pt1, center);
318  V2SUB2(two, pt2, center);
319  if (csg->orientation == 0) {
320  /* ccw arc */
321  angMin = atan2(one[Y], one[X]);
322  angMax = atan2(two[Y], two[X]);
323  } else {
324  angMax = atan2(one[Y], one[X]);
325  angMin = atan2(two[Y], two[X]);
326  }
327  if (pt[X] >= 0) {
328  angle = atan2(dist[Y], sqrt(csg->radius*csg->radius - dist[Y]*dist[Y]));
329  } else {
330  angle = atan2(dist[Y], -sqrt(csg->radius*csg->radius - dist[Y]*dist[Y]));
331  }
332  angMax -= angMin;
333  angle -= angMin;
334  if (angMax < 0) angMax += M_2PI;
335  if (angle < 0) angle += M_2PI;
336  if (angle < angMax) hits++;
337  }
338  }
339  break;
340  case CURVE_BEZIER_MAGIC:
341  break;
342  case CURVE_NURB_MAGIC:
343  break;
344  default:
345  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
346  break;
347  }
348  }
349  return hits%2;
350 }
351 
352 
353 /* sets bounds to { XMIN, XMAX, YMIN, YMAX } */
354 void
355 rt_sketch_bounds(struct rt_sketch_internal *sk, fastf_t *bounds)
356 {
357  fastf_t nseg, radius;
358  int i, j;
359 
360  uint32_t *lng;
361  struct line_seg *lsg;
362  struct carc_seg *csg;
363  struct nurb_seg *nsg;
364  struct bezier_seg *bsg;
365 
366  nseg = sk->curve.count;
367  bounds[0] = bounds[2] = FLT_MAX;
368  bounds[1] = bounds[3] = -FLT_MAX;
369 
370  for (i=0; i<nseg; i++) {
371  lng = (uint32_t *)sk->curve.segment[i];
372 
373  switch (*lng) {
374  case CURVE_LSEG_MAGIC:
375  lsg = (struct line_seg *)lng;
376  V_MIN(bounds[0], FMIN(sk->verts[lsg->start][X], sk->verts[lsg->end][X]));
377  V_MAX(bounds[1], FMAX(sk->verts[lsg->start][X], sk->verts[lsg->end][X]));
378  V_MIN(bounds[2], FMIN(sk->verts[lsg->start][Y], sk->verts[lsg->end][Y]));
379  V_MAX(bounds[3], FMAX(sk->verts[lsg->start][Y], sk->verts[lsg->end][Y]));
380  break;
381  case CURVE_CARC_MAGIC:
382  csg = (struct carc_seg *)lng;
383  if (csg->radius <= 0.0) {
384  /* full circle, use center +- radius */
385  vect2d_t r;
386  V2SUB2(r, sk->verts[csg->end], sk->verts[csg->start]);
387  radius = sqrt(MAG2SQ(r));
388  V_MIN(bounds[0], sk->verts[csg->end][X] - radius);
389  V_MAX(bounds[1], sk->verts[csg->end][X] + radius);
390  V_MIN(bounds[2], sk->verts[csg->end][Y] - radius);
391  V_MAX(bounds[3], sk->verts[csg->end][Y] + radius);
392  } else {
393  /* TODO: actually calculate values from carc center */
394  V_MIN(bounds[0], FMIN(sk->verts[csg->start][X], sk->verts[csg->end][X]) - 2*csg->radius);
395  V_MAX(bounds[1], FMAX(sk->verts[csg->start][X], sk->verts[csg->end][X]) + 2*csg->radius);
396  V_MIN(bounds[2], FMIN(sk->verts[csg->start][Y], sk->verts[csg->end][Y]) - 2*csg->radius);
397  V_MAX(bounds[3], FMAX(sk->verts[csg->start][Y], sk->verts[csg->end][Y]) + 2*csg->radius);
398  }
399  break;
400  case CURVE_BEZIER_MAGIC:
401  bsg = (struct bezier_seg *)lng;
402  for (j=0; j<=bsg->degree; j++) {
403  V_MIN(bounds[0], sk->verts[bsg->ctl_points[j]][X]);
404  V_MAX(bounds[1], sk->verts[bsg->ctl_points[j]][X]);
405  V_MIN(bounds[2], sk->verts[bsg->ctl_points[j]][Y]);
406  V_MAX(bounds[3], sk->verts[bsg->ctl_points[j]][Y]);
407  }
408  break;
409  case CURVE_NURB_MAGIC:
410  nsg = (struct nurb_seg *)lng;
411  for (j=0; j < nsg->c_size; j++) {
412  V_MIN(bounds[0], sk->verts[nsg->ctl_points[j]][X]);
413  V_MAX(bounds[1], sk->verts[nsg->ctl_points[j]][X]);
414  V_MIN(bounds[2], sk->verts[nsg->ctl_points[j]][Y]);
415  V_MAX(bounds[3], sk->verts[nsg->ctl_points[j]][Y]);
416  }
417  break;
418  default:
419  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
420  break;
421  }
422  }
423 
424 }
425 
426 
427 int
428 rt_sketch_degree(struct rt_sketch_internal *sk)
429 {
430 
431  uint32_t *lng;
432  struct nurb_seg *nsg;
433  struct bezier_seg *bsg;
434  int nseg;
435  int degree;
436  int i;
437 
438  degree = 0;
439  nseg = sk->curve.count;
440 
441  for (i=0; i<nseg; i++) {
442  lng = (uint32_t *)sk->curve.segment[i];
443 
444  switch (*lng) {
445  case CURVE_LSEG_MAGIC:
446  if (degree < 1) degree = 1;
447  break;
448  case CURVE_CARC_MAGIC:
449  if (degree < 2) degree = 2;
450  break;
451  case CURVE_BEZIER_MAGIC:
452  bsg = (struct bezier_seg *)lng;
453  if (degree < bsg->degree) degree = bsg->degree;
454  break;
455  case CURVE_NURB_MAGIC:
456  nsg = (struct nurb_seg *)lng;
457  if (degree < nsg->order+1) degree = nsg->order+1;
458  break;
459  default:
460  bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
461  break;
462  }
463  }
464  return degree;
465 }
466 
467 
468 int
469 seg_to_vlist(struct bu_list *vhead, const struct rt_tess_tol *ttol, fastf_t *V, fastf_t *u_vec, fastf_t *v_vec, struct rt_sketch_internal *sketch_ip, void *seg)
470 {
471  int ret=0;
472  int i;
473  uint32_t *lng;
474  struct line_seg *lsg;
475  struct carc_seg *csg;
476  struct nurb_seg *nsg;
477  struct bezier_seg *bsg;
478  fastf_t delta;
479  point_t center, start_pt;
480  fastf_t pt[4];
481  vect_t semi_a, semi_b;
482  fastf_t radius;
483  vect_t norm;
484 
485  BU_CK_LIST_HEAD(vhead);
486 
487  VSETALL(semi_a, 0);
488  VSETALL(semi_b, 0);
489  VSETALL(center, 0);
490 
491  lng = (uint32_t *)seg;
492  switch (*lng) {
493  case CURVE_LSEG_MAGIC:
494  lsg = (struct line_seg *)lng;
495  if ((size_t)lsg->start >= sketch_ip->vert_count || (size_t)lsg->end >= sketch_ip->vert_count) {
496  ret++;
497  break;
498  }
499  VJOIN2(pt, V, sketch_ip->verts[lsg->start][0], u_vec, sketch_ip->verts[lsg->start][1], v_vec);
500  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE)
501  VJOIN2(pt, V, sketch_ip->verts[lsg->end][0], u_vec, sketch_ip->verts[lsg->end][1], v_vec);
502  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
503  break;
504  case CURVE_CARC_MAGIC:
505  {
506  point2d_t mid_pt, start2d, end2d, center2d, s2m, dir;
507  fastf_t s2m_len_sq, len_sq, tmp_len, cross_z;
508  fastf_t start_ang, end_ang, tot_ang, cosdel, sindel;
509  fastf_t oldu, oldv, newu, newv;
510  int nsegs;
511 
512  csg = (struct carc_seg *)lng;
513  if ((size_t)csg->start >= sketch_ip->vert_count || (size_t)csg->end >= sketch_ip->vert_count) {
514  ret++;
515  break;
516  }
517 
518  delta = M_PI_4;
519  if (csg->radius <= 0.0) {
520  VJOIN2(center, V, sketch_ip->verts[csg->end][0], u_vec, sketch_ip->verts[csg->end][1], v_vec);
521  VJOIN2(pt, V, sketch_ip->verts[csg->start][0], u_vec, sketch_ip->verts[csg->start][1], v_vec);
522  VSUB2(semi_a, pt, center);
523  VCROSS(norm, u_vec, v_vec);
524  VCROSS(semi_b, norm, semi_a);
525  VUNITIZE(semi_b);
526  radius = MAGNITUDE(semi_a);
527  VSCALE(semi_b, semi_b, radius);
528  } else if (csg->radius <= SMALL_FASTF) {
529  bu_log("Radius too small in sketch!\n");
530  break;
531  } else {
532  radius = csg->radius;
533  }
534 
535  if (ttol->abs > 0.0) {
536  fastf_t tmp_delta, ratio;
537 
538  ratio = ttol->abs / radius;
539  if (ratio < 1.0) {
540  tmp_delta = 2.0 * acos(1.0 - ratio);
541  if (tmp_delta < delta)
542  delta = tmp_delta;
543  }
544  }
545  if (ttol->rel > 0.0 && ttol->rel < 1.0) {
546  fastf_t tmp_delta;
547 
548  tmp_delta = 2.0 * acos(1.0 - ttol->rel);
549  if (tmp_delta < delta)
550  delta = tmp_delta;
551  }
552  if (ttol->norm > 0.0) {
553  fastf_t normal;
554 
555  normal = ttol->norm * DEG2RAD;
556  if (normal < delta)
557  delta = normal;
558  }
559  if (csg->radius <= 0.0) {
560  /* this is a full circle */
561  nsegs = ceil(M_2PI / delta);
562  delta = M_2PI / (double)nsegs;
563  cosdel = cos(delta);
564  sindel = sin(delta);
565  oldu = 1.0;
566  oldv = 0.0;
567  VJOIN2(start_pt, center, oldu, semi_a, oldv, semi_b);
568  RT_ADD_VLIST(vhead, start_pt, BN_VLIST_LINE_MOVE);
569  for (i=1; i<nsegs; i++) {
570  newu = oldu * cosdel - oldv * sindel;
571  newv = oldu * sindel + oldv * cosdel;
572  VJOIN2(pt, center, newu, semi_a, newv, semi_b);
573  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
574  oldu = newu;
575  oldv = newv;
576  }
577  RT_ADD_VLIST(vhead, start_pt, BN_VLIST_LINE_DRAW);
578  break;
579  }
580 
581  /* this is an arc (not a full circle) */
582  V2MOVE(start2d, sketch_ip->verts[csg->start]);
583  V2MOVE(end2d, sketch_ip->verts[csg->end]);
584  mid_pt[0] = (start2d[0] + end2d[0]) * 0.5;
585  mid_pt[1] = (start2d[1] + end2d[1]) * 0.5;
586  V2SUB2(s2m, mid_pt, start2d);
587  dir[0] = -s2m[1];
588  dir[1] = s2m[0];
589  s2m_len_sq = s2m[0]*s2m[0] + s2m[1]*s2m[1];
590  if (s2m_len_sq <= SMALL_FASTF) {
591  bu_log("start and end points are too close together in circular arc of sketch\n");
592  break;
593  }
594  len_sq = radius*radius - s2m_len_sq;
595  if (len_sq < 0.0) {
596  bu_log("Impossible radius for specified start and end points in circular arc\n");
597  break;
598  }
599  tmp_len = sqrt(dir[0]*dir[0] + dir[1]*dir[1]);
600  dir[0] = dir[0] / tmp_len;
601  dir[1] = dir[1] / tmp_len;
602  tmp_len = sqrt(len_sq);
603  V2JOIN1(center2d, mid_pt, tmp_len, dir);
604 
605  /* check center location */
606  cross_z = (end2d[X] - start2d[X])*(center2d[Y] - start2d[Y]) -
607  (end2d[Y] - start2d[Y])*(center2d[X] - start2d[X]);
608  if (!(cross_z > 0.0 && csg->center_is_left))
609  V2JOIN1(center2d, mid_pt, -tmp_len, dir);
610  start_ang = atan2(start2d[Y]-center2d[Y], start2d[X]-center2d[X]);
611  end_ang = atan2(end2d[Y]-center2d[Y], end2d[X]-center2d[X]);
612  if (csg->orientation) {
613  /* clock-wise */
614  while (end_ang > start_ang)
615  end_ang -= M_2PI;
616  } else {
617  /* counter-clock-wise */
618  while (end_ang < start_ang)
619  end_ang += M_2PI;
620  }
621  tot_ang = end_ang - start_ang;
622  nsegs = ceil(tot_ang / delta);
623  if (nsegs < 0)
624  nsegs = -nsegs;
625  if (nsegs < 3)
626  nsegs = 3;
627  delta = tot_ang / nsegs;
628  cosdel = cos(delta);
629  sindel = sin(delta);
630  VJOIN2(center, V, center2d[0], u_vec, center2d[1], v_vec);
631  VJOIN2(start_pt, V, start2d[0], u_vec, start2d[1], v_vec);
632  oldu = (start2d[0] - center2d[0]);
633  oldv = (start2d[1] - center2d[1]);
634  RT_ADD_VLIST(vhead, start_pt, BN_VLIST_LINE_MOVE);
635  for (i=0; i<nsegs; i++) {
636  newu = oldu * cosdel - oldv * sindel;
637  newv = oldu * sindel + oldv * cosdel;
638  VJOIN2(pt, center, newu, u_vec, newv, v_vec);
639  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
640  oldu = newu;
641  oldv = newv;
642  }
643  break;
644  }
645  case CURVE_NURB_MAGIC:
646  {
647  struct edge_g_cnurb eg;
648  int coords;
649  fastf_t inv_weight;
650  int num_intervals;
651  fastf_t param_delta, epsilon;
652 
653  nsg = (struct nurb_seg *)lng;
654  for (i=0; i<nsg->c_size; i++) {
655  if ((size_t)nsg->ctl_points[i] >= sketch_ip->vert_count) {
656  ret++;
657  break;
658  }
659  }
660  if (nsg->order < 3) {
661  /* just straight lines */
662  VJOIN2(start_pt, V, sketch_ip->verts[nsg->ctl_points[0]][0], u_vec, sketch_ip->verts[nsg->ctl_points[0]][1], v_vec);
663  if (RT_NURB_IS_PT_RATIONAL(nsg->pt_type)) {
664  inv_weight = 1.0/nsg->weights[0];
665  VSCALE(start_pt, start_pt, inv_weight);
666  }
667  RT_ADD_VLIST(vhead, start_pt, BN_VLIST_LINE_MOVE);
668  for (i=1; i<nsg->c_size; i++) {
669  VJOIN2(pt, V, sketch_ip->verts[nsg->ctl_points[i]][0], u_vec, sketch_ip->verts[nsg->ctl_points[i]][1], v_vec);
670  if (RT_NURB_IS_PT_RATIONAL(nsg->pt_type)) {
671  inv_weight = 1.0/nsg->weights[i];
672  VSCALE(pt, pt, inv_weight);
673  }
674  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
675  }
676  break;
677  }
678  eg.l.magic = NMG_EDGE_G_CNURB_MAGIC;
679  eg.order = nsg->order;
680  eg.k.k_size = nsg->k.k_size;
681  eg.k.knots = nsg->k.knots;
682  eg.c_size = nsg->c_size;
683  coords = 3 + RT_NURB_IS_PT_RATIONAL(nsg->pt_type);
684  eg.pt_type = RT_NURB_MAKE_PT_TYPE(coords, 2, RT_NURB_IS_PT_RATIONAL(nsg->pt_type));
685  eg.ctl_points = (fastf_t *)bu_malloc(nsg->c_size * coords * sizeof(fastf_t), "eg.ctl_points");
686  if (RT_NURB_IS_PT_RATIONAL(nsg->pt_type)) {
687  for (i=0; i<nsg->c_size; i++) {
688  VJOIN2(&eg.ctl_points[i*coords], V, sketch_ip->verts[nsg->ctl_points[i]][0], u_vec, sketch_ip->verts[nsg->ctl_points[i]][1], v_vec);
689  eg.ctl_points[(i+1)*coords - 1] = nsg->weights[i];
690  }
691  } else {
692  for (i=0; i<nsg->c_size; i++)
693  VJOIN2(&eg.ctl_points[i*coords], V, sketch_ip->verts[nsg->ctl_points[i]][0], u_vec, sketch_ip->verts[nsg->ctl_points[i]][1], v_vec);
694  }
695  epsilon = MAX_FASTF;
696  if (ttol->abs > 0.0 && ttol->abs < epsilon)
697  epsilon = ttol->abs;
698  if (ttol->rel > 0.0) {
699  point2d_t min_pt, max_pt, tmp_pt;
700  point2d_t diff;
701  fastf_t tmp_epsilon;
702 
703  min_pt[0] = MAX_FASTF;
704  min_pt[1] = MAX_FASTF;
705  max_pt[0] = -MAX_FASTF;
706  max_pt[1] = -MAX_FASTF;
707 
708  for (i=0; i<nsg->c_size; i++) {
709  V2MOVE(tmp_pt, sketch_ip->verts[nsg->ctl_points[i]]);
710  if (tmp_pt[0] > max_pt[0])
711  max_pt[0] = tmp_pt[0];
712  if (tmp_pt[1] > max_pt[1])
713  max_pt[1] = tmp_pt[1];
714  if (tmp_pt[0] < min_pt[0])
715  min_pt[0] = tmp_pt[0];
716  if (tmp_pt[1] < min_pt[1])
717  min_pt[1] = tmp_pt[1];
718  }
719 
720  V2SUB2(diff, max_pt, min_pt);
721  tmp_epsilon = ttol->rel * sqrt(MAG2SQ(diff));
722  if (tmp_epsilon < epsilon)
723  epsilon = tmp_epsilon;
724 
725  }
726  param_delta = rt_cnurb_par_edge(&eg, epsilon);
727  num_intervals = ceil((nsg->k.knots[nsg->k.k_size-1] - nsg->k.knots[0])/param_delta);
728  if (num_intervals < 3)
729  num_intervals = 3;
730  if (num_intervals > 500) {
731  bu_log("num_intervals was %d, clamped to 500\n", num_intervals);
732  num_intervals = 500;
733  }
734  param_delta = (nsg->k.knots[nsg->k.k_size-1] - nsg->k.knots[0])/(double)num_intervals;
735  for (i=0; i<=num_intervals; i++) {
736  fastf_t t;
737  int j;
738 
739  t = nsg->k.knots[0] + i*param_delta;
740  rt_nurb_c_eval(&eg, t, pt);
741  if (RT_NURB_IS_PT_RATIONAL(nsg->pt_type)) {
742  for (j=0; j<coords-1; j++)
743  pt[j] /= pt[coords-1];
744  }
745  if (i == 0)
746  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE)
747  else
748  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
749  }
750  bu_free((char *)eg.ctl_points, "eg.ctl_points");
751  break;
752  }
753  case CURVE_BEZIER_MAGIC: {
754  struct bezier_2d_list *bezier_hd, *bz;
755  fastf_t epsilon;
756 
757  bsg = (struct bezier_seg *)lng;
758 
759  for (i=0; i<=bsg->degree; i++) {
760  if ((size_t)bsg->ctl_points[i] >= sketch_ip->vert_count) {
761  ret++;
762  break;
763  }
764  }
765 
766  if (bsg->degree < 1) {
767  bu_log("g_sketch: ERROR: Bezier curve with illegal degree (%d)\n",
768  bsg->degree);
769  ret++;
770  break;
771  }
772 
773  if (bsg->degree == 1) {
774  /* straight line */
775  VJOIN2(start_pt, V, sketch_ip->verts[bsg->ctl_points[0]][0],
776  u_vec, sketch_ip->verts[bsg->ctl_points[0]][1], v_vec);
777  RT_ADD_VLIST(vhead, start_pt, BN_VLIST_LINE_MOVE);
778  for (i=1; i<=bsg->degree; i++) {
779  VJOIN2(pt, V, sketch_ip->verts[bsg->ctl_points[i]][0],
780  u_vec, sketch_ip->verts[bsg->ctl_points[i]][1], v_vec);
781  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
782  }
783  break;
784  }
785 
786  /* use tolerance to determine coarseness of plot */
787  epsilon = MAX_FASTF;
788  if (ttol->abs > 0.0 && ttol->abs < epsilon)
789  epsilon = ttol->abs;
790  if (ttol->rel > 0.0) {
791  point2d_t min_pt, max_pt, tmp_pt;
792  point2d_t diff;
793  fastf_t tmp_epsilon;
794 
795  min_pt[0] = MAX_FASTF;
796  min_pt[1] = MAX_FASTF;
797  max_pt[0] = -MAX_FASTF;
798  max_pt[1] = -MAX_FASTF;
799 
800  for (i=0; i<=bsg->degree; i++) {
801  V2MOVE(tmp_pt, sketch_ip->verts[bsg->ctl_points[i]]);
802  if (tmp_pt[0] > max_pt[0])
803  max_pt[0] = tmp_pt[0];
804  if (tmp_pt[1] > max_pt[1])
805  max_pt[1] = tmp_pt[1];
806  if (tmp_pt[0] < min_pt[0])
807  min_pt[0] = tmp_pt[0];
808  if (tmp_pt[1] < min_pt[1])
809  min_pt[1] = tmp_pt[1];
810  }
811 
812  V2SUB2(diff, max_pt, min_pt);
813  tmp_epsilon = ttol->rel * sqrt(MAG2SQ(diff));
814  if (tmp_epsilon < epsilon)
815  epsilon = tmp_epsilon;
816 
817  }
818 
819 
820  /* Create an initial bezier_2d_list */
821  BU_ALLOC(bezier_hd, struct bezier_2d_list);
822 
823  BU_LIST_INIT(&bezier_hd->l);
824  bezier_hd->ctl = (point2d_t *)bu_calloc(bsg->degree + 1, sizeof(point2d_t),
825  "g_sketch.c: bezier_hd->ctl");
826  for (i=0; i<=bsg->degree; i++) {
827  V2MOVE(bezier_hd->ctl[i], sketch_ip->verts[bsg->ctl_points[i]]);
828  }
829 
830  /* now do subdivision as necessary */
831  bezier_hd = bezier_subdivide(bezier_hd, bsg->degree, epsilon, 0);
832 
833  /* plot the results */
834  bz = BU_LIST_FIRST(bezier_2d_list, &bezier_hd->l);
835  VJOIN2(pt, V, bz->ctl[0][0], u_vec, bz->ctl[0][1], v_vec);
836  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE);
837 
838  while (BU_LIST_WHILE(bz, bezier_2d_list, &(bezier_hd->l))) {
839  BU_LIST_DEQUEUE(&bz->l);
840  for (i=1; i<=bsg->degree; i++) {
841  VJOIN2(pt, V, bz->ctl[i][0], u_vec,
842  bz->ctl[i][1], v_vec);
843  RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
844  }
845  bu_free((char *)bz->ctl, "g_sketch.c: bz->ctl");
846  bu_free((char *)bz, "g_sketch.c: bz");
847  }
848  bu_free((char *)bezier_hd, "g_sketch.c: bezier_hd");
849  break;
850  }
851  default:
852  bu_log("seg_to_vlist: ERROR: unrecognized segment type!\n");
853  break;
854  }
855 
856  return ret;
857 }
858 
859 
860 int
861 curve_to_vlist(struct bu_list *vhead, const struct rt_tess_tol *ttol, fastf_t *V, fastf_t *u_vec, fastf_t *v_vec, struct rt_sketch_internal *sketch_ip, struct rt_curve *crv)
862 {
863  size_t seg_no;
864  int ret=0;
865 
866  BU_CK_LIST_HEAD(vhead);
867 
869  bu_log("Barrier check at start of curve_to_vlist():\n");
871  }
872 
873  for (seg_no=0; seg_no < crv->count; seg_no++) {
874  ret += seg_to_vlist(vhead, ttol, V, u_vec, v_vec, sketch_ip, crv->segment[seg_no]);
875  }
876 
877  if (bu_debug&BU_DEBUG_MEM_CHECK) {
878  bu_log("Barrier check at end of curve_to_vlist():\n");
880  }
881 
882  return ret;
883 }
884 
885 
886 int
887 rt_sketch_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))
888 {
889  struct rt_sketch_internal *sketch_ip;
890  int ret;
891  int myret=0;
892 
893  BU_CK_LIST_HEAD(vhead);
894  RT_CK_DB_INTERNAL(ip);
895  sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
896  RT_SKETCH_CK_MAGIC(sketch_ip);
897 
898  ret=curve_to_vlist(vhead, ttol, sketch_ip->V, sketch_ip->u_vec, sketch_ip->v_vec, sketch_ip, &sketch_ip->curve);
899  if (ret) {
900  myret--;
901  bu_log("WARNING: Errors in sketch (%d segments reference non-existent vertices)\n",
902  ret);
903  }
904 
905  return myret;
906 }
907 
908 /**
909  * Given a sketch, bounds, and precision for rt_sketch_centroid, check
910  * if the precision is large enough (if the sample size is small
911  * enough) to intersect every curve of the given sketch.
912  *
913  * Returns -
914  * 0 precision is sufficiently large
915  * !0 precision is too small
916  */
917 static int
918 sketch_centroid_check_precision(const struct rt_sketch_internal *skt,
919  fastf_t precision,
920  fastf_t bounds[4])
921 {
922  fastf_t x_inc, y_inc, min_inc;
923  fastf_t min_size = INFINITY;
924  unsigned int i;
925  const struct rt_curve *crv = &skt->curve;
926  x_inc = (bounds[1]-bounds[0])/precision;
927  y_inc = (bounds[3]-bounds[2])/precision;
928  min_inc = x_inc < y_inc ? x_inc : y_inc;
929  for (i = 0; i < crv->count; i++) {
930  point2d_t size;
931  const struct line_seg *lsg;
932  const struct carc_seg *csg;
933  const struct nurb_seg *nsg;
934  const struct bezier_seg *bsg;
935  const uint32_t *lng;
936  int j;
937  point2d_t min_pt, max_pt;
938 
939  V2SETALL(min_pt, INFINITY);
940  V2SETALL(max_pt, -INFINITY);
941 
942  lng = (uint32_t *)crv->segment[i];
943 
944  switch (*lng) {
945  case CURVE_LSEG_MAGIC:
946  lsg = (struct line_seg *)lng;
947  V2SUB2(size, skt->verts[lsg->end], skt->verts[lsg->start]);
948  V_MIN(min_size, MAGNITUDE2(size));
949  break;
950  case CURVE_CARC_MAGIC:
951  csg = (struct carc_seg *)lng;
952  V2SUB2(size, skt->verts[csg->end], skt->verts[csg->start]);
953  V_MIN(min_size, MAGNITUDE2(size));
954  break;
955  case CURVE_NURB_MAGIC:
956  nsg = (struct nurb_seg *)lng;
957  for (j = 0; j < nsg->c_size; j++) {
958  V2MINMAX(min_pt, max_pt, skt->verts[nsg->ctl_points[j]]);
959  }
960  V2SUB2(size, max_pt, min_pt);
961  V_MIN(min_size, MAGNITUDE2(size));
962  break;
963  case CURVE_BEZIER_MAGIC:
964  bsg = (struct bezier_seg *)lng;
965  for (j = 0; j <= bsg->degree; j++) {
966  V2MINMAX(min_pt, max_pt, skt->verts[bsg->ctl_points[j]]);
967  }
968  V2SUB2(size, max_pt, min_pt);
969  V_MIN(min_size, MAGNITUDE2(size));
970  break;
971  }
972  }
973  return (min_size < min_inc);
974 }
975 
976 static long
977 sketch_update_centroid_with_coords(point_t *cent,
978  struct rt_sketch_internal *skt,
979  long n,
980  fastf_t i,
981  fastf_t j)
982 {
983  point2d_t pt;
984  point_t pt3d;
985  V2SET(pt, i, j);
986  VSET(pt3d, i, j, 0);
987  if (rt_sketch_contains(skt, pt)) {
988  VADD2(*cent, *cent, pt3d);
989  n++;
990  }
991  return n;
992 }
993 
994 
995 static long
996 sketch_centroid_with_precision(point_t *cent,
997  struct rt_sketch_internal *skt,
998  fastf_t precision,
999  long n,
1000  fastf_t bounds[4])
1001 {
1002  fastf_t x_inc, y_inc;
1003  fastf_t x_skip, y_skip;
1004  fastf_t i, j;
1005 
1006  x_inc = (bounds[1] - bounds[0])/precision;
1007  y_inc = (bounds[3] - bounds[2])/precision;
1008 
1009  x_skip = 2 * x_inc;
1010  y_skip = 2 * y_inc;
1011 
1012  if (n > 0) {
1013  VSCALE(*cent, *cent, n);
1014  for (i = bounds[0] + x_inc; i < bounds[1]; i += x_skip) {
1015  for (j = bounds[2]; j < bounds[3]; j += y_inc) {
1016  n = sketch_update_centroid_with_coords(cent, skt, n, i, j);
1017  }
1018  }
1019  for (i = bounds[0]; i < bounds[1]; i += x_skip) {
1020  for (j = bounds[2] + y_inc; j < bounds[3]; j += y_skip) {
1021  n = sketch_update_centroid_with_coords(cent, skt, n, i, j);
1022  }
1023  }
1024  } else {
1025  for (i = bounds[0]; i < bounds[1]; i += x_inc) {
1026  for (j = bounds[2]; j < bounds[3]; j += y_inc) {
1027  n = sketch_update_centroid_with_coords(cent, skt, n, i, j);
1028  }
1029  }
1030  }
1031  VSCALE(*cent, *cent, 1.0 / (fastf_t)n);
1032  return n;
1033 }
1034 
1035 void
1036 rt_sketch_centroid(point_t *cent, const struct rt_db_internal *ip)
1037 {
1038  /* With BN_TOL_DIST instead, even relatively simple sketches can
1039  * bounce back and forth between points < 0.005 apart but > 0.0005
1040  * for a long time. Since calculating is very computationally
1041  * intensive, using this TOLERANCE instead makes the computation
1042  * finish significantly faster without a huge loss of accuracy
1043  */
1044  const fastf_t TOLERANCE = 0.005;
1045  /* This is the initial precision that will be used as the
1046  * precision for the first iteration, assuming that the sketch
1047  * does not have any features that are small enough to escape
1048  * detection with this precision. 1024 was chosen because
1049  * smaller values tend to be very inaccurate, and oscillate enough
1050  * that convergence is not achieved; 1024 is a good balance
1051  * between (for the majority of sketches) being too large (and
1052  * missing a smaller convergence) and being too small (and doing
1053  * extra iterations for no reason).
1054  */
1055  fastf_t precision = 1024;
1056  fastf_t bounds[4];
1057  struct rt_sketch_internal *sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
1058  point_t current_cents[2];
1059  point_t difference = {INFINITY, INFINITY, INFINITY};
1060  long n[2] = {0, 0};
1061  int i = 1;
1062  RT_SKETCH_CK_MAGIC(sketch_ip);
1063 
1064  VSETALL(*cent, 0.0);
1065  VSETALL(current_cents[0], 0.0);
1066  VSETALL(current_cents[1], 0.0);
1067 
1068  rt_sketch_bounds(sketch_ip, bounds);
1069  while (sketch_centroid_check_precision(sketch_ip, precision, bounds)) {
1070  precision *= 2;
1071  }
1072 
1073  while (!NEAR_ZERO(MAGNITUDE(difference), TOLERANCE)) {
1074  n[i] = sketch_centroid_with_precision(&current_cents[i], sketch_ip, precision, n[i], bounds);
1075  precision *= M_SQRT2;
1076  VSUB2(difference, current_cents[i], current_cents[!i]);
1077  i = !i;
1078  }
1079 
1080  VMOVE(*cent, current_cents[!i]);
1081 }
1082 
1083 
1084 /**
1085  * Returns -
1086  * -1 failure
1087  * 0 OK. *r points to nmgregion that holds this tessellation.
1088  */
1089 int
1090 rt_sketch_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))
1091 {
1092  if (ip) RT_CK_DB_INTERNAL(ip);
1093 
1094  return -1;
1095 }
1096 
1097 
1098 /**
1099  * Import an SKETCH from the database format to the internal format.
1100  * Apply modeling transformations as well.
1101  */
1102 int
1103 rt_sketch_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
1104 {
1105  struct rt_sketch_internal *sketch_ip;
1106  union record *rp;
1107  size_t seg_no;
1108  unsigned char *ptr;
1109  struct rt_curve *crv;
1110  size_t i;
1111 
1112  /* must be double for import and export */
1113  double v[ELEMENTS_PER_VECT];
1114  double *vp;
1115 
1116  if (dbip) RT_CK_DBI(dbip);
1117 
1118  BU_CK_EXTERNAL(ep);
1119  rp = (union record *)ep->ext_buf;
1120  /* Check record type */
1121  if (rp->u_id != DBID_SKETCH) {
1122  bu_log("rt_sketch_import4: defective record\n");
1123  return -1;
1124  }
1125 
1127  bu_log("Barrier check at start of sketch_import4():\n");
1129  }
1130 
1131  RT_CK_DB_INTERNAL(ip);
1132  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
1133  ip->idb_type = ID_SKETCH;
1134  ip->idb_meth = &OBJ[ID_SKETCH];
1135  BU_ALLOC(ip->idb_ptr, struct rt_sketch_internal);
1136 
1137  sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
1138  sketch_ip->magic = RT_SKETCH_INTERNAL_MAGIC;
1139 
1140  if (mat == NULL) mat = bn_mat_identity;
1141  bu_cv_ntohd((unsigned char *)v, rp->skt.skt_V, ELEMENTS_PER_VECT);
1142  MAT4X3PNT(sketch_ip->V, mat, v);
1143  bu_cv_ntohd((unsigned char *)v, rp->skt.skt_uvec, ELEMENTS_PER_VECT);
1144  MAT4X3VEC(sketch_ip->u_vec, mat, v);
1145  bu_cv_ntohd((unsigned char *)v, rp->skt.skt_vvec, ELEMENTS_PER_VECT);
1146  MAT4X3VEC(sketch_ip->v_vec, mat, v);
1147  sketch_ip->vert_count = ntohl(*(uint32_t *)rp->skt.skt_vert_count);
1148  sketch_ip->curve.count = ntohl(*(uint32_t *)rp->skt.skt_count);
1149 
1150  ptr = (unsigned char *)rp;
1151  ptr += sizeof(struct sketch_rec);
1152  if (sketch_ip->vert_count) {
1153  sketch_ip->verts = (point2d_t *)bu_calloc(sketch_ip->vert_count, sizeof(point2d_t), "sketch_ip->vert");
1154  vp = (double *)bu_calloc(sketch_ip->vert_count, sizeof(double)*ELEMENTS_PER_VECT2D, "vp");
1155  bu_cv_ntohd((unsigned char *)vp, ptr, sketch_ip->vert_count*ELEMENTS_PER_VECT2D);
1156 
1157  /* convert double to fastf_t */
1158  for (i=0; i<sketch_ip->vert_count; i++) {
1159  sketch_ip->verts[i][X] = vp[(i*ELEMENTS_PER_VECT2D)+0];
1160  sketch_ip->verts[i][Y] = vp[(i*ELEMENTS_PER_VECT2D)+1];
1161  }
1162 
1163  bu_free(vp, "vp");
1164  ptr += 16 * sketch_ip->vert_count;
1165  }
1166 
1167  if (sketch_ip->curve.count)
1168  sketch_ip->curve.segment = (void **)bu_calloc(sketch_ip->curve.count, sizeof(void *), "segs");
1169  else
1170  sketch_ip->curve.segment = (void **)NULL;
1171  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1172  uint32_t magic;
1173  struct line_seg *lsg;
1174  struct carc_seg *csg;
1175  struct nurb_seg *nsg;
1176  struct bezier_seg *bsg;
1177 
1178  /* must be double for import and export */
1179  double scan;
1180  double *scanp;
1181 
1182  magic = ntohl(*(uint32_t *)ptr);
1183  ptr += SIZEOF_NETWORK_LONG;
1184  switch (magic) {
1185  case CURVE_LSEG_MAGIC:
1186  BU_ALLOC(lsg, struct line_seg);
1187  lsg->magic = magic;
1188  lsg->start = ntohl(*(uint32_t *)ptr);
1189  ptr += SIZEOF_NETWORK_LONG;
1190  lsg->end = ntohl(*(uint32_t *)ptr);
1191  ptr += SIZEOF_NETWORK_LONG;
1192  sketch_ip->curve.segment[seg_no] = (void *)lsg;
1193  break;
1194  case CURVE_CARC_MAGIC:
1195  BU_ALLOC(csg, struct carc_seg);
1196  csg->magic = magic;
1197  csg->start = ntohl(*(uint32_t *)ptr);
1198  ptr += SIZEOF_NETWORK_LONG;
1199  csg->end = ntohl(*(uint32_t *)ptr);
1200  ptr += SIZEOF_NETWORK_LONG;
1201  csg->orientation = ntohl(*(uint32_t *)ptr);
1202  ptr += SIZEOF_NETWORK_LONG;
1203  csg->center_is_left = ntohl(*(uint32_t *)ptr);
1204  ptr += SIZEOF_NETWORK_LONG;
1205  bu_cv_ntohd((unsigned char *)&scan, ptr, 1);
1206  csg->radius = scan; /* convert double to fastf_t */
1207  ptr += SIZEOF_NETWORK_DOUBLE;
1208  sketch_ip->curve.segment[seg_no] = (void *)csg;
1209  break;
1210  case CURVE_NURB_MAGIC:
1211  BU_ALLOC(nsg, struct nurb_seg);
1212  nsg->magic = magic;
1213  nsg->order = ntohl(*(uint32_t *)ptr);
1214  ptr += SIZEOF_NETWORK_LONG;
1215  nsg->pt_type = ntohl(*(uint32_t *)ptr);
1216  ptr += SIZEOF_NETWORK_LONG;
1217  nsg->k.k_size = ntohl(*(uint32_t *)ptr);
1218  ptr += SIZEOF_NETWORK_LONG;
1219 
1220  nsg->k.knots = (fastf_t *)bu_malloc(nsg->k.k_size * sizeof(fastf_t), "nsg->k.knots");
1221  scanp = (double *)bu_malloc(nsg->k.k_size * sizeof(double), "scanp");
1222  bu_cv_ntohd((unsigned char *)scanp, ptr, nsg->k.k_size);
1223 
1224  /* convert double to fastf_t */
1225  for (i=0; i<(size_t)nsg->k.k_size; i++) {
1226  nsg->k.knots[i] = scanp[i];
1227  }
1228  bu_free(scanp, "scanp");
1229 
1230  ptr += SIZEOF_NETWORK_DOUBLE * nsg->k.k_size;
1231  nsg->c_size = ntohl(*(uint32_t *)ptr);
1232  ptr += SIZEOF_NETWORK_LONG;
1233  nsg->ctl_points = (int *)bu_malloc(nsg->c_size * sizeof(int), "nsg->ctl_points");
1234  for (i=0; i<(size_t)nsg->c_size; i++) {
1235  nsg->ctl_points[i] = ntohl(*(uint32_t *)ptr);
1236  ptr += SIZEOF_NETWORK_LONG;
1237  }
1238  if (RT_NURB_IS_PT_RATIONAL(nsg->pt_type)) {
1239  nsg->weights = (fastf_t *)bu_malloc(nsg->c_size * sizeof(fastf_t), "nsg->weights");
1240  scanp = (double *)bu_malloc(nsg->c_size * sizeof(double), "scanp");
1241  bu_cv_ntohd((unsigned char *)scanp, ptr, nsg->c_size);
1242 
1243  /* convert double to fastf_t */
1244  for (i=0; i<(size_t)nsg->k.k_size; i++) {
1245  nsg->weights[i] = scanp[i];
1246  }
1247  bu_free(scanp, "scanp");
1248 
1249  ptr += SIZEOF_NETWORK_DOUBLE * nsg->c_size;
1250  } else {
1251  nsg->weights = (fastf_t *)NULL;
1252  }
1253  sketch_ip->curve.segment[seg_no] = (void *)nsg;
1254  break;
1255  case CURVE_BEZIER_MAGIC:
1256  BU_ALLOC(bsg, struct bezier_seg);
1257  bsg->magic = magic;
1258  bsg->degree = ntohl(*(uint32_t *)ptr);
1259  ptr += SIZEOF_NETWORK_LONG;
1260  bsg->ctl_points = (int *)bu_calloc(bsg->degree + 1, sizeof(int), "bsg->ctl_points");
1261  for (i=0; i<=(size_t)bsg->degree; i++) {
1262  bsg->ctl_points[i] = ntohl(*(uint32_t *)ptr);
1263  ptr += SIZEOF_NETWORK_LONG;
1264  }
1265  sketch_ip->curve.segment[seg_no] = (void *)bsg;
1266  break;
1267  default:
1268  bu_bomb("rt_sketch_import4: ERROR: unrecognized segment type!\n");
1269  break;
1270  }
1271  }
1272 
1273  crv = &sketch_ip->curve;
1274 
1275  if (crv->count)
1276  crv->reverse = (int *)bu_calloc(crv->count, sizeof(int), "crv->reverse");
1277  for (i=0; i<crv->count; i++) {
1278  crv->reverse[i] = ntohl(*(uint32_t *)ptr);
1279  ptr += SIZEOF_NETWORK_LONG;
1280  }
1281 
1282  if (bu_debug&BU_DEBUG_MEM_CHECK) {
1283  bu_log("Barrier check at end of sketch_import4():\n");
1285  }
1286 
1287  return 0; /* OK */
1288 }
1289 
1290 
1291 /**
1292  * The name is added by the caller, in the usual place.
1293  */
1294 int
1295 rt_sketch_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
1296 {
1297  struct rt_sketch_internal *sketch_ip;
1298  union record *rec;
1299  size_t i, seg_no, nbytes=0, ngran;
1300  unsigned char *ptr;
1301 
1302  /* must be double for import and export */
1303  double tmp_vec[ELEMENTS_PER_VECT];
1304 
1305  if (dbip) RT_CK_DBI(dbip);
1306 
1307  RT_CK_DB_INTERNAL(ip);
1308  if (ip->idb_type != ID_SKETCH) return -1;
1309  sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
1310  RT_SKETCH_CK_MAGIC(sketch_ip);
1311 
1313  bu_log("Barrier check at start of sketch_export4():\n");
1315  }
1316 
1317  BU_CK_EXTERNAL(ep);
1318 
1319  nbytes = sizeof(union record); /* base record */
1320  nbytes += sketch_ip->vert_count*(8*2); /* vertex list */
1321 
1322  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1323  uint32_t *lng;
1324  struct nurb_seg *nseg;
1325  struct bezier_seg *bseg;
1326 
1327  lng = (uint32_t *)sketch_ip->curve.segment[seg_no];
1328  switch (*lng) {
1329  case CURVE_LSEG_MAGIC:
1330  nbytes += 12;
1331  break;
1332  case CURVE_CARC_MAGIC:
1333  nbytes += 28;
1334  break;
1335  case CURVE_NURB_MAGIC:
1336  nseg = (struct nurb_seg *)lng;
1337  nbytes += 16 + sizeof(struct knot_vector) + nseg->k.k_size * 8 + nseg->c_size * 4;
1338  if (RT_NURB_IS_PT_RATIONAL(nseg->pt_type))
1339  nbytes += nseg->c_size * 8; /* weights */
1340  break;
1341  case CURVE_BEZIER_MAGIC:
1342  bseg = (struct bezier_seg *)lng;
1343  nbytes += 8 + (bseg->degree + 1) * 4;
1344  break;
1345  default:
1346  bu_log("rt_sketch_export4: unsupported segment type (x%x)\n", *lng);
1347  bu_bomb("rt_sketch_export4: unsupported segment type\n");
1348  }
1349  }
1350 
1351  ngran = ceil((double)(nbytes + sizeof(union record)) / sizeof(union record));
1352  ep->ext_nbytes = ngran * sizeof(union record);
1353  ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "sketch external");
1354 
1355  rec = (union record *)ep->ext_buf;
1356 
1357  rec->skt.skt_id = DBID_SKETCH;
1358 
1359  /* convert from local editing units to mm and export
1360  * to database record format
1361  */
1362  VSCALE(tmp_vec, sketch_ip->V, local2mm);
1363  bu_cv_htond(rec->skt.skt_V, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT);
1364 
1365  /* uvec and uvec are unit vectors, do not convert to/from mm */
1366  VMOVE(tmp_vec, sketch_ip->u_vec); /* convert fastf_t to double */
1367  bu_cv_htond(rec->skt.skt_uvec, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT);
1368  VMOVE(tmp_vec, sketch_ip->v_vec); /* convert fastf_t to double */
1369  bu_cv_htond(rec->skt.skt_vvec, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT);
1370 
1371  *(uint32_t *)rec->skt.skt_vert_count = htonl(sketch_ip->vert_count);
1372  *(uint32_t *)rec->skt.skt_count = htonl(sketch_ip->curve.count);
1373  *(uint32_t *)rec->skt.skt_count = htonl(ngran-1);
1374 
1375  ptr = (unsigned char *)rec;
1376  ptr += sizeof(struct sketch_rec);
1377  /* convert 2D points to mm */
1378  for (i=0; i<sketch_ip->vert_count; i++) {
1379  /* must be double for import and export */
1380  double pt2d[ELEMENTS_PER_VECT2D];
1381 
1382  V2SCALE(pt2d, sketch_ip->verts[i], local2mm);
1383  bu_cv_htond(ptr, (const unsigned char *)pt2d, ELEMENTS_PER_VECT2D);
1384  ptr += 16;
1385  }
1386 
1387  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1388  struct line_seg *lseg;
1389  struct carc_seg *cseg;
1390  struct nurb_seg *nseg;
1391  struct bezier_seg *bseg;
1392  uint32_t *lng;
1393 
1394  /* must be double for import and export */
1395  double tmp_fastf;
1396  double *scanp;
1397 
1398  /* write segment type ID, and segment parameters */
1399  lng = (uint32_t *)sketch_ip->curve.segment[seg_no];
1400  switch (*lng) {
1401  case CURVE_LSEG_MAGIC:
1402  lseg = (struct line_seg *)lng;
1403  *(uint32_t *)ptr = htonl(CURVE_LSEG_MAGIC);
1404  ptr += SIZEOF_NETWORK_LONG;
1405  *(uint32_t *)ptr = htonl(lseg->start);
1406  ptr += SIZEOF_NETWORK_LONG;
1407  *(uint32_t *)ptr = htonl(lseg->end);
1408  ptr += SIZEOF_NETWORK_LONG;
1409  break;
1410  case CURVE_CARC_MAGIC:
1411  cseg = (struct carc_seg *)lng;
1412  *(uint32_t *)ptr = htonl(CURVE_CARC_MAGIC);
1413  ptr += SIZEOF_NETWORK_LONG;
1414  *(uint32_t *)ptr = htonl(cseg->start);
1415  ptr += SIZEOF_NETWORK_LONG;
1416  *(uint32_t *)ptr = htonl(cseg->end);
1417  ptr += SIZEOF_NETWORK_LONG;
1418  *(uint32_t *)ptr = htonl(cseg->orientation);
1419  ptr += SIZEOF_NETWORK_LONG;
1420  *(uint32_t *)ptr = htonl(cseg->center_is_left);
1421  ptr += SIZEOF_NETWORK_LONG;
1422  tmp_fastf = cseg->radius * local2mm;
1423  bu_cv_htond(ptr, (unsigned char *)&tmp_fastf, 1);
1424  ptr += SIZEOF_NETWORK_DOUBLE;
1425  break;
1426  case CURVE_NURB_MAGIC:
1427  nseg = (struct nurb_seg *)lng;
1428  *(uint32_t *)ptr = htonl(CURVE_NURB_MAGIC);
1429  ptr += SIZEOF_NETWORK_LONG;
1430  *(uint32_t *)ptr = htonl(nseg->order);
1431  ptr += SIZEOF_NETWORK_LONG;
1432  *(uint32_t *)ptr = htonl(nseg->pt_type);
1433  ptr += SIZEOF_NETWORK_LONG;
1434  *(uint32_t *)ptr = htonl(nseg->k.k_size);
1435  ptr += SIZEOF_NETWORK_LONG;
1436  scanp = (double *)bu_malloc(nseg->k.k_size * sizeof(double), "scanp");
1437  /* convert fastf_t to double */
1438  for (i=0; i<(size_t)nseg->k.k_size; i++) {
1439  scanp[i] = nseg->k.knots[i];
1440  }
1441  bu_cv_htond(ptr, (const unsigned char *)scanp, nseg->k.k_size);
1442  bu_free(scanp, "scanp");
1443  ptr += nseg->k.k_size * 8;
1444  *(uint32_t *)ptr = htonl(nseg->c_size);
1445  ptr += SIZEOF_NETWORK_LONG;
1446  for (i=0; i<(size_t)nseg->c_size; i++) {
1447  *(uint32_t *)ptr = htonl(nseg->ctl_points[i]);
1448  ptr += SIZEOF_NETWORK_LONG;
1449  }
1450  if (RT_NURB_IS_PT_RATIONAL(nseg->pt_type)) {
1451  scanp = (double *)bu_malloc(nseg->c_size * sizeof(double), "scanp");
1452  /* convert fastf_t to double */
1453  for (i=0; i<(size_t)nseg->c_size; i++) {
1454  scanp[i] = nseg->weights[i];
1455  }
1456  bu_cv_htond(ptr, (const unsigned char *)scanp, nseg->c_size);
1457  bu_free(scanp, "scanp");
1458  ptr += SIZEOF_NETWORK_DOUBLE * nseg->c_size;
1459  }
1460  break;
1461  case CURVE_BEZIER_MAGIC:
1462  bseg = (struct bezier_seg *)lng;
1463  *(uint32_t *)ptr = htonl(CURVE_BEZIER_MAGIC);
1464  ptr += SIZEOF_NETWORK_LONG;
1465  *(uint32_t *)ptr = htonl(bseg->degree);
1466  ptr += SIZEOF_NETWORK_LONG;
1467  for (i=0; i<=(size_t)bseg->degree; i++) {
1468  *(uint32_t *)ptr = htonl(bseg->ctl_points[i]);
1469  ptr += SIZEOF_NETWORK_LONG;
1470  }
1471  break;
1472  default:
1473  bu_bomb("rt_sketch_export4: ERROR: unrecognized curve type!\n");
1474  break;
1475 
1476  }
1477  }
1478 
1479  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1480  *(uint32_t *)ptr = htonl(sketch_ip->curve.reverse[seg_no]);
1481  ptr += SIZEOF_NETWORK_LONG;
1482  }
1483  if (bu_debug&BU_DEBUG_MEM_CHECK) {
1484  bu_log("Barrier check at end of sketch_export4():\n");
1486  }
1487 
1488  return 0;
1489 }
1490 
1491 
1492 /**
1493  * Import an SKETCH from the database format to the internal format.
1494  * Apply modeling transformations as well.
1495  */
1496 int
1497 rt_sketch_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
1498 {
1499  struct rt_sketch_internal *sketch_ip;
1500  size_t seg_no;
1501  unsigned char *ptr;
1502  struct rt_curve *crv;
1503  size_t i;
1504 
1505  /* must be double for import and export */
1506  double v[ELEMENTS_PER_VECT];
1507  double *vp;
1508 
1510  bu_log("Barrier check at start of sketch_import5():\n");
1512  }
1513 
1514  if (dbip) RT_CK_DBI(dbip);
1515  BU_CK_EXTERNAL(ep);
1516 
1517  RT_CK_DB_INTERNAL(ip);
1518  ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
1519  ip->idb_type = ID_SKETCH;
1520  ip->idb_meth = &OBJ[ID_SKETCH];
1521  BU_ALLOC(ip->idb_ptr, struct rt_sketch_internal);
1522 
1523  sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
1524  sketch_ip->magic = RT_SKETCH_INTERNAL_MAGIC;
1525 
1526  ptr = ep->ext_buf;
1527  if (mat == NULL) mat = bn_mat_identity;
1528  bu_cv_ntohd((unsigned char *)v, ptr, ELEMENTS_PER_VECT);
1529  MAT4X3PNT(sketch_ip->V, mat, v);
1530  ptr += SIZEOF_NETWORK_DOUBLE * ELEMENTS_PER_VECT;
1531  bu_cv_ntohd((unsigned char *)v, ptr, ELEMENTS_PER_VECT);
1532  MAT4X3VEC(sketch_ip->u_vec, mat, v);
1533  ptr += SIZEOF_NETWORK_DOUBLE * ELEMENTS_PER_VECT;
1534  bu_cv_ntohd((unsigned char *)v, ptr, ELEMENTS_PER_VECT);
1535  MAT4X3VEC(sketch_ip->v_vec, mat, v);
1536  ptr += SIZEOF_NETWORK_DOUBLE * ELEMENTS_PER_VECT;
1537  sketch_ip->vert_count = ntohl(*(uint32_t *)ptr);
1538  ptr += SIZEOF_NETWORK_LONG;
1539  sketch_ip->curve.count = ntohl(*(uint32_t *)ptr);
1540  ptr += SIZEOF_NETWORK_LONG;
1541 
1542  if (sketch_ip->vert_count) {
1543  sketch_ip->verts = (point2d_t *)bu_calloc(sketch_ip->vert_count, sizeof(point2d_t), "sketch_ip->vert");
1544  vp = (double *)bu_calloc(sketch_ip->vert_count, sizeof(double)*ELEMENTS_PER_VECT2D, "vp");
1545  bu_cv_ntohd((unsigned char *)vp, ptr, sketch_ip->vert_count*2);
1546 
1547  /* convert double to fastf_t */
1548  for (i=0; i<sketch_ip->vert_count; i++) {
1549  sketch_ip->verts[i][X] = vp[(i*ELEMENTS_PER_VECT2D)+0];
1550  sketch_ip->verts[i][Y] = vp[(i*ELEMENTS_PER_VECT2D)+1];
1551  }
1552 
1553  bu_free(vp, "vp");
1554  ptr += SIZEOF_NETWORK_DOUBLE * 2 * sketch_ip->vert_count;
1555  }
1556 
1557  if (sketch_ip->curve.count)
1558  sketch_ip->curve.segment = (void **)bu_calloc(sketch_ip->curve.count, sizeof(void *), "segs");
1559  else
1560  sketch_ip->curve.segment = (void **)NULL;
1561  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1562  uint32_t magic;
1563  struct line_seg *lsg;
1564  struct carc_seg *csg;
1565  struct nurb_seg *nsg;
1566  struct bezier_seg *bsg;
1567 
1568  /* must be double for import and export */
1569  double scan;
1570  double *scanp;
1571 
1572  magic = ntohl(*(uint32_t *)ptr);
1573  ptr += SIZEOF_NETWORK_LONG;
1574  switch (magic) {
1575  case CURVE_LSEG_MAGIC:
1576  BU_ALLOC(lsg, struct line_seg);
1577  lsg->magic = magic;
1578  lsg->start = ntohl(*(uint32_t *)ptr);
1579  ptr += SIZEOF_NETWORK_LONG;
1580  lsg->end = ntohl(*(uint32_t *)ptr);
1581  ptr += SIZEOF_NETWORK_LONG;
1582  sketch_ip->curve.segment[seg_no] = (void *)lsg;
1583  break;
1584  case CURVE_CARC_MAGIC:
1585  BU_ALLOC(csg, struct carc_seg);
1586  csg->magic = magic;
1587  csg->start = ntohl(*(uint32_t *)ptr);
1588  ptr += SIZEOF_NETWORK_LONG;
1589  csg->end = ntohl(*(uint32_t *)ptr);
1590  ptr += SIZEOF_NETWORK_LONG;
1591  csg->orientation = ntohl(*(uint32_t *)ptr);
1592  ptr += SIZEOF_NETWORK_LONG;
1593  csg->center_is_left = ntohl(*(uint32_t *)ptr);
1594  ptr += SIZEOF_NETWORK_LONG;
1595  bu_cv_ntohd((unsigned char *)&scan, ptr, 1);
1596  csg->radius = scan; /* double to fastf_t */
1597  ptr += SIZEOF_NETWORK_DOUBLE;
1598  sketch_ip->curve.segment[seg_no] = (void *)csg;
1599  break;
1600  case CURVE_NURB_MAGIC:
1601  BU_ALLOC(nsg, struct nurb_seg);
1602  nsg->magic = magic;
1603  nsg->order = ntohl(*(uint32_t *)ptr);
1604  ptr += SIZEOF_NETWORK_LONG;
1605  nsg->pt_type = ntohl(*(uint32_t *)ptr);
1606  ptr += SIZEOF_NETWORK_LONG;
1607  nsg->k.k_size = ntohl(*(uint32_t *)ptr);
1608  ptr += SIZEOF_NETWORK_LONG;
1609 
1610  nsg->k.knots = (fastf_t *)bu_malloc(nsg->k.k_size * sizeof(fastf_t), "nsg->k.knots");
1611  scanp = (double *)bu_malloc(nsg->k.k_size * sizeof(double), "scanp");
1612  bu_cv_ntohd((unsigned char *)scanp, ptr, nsg->k.k_size);
1613 
1614  /* convert double to fastf_t */
1615  for (i=0; i<(size_t)nsg->k.k_size; i++) {
1616  nsg->k.knots[i] = scanp[i];
1617  }
1618  bu_free(scanp, "scanp");
1619 
1620  ptr += SIZEOF_NETWORK_DOUBLE * nsg->k.k_size;
1621  nsg->c_size = ntohl(*(uint32_t *)ptr);
1622  ptr += SIZEOF_NETWORK_LONG;
1623  nsg->ctl_points = (int *)bu_malloc(nsg->c_size * sizeof(int), "nsg->ctl_points");
1624  for (i=0; i<(size_t)nsg->c_size; i++) {
1625  nsg->ctl_points[i] = ntohl(*(uint32_t *)ptr);
1626  ptr += SIZEOF_NETWORK_LONG;
1627  }
1628  if (RT_NURB_IS_PT_RATIONAL(nsg->pt_type)) {
1629  nsg->weights = (fastf_t *)bu_malloc(nsg->c_size * sizeof(fastf_t), "nsg->weights");
1630  scanp = (double *)bu_malloc(nsg->c_size * sizeof(double), "scanp");
1631  bu_cv_ntohd((unsigned char *)scanp, ptr, nsg->c_size);
1632 
1633  /* convert double to fastf_t */
1634  for (i=0; i<(size_t)nsg->k.k_size; i++) {
1635  nsg->weights[i] = scanp[i];
1636  }
1637  bu_free(scanp, "scanp");
1638 
1639  ptr += SIZEOF_NETWORK_DOUBLE * nsg->c_size;
1640  } else
1641  nsg->weights = (fastf_t *)NULL;
1642  sketch_ip->curve.segment[seg_no] = (void *)nsg;
1643  break;
1644  case CURVE_BEZIER_MAGIC:
1645  BU_ALLOC(bsg, struct bezier_seg);
1646  bsg->magic = magic;
1647  bsg->degree = ntohl(*(uint32_t *)ptr);
1648  ptr += SIZEOF_NETWORK_LONG;
1649  bsg->ctl_points = (int *)bu_calloc(bsg->degree+1, sizeof(int), "bsg->ctl_points");
1650  for (i=0; i<=(size_t)bsg->degree; i++) {
1651  bsg->ctl_points[i] = ntohl(*(uint32_t *)ptr);
1652  ptr += SIZEOF_NETWORK_LONG;
1653  }
1654  sketch_ip->curve.segment[seg_no] = (void *)bsg;
1655  break;
1656  default:
1657  bu_bomb("rt_sketch_import4: ERROR: unrecognized segment type!\n");
1658  break;
1659  }
1660  }
1661 
1662  crv = &sketch_ip->curve;
1663 
1664  if (crv->count) {
1665  crv->reverse = (int *)bu_calloc(crv->count, sizeof(int), "crv->reverse");
1666  }
1667 
1668  for (i=0; i<crv->count; i++) {
1669  crv->reverse[i] = ntohl(*(uint32_t *)ptr);
1670  ptr += SIZEOF_NETWORK_LONG;
1671  }
1672 
1673  if (bu_debug&BU_DEBUG_MEM_CHECK) {
1674  bu_log("Barrier check at end of sketch_import5():\n");
1676  }
1677 
1678  return 0; /* OK */
1679 }
1680 
1681 
1682 /**
1683  * The name is added by the caller, in the usual place.
1684  */
1685 int
1686 rt_sketch_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
1687 {
1688  struct rt_sketch_internal *sketch_ip;
1689  unsigned char *cp;
1690  size_t seg_no;
1691  size_t i;
1692 
1693  /* must be double for import and export */
1694  double tmp_vec[ELEMENTS_PER_VECT];
1695 
1697  bu_log("Barrier check at start of sketch_export5():\n");
1699  }
1700 
1701  if (dbip) RT_CK_DBI(dbip);
1702 
1703  RT_CK_DB_INTERNAL(ip);
1704  if (ip->idb_type != ID_SKETCH) return -1;
1705  sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
1706  RT_SKETCH_CK_MAGIC(sketch_ip);
1707 
1708  BU_CK_EXTERNAL(ep);
1709 
1710  /* tally up size of buffer needed */
1711  ep->ext_nbytes = 3 * (ELEMENTS_PER_VECT * SIZEOF_NETWORK_DOUBLE) /* V, u_vec, v_vec */
1712  + 2 * SIZEOF_NETWORK_LONG /* vert_count and count */
1713  + 2 * sketch_ip->vert_count * SIZEOF_NETWORK_DOUBLE /* 2D-vertices */
1714  + sketch_ip->curve.count * SIZEOF_NETWORK_LONG; /* reverse flags */
1715 
1716  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1717  uint32_t *lng;
1718  struct nurb_seg *nseg;
1719  struct bezier_seg *bseg;
1720 
1721  lng = (uint32_t *)sketch_ip->curve.segment[seg_no];
1722  switch (*lng) {
1723  case CURVE_LSEG_MAGIC:
1724  /* magic + start + end */
1725  ep->ext_nbytes += 3 * SIZEOF_NETWORK_LONG;
1726  break;
1727  case CURVE_CARC_MAGIC:
1728  /* magic + start + end + orientation + center_is_left + (double)radius*/
1730  break;
1731  case CURVE_NURB_MAGIC:
1732  nseg = (struct nurb_seg *)lng;
1733  /* magic + order + pt_type + c_size */
1734  ep->ext_nbytes += 4 * SIZEOF_NETWORK_LONG;
1735  /* (double)knots */
1736  ep->ext_nbytes += SIZEOF_NETWORK_LONG + nseg->k.k_size * SIZEOF_NETWORK_DOUBLE;
1737  /* control point count */
1738  ep->ext_nbytes += nseg->c_size * SIZEOF_NETWORK_LONG;
1739  if (RT_NURB_IS_PT_RATIONAL(nseg->pt_type))
1740  /* (double)weights */
1741  ep->ext_nbytes += nseg->c_size * SIZEOF_NETWORK_DOUBLE;
1742  break;
1743  case CURVE_BEZIER_MAGIC:
1744  bseg = (struct bezier_seg *)lng;
1745  /* magic + degree */
1746  ep->ext_nbytes += 2 * SIZEOF_NETWORK_LONG;
1747  /* control points */
1748  ep->ext_nbytes += (bseg->degree + 1) * SIZEOF_NETWORK_LONG;
1749  break;
1750  default:
1751  bu_log("rt_sketch_export5: unsupported segment type (x%x)\n", *lng);
1752  bu_bomb("rt_sketch_export5: unsupported segment type\n");
1753  }
1754  }
1755  ep->ext_buf = (uint8_t *)bu_malloc(ep->ext_nbytes, "sketch external");
1756 
1757  cp = (unsigned char *)ep->ext_buf;
1758 
1759  /* scale and export */
1760  VSCALE(tmp_vec, sketch_ip->V, local2mm);
1761  bu_cv_htond(cp, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT);
1762  cp += ELEMENTS_PER_VECT * SIZEOF_NETWORK_DOUBLE;
1763 
1764  /* uvec and uvec are unit vectors, do not convert to/from mm */
1765  VMOVE(tmp_vec, sketch_ip->u_vec); /* convert fastf_t to double */
1766  bu_cv_htond(cp, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT);
1767  cp += ELEMENTS_PER_VECT * SIZEOF_NETWORK_DOUBLE;
1768  VMOVE(tmp_vec, sketch_ip->v_vec); /* convert fastf_t to double */
1769  bu_cv_htond(cp, (unsigned char *)tmp_vec, ELEMENTS_PER_VECT);
1770  cp += ELEMENTS_PER_VECT * SIZEOF_NETWORK_DOUBLE;
1771 
1772  *(uint32_t *)cp = htonl(sketch_ip->vert_count);
1773  cp += SIZEOF_NETWORK_LONG;
1774  *(uint32_t *)cp = htonl(sketch_ip->curve.count);
1775  cp += SIZEOF_NETWORK_LONG;
1776 
1777  /* convert 2D points to mm */
1778  for (i=0; i<sketch_ip->vert_count; i++) {
1779  /* must be double for import and export */
1780  double pt2d[ELEMENTS_PER_VECT2D];
1781 
1782  V2SCALE(pt2d, sketch_ip->verts[i], local2mm);
1783  bu_cv_htond(cp, (const unsigned char *)pt2d, ELEMENTS_PER_VECT2D);
1784  cp += 2 * SIZEOF_NETWORK_DOUBLE;
1785  }
1786 
1787  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1788  struct line_seg *lseg;
1789  struct carc_seg *cseg;
1790  struct nurb_seg *nseg;
1791  struct bezier_seg *bseg;
1792  uint32_t *lng;
1793 
1794  /* must be double for import and export */
1795  double scan;
1796  double *scanp;
1797 
1798  /* write segment type ID, and segment parameters */
1799  lng = (uint32_t *)sketch_ip->curve.segment[seg_no];
1800  switch (*lng) {
1801  case CURVE_LSEG_MAGIC:
1802  lseg = (struct line_seg *)lng;
1803  *(uint32_t *)cp = htonl(CURVE_LSEG_MAGIC);
1804  cp += SIZEOF_NETWORK_LONG;
1805  *(uint32_t *)cp = htonl(lseg->start);
1806  cp += SIZEOF_NETWORK_LONG;
1807  *(uint32_t *)cp = htonl(lseg->end);
1808  cp += SIZEOF_NETWORK_LONG;
1809  break;
1810  case CURVE_CARC_MAGIC:
1811  cseg = (struct carc_seg *)lng;
1812  *(uint32_t *)cp = htonl(CURVE_CARC_MAGIC);
1813  cp += SIZEOF_NETWORK_LONG;
1814  *(uint32_t *)cp = htonl(cseg->start);
1815  cp += SIZEOF_NETWORK_LONG;
1816  *(uint32_t *)cp = htonl(cseg->end);
1817  cp += SIZEOF_NETWORK_LONG;
1818  *(uint32_t *)cp = htonl(cseg->orientation);
1819  cp += SIZEOF_NETWORK_LONG;
1820  *(uint32_t *)cp = htonl(cseg->center_is_left);
1821  cp += SIZEOF_NETWORK_LONG;
1822  scan = cseg->radius * local2mm;
1823  bu_cv_htond(cp, (unsigned char *)&scan, 1);
1824  cp += SIZEOF_NETWORK_DOUBLE;
1825  break;
1826  case CURVE_NURB_MAGIC:
1827  nseg = (struct nurb_seg *)lng;
1828  *(uint32_t *)cp = htonl(CURVE_NURB_MAGIC);
1829  cp += SIZEOF_NETWORK_LONG;
1830  *(uint32_t *)cp = htonl(nseg->order);
1831  cp += SIZEOF_NETWORK_LONG;
1832  *(uint32_t *)cp = htonl(nseg->pt_type);
1833  cp += SIZEOF_NETWORK_LONG;
1834  *(uint32_t *)cp = htonl(nseg->k.k_size);
1835  cp += SIZEOF_NETWORK_LONG;
1836  scanp = (double *)bu_malloc(nseg->k.k_size * sizeof(double), "scanp");
1837  /* convert fastf_t to double */
1838  for (i=0; i<(size_t)nseg->k.k_size; i++) {
1839  scanp[i] = nseg->k.knots[i];
1840  }
1841  bu_cv_htond(cp, (const unsigned char *)nseg->k.knots, nseg->k.k_size);
1842  bu_free(scanp, "scanp");
1843  cp += nseg->k.k_size * SIZEOF_NETWORK_DOUBLE;
1844  *(uint32_t *)cp = htonl(nseg->c_size);
1845  cp += SIZEOF_NETWORK_LONG;
1846  for (i=0; i<(size_t)nseg->c_size; i++) {
1847  *(uint32_t *)cp = htonl(nseg->ctl_points[i]);
1848  cp += SIZEOF_NETWORK_LONG;
1849  }
1850  if (RT_NURB_IS_PT_RATIONAL(nseg->pt_type)) {
1851  scanp = (double *)bu_malloc(nseg->c_size * sizeof(double), "scanp");
1852  /* convert fastf_t to double */
1853  for (i=0; i<(size_t)nseg->c_size; i++) {
1854  scanp[i] = nseg->weights[i];
1855  }
1856  bu_cv_htond(cp, (const unsigned char *)scanp, nseg->c_size);
1857  bu_free(scanp, "scanp");
1858  cp += SIZEOF_NETWORK_DOUBLE * nseg->c_size;
1859  }
1860  break;
1861  case CURVE_BEZIER_MAGIC:
1862  bseg = (struct bezier_seg *)lng;
1863  *(uint32_t *)cp = htonl(CURVE_BEZIER_MAGIC);
1864  cp += SIZEOF_NETWORK_LONG;
1865  *(uint32_t *)cp = htonl(bseg->degree);
1866  cp += SIZEOF_NETWORK_LONG;
1867  for (i=0; i<=(size_t)bseg->degree; i++) {
1868  *(uint32_t *)cp = htonl(bseg->ctl_points[i]);
1869  cp += SIZEOF_NETWORK_LONG;
1870  }
1871  break;
1872  default:
1873  bu_bomb("rt_sketch_export5: ERROR: unrecognized curve type!\n");
1874  break;
1875 
1876  }
1877  }
1878 
1879  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1880  *(uint32_t *)cp = htonl(sketch_ip->curve.reverse[seg_no]);
1881  cp += SIZEOF_NETWORK_LONG;
1882  }
1883 
1884  if (bu_debug&BU_DEBUG_MEM_CHECK) {
1885  bu_log("Barrier check at end of sketch_export5():\n");
1887  }
1888 
1889  return 0;
1890 }
1891 
1892 
1893 /**
1894  * Make human-readable formatted presentation of this solid. First
1895  * line describes type of solid. Additional lines are indented one
1896  * tab, and give parameter values.
1897  */
1898 int
1899 rt_sketch_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
1900 {
1901  struct rt_sketch_internal *sketch_ip =
1902  (struct rt_sketch_internal *)ip->idb_ptr;
1903  size_t i;
1904  size_t seg_no;
1905  char buf[256];
1906  point_t V;
1907  vect_t u, v;
1908 
1909  RT_SKETCH_CK_MAGIC(sketch_ip);
1910  bu_vls_strcat(str, "2D sketch (SKETCH)\n");
1911 
1912  VSCALE(V, sketch_ip->V, mm2local);
1913  VSCALE(u, sketch_ip->u_vec, mm2local);
1914  VSCALE(v, sketch_ip->v_vec, mm2local);
1915 
1916  sprintf(buf, "\tV = (%g %g %g), A = (%g %g %g), B = (%g %g %g)\n\t%lu vertices\n",
1917  V3INTCLAMPARGS(V),
1918  V3INTCLAMPARGS(u),
1919  V3INTCLAMPARGS(v),
1920  (long unsigned)sketch_ip->vert_count);
1921  bu_vls_strcat(str, buf);
1922 
1923  if (!verbose)
1924  return 0;
1925 
1926  if (sketch_ip->vert_count) {
1927  bu_vls_strcat(str, "\tVertices:\n\t");
1928  for (i=0; i<sketch_ip->vert_count; i++) {
1929  sprintf(buf, " %lu-(%g %g)", (long unsigned)i, V2INTCLAMPARGS(sketch_ip->verts[i]));
1930  bu_vls_strcat(str, buf);
1931  if (i && (i+1)%3 == 0)
1932  bu_vls_strcat(str, "\n\t");
1933  }
1934  }
1935  bu_vls_strcat(str, "\n");
1936 
1937  sprintf(buf, "\n\tCurve:\n");
1938  bu_vls_strcat(str, buf);
1939  for (seg_no=0; seg_no < sketch_ip->curve.count; seg_no++) {
1940  struct line_seg *lsg;
1941  struct carc_seg *csg;
1942  struct nurb_seg *nsg;
1943  struct bezier_seg *bsg;
1944 
1945  lsg = (struct line_seg *)sketch_ip->curve.segment[seg_no];
1946  switch (lsg->magic) {
1947  case CURVE_LSEG_MAGIC:
1948  lsg = (struct line_seg *)sketch_ip->curve.segment[seg_no];
1949  if ((size_t)lsg->start >= sketch_ip->vert_count || (size_t)lsg->end >= sketch_ip->vert_count) {
1950  if (sketch_ip->curve.reverse[seg_no])
1951  sprintf(buf, "\t\tLine segment from vertex #%d to #%d\n",
1952  lsg->end, lsg->start);
1953  else
1954  sprintf(buf, "\t\tLine segment from vertex #%d to #%d\n",
1955  lsg->start, lsg->end);
1956  } else {
1957  if (sketch_ip->curve.reverse[seg_no])
1958  sprintf(buf, "\t\tLine segment (%g %g) <-> (%g %g)\n",
1959  V2INTCLAMPARGS(sketch_ip->verts[lsg->end]),
1960  V2INTCLAMPARGS(sketch_ip->verts[lsg->start]));
1961  else
1962  sprintf(buf, "\t\tLine segment (%g %g) <-> (%g %g)\n",
1963  V2INTCLAMPARGS(sketch_ip->verts[lsg->start]),
1964  V2INTCLAMPARGS(sketch_ip->verts[lsg->end]));
1965  }
1966  bu_vls_strcat(str, buf);
1967  break;
1968  case CURVE_CARC_MAGIC:
1969  csg = (struct carc_seg *)sketch_ip->curve.segment[seg_no];
1970  if (csg->radius < 0.0) {
1971  bu_vls_strcat(str, "\t\tFull Circle:\n");
1972 
1973  if ((size_t)csg->end >= sketch_ip->vert_count || (size_t)csg->start >= sketch_ip->vert_count) {
1974  sprintf(buf, "\t\tcenter at vertex #%d\n",
1975  csg->end);
1976  bu_vls_strcat(str, buf);
1977  sprintf(buf, "\t\tpoint on circle at vertex #%d\n",
1978  csg->start);
1979  } else {
1980  sprintf(buf, "\t\t\tcenter: (%g %g)\n",
1981  V2INTCLAMPARGS(sketch_ip->verts[csg->end]));
1982  bu_vls_strcat(str, buf);
1983  sprintf(buf, "\t\t\tpoint on circle: (%g %g)\n",
1984  V2INTCLAMPARGS(sketch_ip->verts[csg->start]));
1985  }
1986  bu_vls_strcat(str, buf);
1987  } else {
1988  bu_vls_strcat(str, "\t\tCircular Arc:\n");
1989 
1990  if ((size_t)csg->end >= sketch_ip->vert_count || (size_t)csg->start >= sketch_ip->vert_count) {
1991  sprintf(buf, "\t\t\tstart at vertex #%d\n",
1992  csg->start);
1993  bu_vls_strcat(str, buf);
1994  sprintf(buf, "\t\t\tend at vertex #%d\n",
1995  csg->end);
1996  bu_vls_strcat(str, buf);
1997  } else {
1998  sprintf(buf, "\t\t\tstart: (%g, %g)\n",
1999  V2INTCLAMPARGS(sketch_ip->verts[csg->start]));
2000  bu_vls_strcat(str, buf);
2001  sprintf(buf, "\t\t\tend: (%g, %g)\n",
2002  V2INTCLAMPARGS(sketch_ip->verts[csg->end]));
2003  bu_vls_strcat(str, buf);
2004  }
2005  sprintf(buf, "\t\t\tradius: %g\n", csg->radius*mm2local);
2006  bu_vls_strcat(str, buf);
2007  if (csg->orientation)
2008  bu_vls_strcat(str, "\t\t\tcurve is clock-wise\n");
2009  else
2010  bu_vls_strcat(str, "\t\t\tcurve is counter-clock-wise\n");
2011  if (csg->center_is_left)
2012  bu_vls_strcat(str, "\t\t\tcenter of curvature is left of the line from start point to end point\n");
2013  else
2014  bu_vls_strcat(str, "\t\t\tcenter of curvature is right of the line from start point to end point\n");
2015  if (sketch_ip->curve.reverse[seg_no])
2016  bu_vls_strcat(str, "\t\t\tarc is reversed\n");
2017  }
2018  break;
2019  case CURVE_NURB_MAGIC:
2020  nsg = (struct nurb_seg *)sketch_ip->curve.segment[seg_no];
2021  bu_vls_strcat(str, "\t\tNURB Curve:\n");
2022  if (RT_NURB_IS_PT_RATIONAL(nsg->pt_type)) {
2023  sprintf(buf, "\t\t\tCurve is rational\n");
2024  bu_vls_strcat(str, buf);
2025  }
2026  sprintf(buf, "\t\t\torder = %d, number of control points = %d\n",
2027  nsg->order, nsg->c_size);
2028  bu_vls_strcat(str, buf);
2029  if ((size_t)nsg->ctl_points[0] >= sketch_ip->vert_count ||
2030  (size_t)nsg->ctl_points[nsg->c_size-1] >= sketch_ip->vert_count) {
2031  if (sketch_ip->curve.reverse[seg_no])
2032  sprintf(buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
2033  nsg->ctl_points[nsg->c_size-1],
2034  nsg->ctl_points[0]);
2035  else
2036  sprintf(buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
2037  nsg->ctl_points[0],
2038  nsg->ctl_points[nsg->c_size-1]);
2039  } else {
2040  if (sketch_ip->curve.reverse[seg_no])
2041  sprintf(buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
2042  V2INTCLAMPARGS(sketch_ip->verts[nsg->ctl_points[nsg->c_size-1]]),
2043  V2INTCLAMPARGS(sketch_ip->verts[nsg->ctl_points[0]]));
2044  else
2045  sprintf(buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
2046  V2INTCLAMPARGS(sketch_ip->verts[nsg->ctl_points[0]]),
2047  V2INTCLAMPARGS(sketch_ip->verts[nsg->ctl_points[nsg->c_size-1]]));
2048  }
2049  bu_vls_strcat(str, buf);
2050  sprintf(buf, "\t\t\tknot values are %g to %g\n",
2051  INTCLAMP(nsg->k.knots[0]), INTCLAMP(nsg->k.knots[nsg->k.k_size-1]));
2052  bu_vls_strcat(str, buf);
2053  break;
2054  case CURVE_BEZIER_MAGIC:
2055  bsg = (struct bezier_seg *)sketch_ip->curve.segment[seg_no];
2056  bu_vls_strcat(str, "\t\tBezier segment:\n");
2057  sprintf(buf, "\t\t\tdegree = %d\n", bsg->degree);
2058  bu_vls_strcat(str, buf);
2059  if ((size_t)bsg->ctl_points[0] >= sketch_ip->vert_count ||
2060  (size_t)bsg->ctl_points[bsg->degree] >= sketch_ip->vert_count) {
2061  if (sketch_ip->curve.reverse[seg_no]) {
2062  sprintf(buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
2063  bsg->ctl_points[bsg->degree],
2064  bsg->ctl_points[0]);
2065  } else {
2066  sprintf(buf, "\t\t\tstarts at vertex #%d\n\t\t\tends at vertex #%d\n",
2067  bsg->ctl_points[0],
2068  bsg->ctl_points[bsg->degree]);
2069  }
2070  } else {
2071  if (sketch_ip->curve.reverse[seg_no])
2072  sprintf(buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
2073  V2INTCLAMPARGS(sketch_ip->verts[bsg->ctl_points[bsg->degree]]),
2074  V2INTCLAMPARGS(sketch_ip->verts[bsg->ctl_points[0]]));
2075  else
2076  sprintf(buf, "\t\t\tstarts at (%g %g)\n\t\t\tends at (%g %g)\n",
2077  V2INTCLAMPARGS(sketch_ip->verts[bsg->ctl_points[0]]),
2078  V2INTCLAMPARGS(sketch_ip->verts[bsg->ctl_points[bsg->degree]]));
2079  }
2080  bu_vls_strcat(str, buf);
2081  break;
2082  default:
2083  bu_bomb("rt_sketch_describe: ERROR: unrecognized segment type\n");
2084  }
2085  }
2086 
2087  return 0;
2088 }
2089 
2090 
2091 void
2092 rt_curve_free(struct rt_curve *crv)
2093 {
2094  size_t i;
2095 
2096  if (crv->count)
2097  bu_free((char *)crv->reverse, "crv->reverse");
2098  for (i=0; i<crv->count; i++) {
2099  uint32_t *lng;
2100  struct nurb_seg *nsg;
2101  struct bezier_seg *bsg;
2102 
2103  lng = (uint32_t *)crv->segment[i];
2104  switch (*lng) {
2105  case CURVE_NURB_MAGIC:
2106  nsg = (struct nurb_seg *)lng;
2107  bu_free((char *)nsg->ctl_points, "nsg->ctl_points");
2108  if (nsg->weights)
2109  bu_free((char *)nsg->weights, "nsg->weights");
2110  bu_free((char *)nsg->k.knots, "nsg->k.knots");
2111  bu_free((char *)lng, "curve segment");
2112  break;
2113  case CURVE_BEZIER_MAGIC:
2114  bsg = (struct bezier_seg *)lng;
2115  bu_free((char *)bsg->ctl_points, "bsg->ctl_points");
2116  bu_free((char *)lng, "curve segment");
2117  break;
2118  case CURVE_LSEG_MAGIC:
2119  case CURVE_CARC_MAGIC:
2120  bu_free((char *)lng, "curve segment");
2121  break;
2122  default:
2123  bu_log("ERROR: rt_curve_free: unrecognized curve segments type!\n");
2124  break;
2125  }
2126  }
2127 
2128  if (crv->count > 0)
2129  bu_free((char *)crv->segment, "crv->segments");
2130 
2131  crv->count = 0;
2132  crv->reverse = (int *)NULL;
2133  crv->segment = (void **)NULL;
2134 }
2135 
2136 
2137 /**
2138  * Free the storage associated with the rt_db_internal version of this
2139  * solid.
2140  */
2141 void
2143 {
2144  struct rt_sketch_internal *sketch_ip;
2145  struct rt_curve *crv;
2146 
2147  RT_CK_DB_INTERNAL(ip);
2148 
2149  sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
2150  RT_SKETCH_CK_MAGIC(sketch_ip);
2151  sketch_ip->magic = 0; /* sanity */
2152 
2154  bu_log("Barrier check at start of sketch_ifree():\n");
2156  }
2157 
2158  if (sketch_ip->verts)
2159  bu_free((char *)sketch_ip->verts, "sketch_ip->verts");
2160 
2161  crv = &sketch_ip->curve;
2162 
2163  rt_curve_free(crv);
2164 
2165  bu_free((char *)sketch_ip, "sketch ifree");
2166  ip->idb_ptr = ((void *)0); /* sanity */
2167 
2168  if (bu_debug&BU_DEBUG_MEM_CHECK) {
2169  bu_log("Barrier check at end of sketch_ifree():\n");
2171  }
2172 }
2173 
2174 
2175 void
2176 rt_copy_curve(struct rt_curve *crv_out, const struct rt_curve *crv_in)
2177 {
2178  size_t i, j;
2179 
2180  crv_out->count = crv_in->count;
2181  if (crv_out->count) {
2182  crv_out->reverse = (int *)bu_calloc(crv_out->count, sizeof(int), "crv->reverse");
2183  crv_out->segment = (void **)bu_calloc(crv_out->count, sizeof(void *), "crv->segments");
2184  }
2185 
2186  for (j=0; j<crv_out->count; j++) {
2187  uint32_t *lng;
2188  struct line_seg *lsg_out, *lsg_in;
2189  struct carc_seg *csg_out, *csg_in;
2190  struct nurb_seg *nsg_out, *nsg_in;
2191  struct bezier_seg *bsg_out, *bsg_in;
2192 
2193  crv_out->reverse[j] = crv_in->reverse[j];
2194  lng = (uint32_t *)crv_in->segment[j];
2195  switch (*lng) {
2196  case CURVE_LSEG_MAGIC:
2197  lsg_in = (struct line_seg *)lng;
2198  BU_ALLOC(lsg_out, struct line_seg);
2199  crv_out->segment[j] = (void *)lsg_out;
2200  *lsg_out = *lsg_in;
2201  break;
2202  case CURVE_CARC_MAGIC:
2203  csg_in = (struct carc_seg *)lng;
2204  BU_ALLOC(csg_out, struct carc_seg);
2205  crv_out->segment[j] = (void *)csg_out;
2206  *csg_out = *csg_in;
2207  break;
2208  case CURVE_NURB_MAGIC:
2209  nsg_in = (struct nurb_seg *)lng;
2210  BU_ALLOC(nsg_out, struct nurb_seg);
2211  crv_out->segment[j] = (void *)nsg_out;
2212  *nsg_out = *nsg_in;
2213  nsg_out->ctl_points = (int *)bu_calloc(nsg_in->c_size, sizeof(int), "nsg_out->ctl_points");
2214  for (i=0; i<(size_t)nsg_out->c_size; i++)
2215  nsg_out->ctl_points[i] = nsg_in->ctl_points[i];
2216  if (RT_NURB_IS_PT_RATIONAL(nsg_in->pt_type)) {
2217  nsg_out->weights = (fastf_t *)bu_malloc(nsg_out->c_size * sizeof(fastf_t), "nsg_out->weights");
2218  for (i=0; i<(size_t)nsg_out->c_size; i++)
2219  nsg_out->weights[i] = nsg_in->weights[i];
2220  } else
2221  nsg_out->weights = (fastf_t *)NULL;
2222  nsg_out->k.knots = (fastf_t *)bu_malloc(nsg_in->k.k_size * sizeof(fastf_t), "nsg_out->k.knots");
2223  for (i=0; i<(size_t)nsg_in->k.k_size; i++)
2224  nsg_out->k.knots[i] = nsg_in->k.knots[i];
2225  break;
2226  case CURVE_BEZIER_MAGIC:
2227  bsg_in = (struct bezier_seg *)lng;
2228  BU_ALLOC(bsg_out, struct bezier_seg);
2229  crv_out->segment[j] = (void *)bsg_out;
2230  *bsg_out = *bsg_in;
2231  bsg_out->ctl_points = (int *)bu_calloc(bsg_out->degree + 1,
2232  sizeof(int), "bsg_out->ctl_points");
2233  for (i=0; i<=(size_t)bsg_out->degree; i++) {
2234  bsg_out->ctl_points[i] = bsg_in->ctl_points[i];
2235  }
2236  break;
2237  default:
2238  bu_bomb("rt_copy_sketch: ERROR: unrecognized segment type!\n");
2239  }
2240  }
2241 
2242 }
2243 
2244 
2245 struct rt_sketch_internal *
2246 rt_copy_sketch(const struct rt_sketch_internal *sketch_ip)
2247 {
2248  struct rt_sketch_internal *out;
2249  size_t i;
2250  struct rt_curve *crv_out;
2251 
2252  RT_SKETCH_CK_MAGIC(sketch_ip);
2253 
2255  bu_log("Barrier check at start of rt_copy_sketch():\n");
2257  }
2258 
2259  BU_ALLOC(out, struct rt_sketch_internal);
2260  *out = *sketch_ip; /* struct copy */
2261 
2262  if (out->vert_count)
2263  out->verts = (point2d_t *)bu_calloc(out->vert_count, sizeof(point2d_t), "out->verts");
2264 
2265  for (i=0; sketch_ip->verts && i<out->vert_count; i++) {
2266  V2MOVE(out->verts[i], sketch_ip->verts[i]);
2267  }
2268 
2269  crv_out = &out->curve;
2270  if (crv_out)
2271  rt_copy_curve(crv_out, &sketch_ip->curve);
2272 
2273  if (bu_debug&BU_DEBUG_MEM_CHECK) {
2274  bu_log("Barrier check at end of rt_copy_sketch():\n");
2276  }
2277 
2278  return out;
2279 }
2280 
2281 
2282 int
2283 curve_to_tcl_list(struct bu_vls *vls, struct rt_curve *crv)
2284 {
2285  size_t i, j;
2286 
2287  bu_vls_printf(vls, " SL {");
2288  for (j=0; j<crv->count; j++) {
2289  switch ((*(uint32_t *)crv->segment[j])) {
2290  case CURVE_LSEG_MAGIC:
2291  {
2292  struct line_seg *lsg = (struct line_seg *)crv->segment[j];
2293  bu_vls_printf(vls, " { line S %d E %d }", lsg->start, lsg->end);
2294  }
2295  break;
2296  case CURVE_CARC_MAGIC:
2297  {
2298  struct carc_seg *csg = (struct carc_seg *)crv->segment[j];
2299  bu_vls_printf(vls, " { carc S %d E %d R %.25g L %d O %d }",
2300  csg->start, csg->end, csg->radius,
2301  csg->center_is_left, csg->orientation);
2302  }
2303  break;
2304  case CURVE_BEZIER_MAGIC:
2305  {
2306  struct bezier_seg *bsg = (struct bezier_seg *)crv->segment[j];
2307  bu_vls_printf(vls, " { bezier D %d P {", bsg->degree);
2308  for (i=0; i<=(size_t)bsg->degree; i++)
2309  bu_vls_printf(vls, " %d", bsg->ctl_points[i]);
2310  bu_vls_printf(vls, " } }");
2311  }
2312  break;
2313  case CURVE_NURB_MAGIC:
2314  {
2315  size_t k;
2316  struct nurb_seg *nsg = (struct nurb_seg *)crv->segment[j];
2317  bu_vls_printf(vls, " { nurb O %d T %d K {",
2318  nsg->order, nsg->pt_type);
2319  for (k=0; k<(size_t)nsg->k.k_size; k++)
2320  bu_vls_printf(vls, " %.25g", nsg->k.knots[k]);
2321  bu_vls_strcat(vls, "} P {");
2322  for (k=0; k<(size_t)nsg->c_size; k++)
2323  bu_vls_printf(vls, " %d", nsg->ctl_points[k]);
2324  if (nsg->weights) {
2325  bu_vls_strcat(vls, "} W {");
2326  for (k=0; k<(size_t)nsg->c_size; k++)
2327  bu_vls_printf(vls, " %.25g", nsg->weights[k]);
2328  }
2329  bu_vls_strcat(vls, "} }");
2330  }
2331  break;
2332  }
2333  }
2334  bu_vls_strcat(vls, " }"); /* end of segment list */
2335 
2336  return 0;
2337 }
2338 
2339 
2340 int rt_sketch_form(struct bu_vls *logstr, const struct rt_functab *ftp)
2341 {
2342  BU_CK_VLS(logstr);
2343  RT_CK_FUNCTAB(ftp);
2344 
2345  bu_vls_printf(logstr, "V {%%f %%f %%f} A {%%f %%f %%f} B {%%f %%f %%f} VL {{%%f %%f} {%%f %%f} ...} SL {{segment_data} {segment_data}}");
2346 
2347  return BRLCAD_OK;
2348 }
2349 
2350 
2351 int
2352 rt_sketch_get(struct bu_vls *logstr, const struct rt_db_internal *intern, const char *attr)
2353 {
2354  struct rt_sketch_internal *skt=(struct rt_sketch_internal *)intern->idb_ptr;
2355  size_t i;
2356  struct rt_curve *crv;
2357 
2358  BU_CK_VLS(logstr);
2359  RT_SKETCH_CK_MAGIC(skt);
2360 
2361  if (attr == (char *)NULL) {
2362  bu_vls_strcpy(logstr, "sketch");
2363  bu_vls_printf(logstr, " V {%.25g %.25g %.25g}", V3ARGS(skt->V));
2364  bu_vls_printf(logstr, " A {%.25g %.25g %.25g}", V3ARGS(skt->u_vec));
2365  bu_vls_printf(logstr, " B {%.25g %.25g %.25g}", V3ARGS(skt->v_vec));
2366  bu_vls_strcat(logstr, " VL {");
2367  for (i=0; i<skt->vert_count; i++)
2368  bu_vls_printf(logstr, " {%.25g %.25g}", V2ARGS(skt->verts[i]));
2369  bu_vls_strcat(logstr, " }");
2370 
2371  crv = &skt->curve;
2372  if (curve_to_tcl_list(logstr, crv)) {
2373  return BRLCAD_ERROR;
2374  }
2375  } else if (BU_STR_EQUAL(attr, "V")) {
2376  bu_vls_printf(logstr, "%.25g %.25g %.25g", V3ARGS(skt->V));
2377  } else if (BU_STR_EQUAL(attr, "A")) {
2378  bu_vls_printf(logstr, "%.25g %.25g %.25g", V3ARGS(skt->u_vec));
2379  } else if (BU_STR_EQUAL(attr, "B")) {
2380  bu_vls_printf(logstr, "%.25g %.25g %.25g", V3ARGS(skt->v_vec));
2381  } else if (BU_STR_EQUAL(attr, "VL")) {
2382  for (i=0; i<skt->vert_count; i++)
2383  bu_vls_printf(logstr, " {%.25g %.25g}", V2ARGS(skt->verts[i]));
2384  } else if (BU_STR_EQUAL(attr, "SL")) {
2385  crv = &skt->curve;
2386  if (curve_to_tcl_list(logstr, crv)) {
2387  return BRLCAD_ERROR;
2388  }
2389  } else if (*attr == 'V') {
2390  long lval = atol((attr+1));
2391  if (lval < 0 || (size_t)lval >= skt->vert_count) {
2392  bu_vls_printf(logstr, "ERROR: Illegal vertex number\n");
2393  return BRLCAD_ERROR;
2394  }
2395  bu_vls_printf(logstr, "%.25g %.25g", V2ARGS(skt->verts[lval]));
2396  } else {
2397  /* unrecognized attribute */
2398  bu_vls_printf(logstr, "ERROR: Unknown attribute, choices are V, A, B, VL, SL, or V#\n");
2399  return BRLCAD_ERROR;
2400  }
2401 
2402  return BRLCAD_OK;
2403 }
2404 
2405 
2406 int
2407 get_tcl_curve(Tcl_Interp *interp, struct rt_curve *crv, Tcl_Obj *seg_list)
2408 {
2409  int count;
2410  int ret, j;
2411 
2412  /* get number of segments */
2413  count = 0;
2414  ret=Tcl_ListObjLength(interp, seg_list, &count);
2415  if (ret) {
2416  return ret;
2417  }
2418 
2419  if (count) {
2420  crv->count = count;
2421  crv->reverse = (int *)bu_calloc(count, sizeof(int), "crv->reverse");
2422  crv->segment = (void **)bu_calloc(count, sizeof(void *), "crv->segment");
2423  }
2424 
2425  /* loop through all the segments */
2426  for (j=0; j<count; j++) {
2427  Tcl_Obj *seg, *seg_type, *seg_elem, *seg_val;
2428  char *type, *elem;
2429  int k, seg_len;
2430 
2431 
2432  /* get the next segment */
2433  ret=Tcl_ListObjIndex(interp, seg_list, j, &seg);
2434  if (ret)
2435  return ret;
2436 
2437  ret=Tcl_ListObjLength(interp, seg, &seg_len);
2438  if (ret)
2439  return ret;
2440 
2441  /* get the segment type */
2442  ret=Tcl_ListObjIndex(interp, seg, 0, &seg_type);
2443  if (ret)
2444  return ret;
2445  type = Tcl_GetString(seg_type);
2446 
2447  if (BU_STR_EQUAL(type, "line")) {
2448  struct line_seg *lsg;
2449 
2450  BU_ALLOC(lsg, struct line_seg);
2451  for (k=1; k<seg_len; k += 2) {
2452  ret=Tcl_ListObjIndex(interp, seg, k, &seg_elem);
2453  if (ret)
2454  return ret;
2455 
2456  ret=Tcl_ListObjIndex(interp, seg, k+1, &seg_val);
2457  if (ret)
2458  return ret;
2459 
2460  elem = Tcl_GetString(seg_elem);
2461  switch (*elem) {
2462  case 'S':
2463  Tcl_GetIntFromObj(interp, seg_val, &lsg->start);
2464  break;
2465  case 'E':
2466  Tcl_GetIntFromObj(interp, seg_val, &lsg->end);
2467  break;
2468  }
2469  }
2470  lsg->magic = CURVE_LSEG_MAGIC;
2471  crv->segment[j] = (void *)lsg;
2472  } else if (BU_STR_EQUAL(type, "bezier")) {
2473  struct bezier_seg *bsg;
2474  int num_points;
2475 
2476  BU_ALLOC(bsg, struct bezier_seg);
2477  for (k=1; k<seg_len; k+= 2) {
2478 
2479  ret=Tcl_ListObjIndex(interp, seg, k, &seg_elem);
2480  if (ret)
2481  return ret;
2482 
2483  ret=Tcl_ListObjIndex(interp, seg, k+1, &seg_val);
2484  if (ret)
2485  return ret;
2486 
2487  elem = Tcl_GetString(seg_elem);
2488  switch (*elem) {
2489  case 'D': /* degree */
2490  Tcl_GetIntFromObj(interp, seg_val,
2491  &bsg->degree);
2492  break;
2493  case 'P': /* list of control points */
2494  num_points = 0;
2495  (void)tcl_obj_to_int_array(interp,
2496  seg_val, &bsg->ctl_points,
2497  &num_points);
2498 
2499  if (num_points != bsg->degree + 1) {
2500  Tcl_SetResult(interp, "ERROR: degree and number of control points disagree for a Bezier segment\n", TCL_STATIC);
2501  return TCL_ERROR;
2502  }
2503  }
2504  }
2505  bsg->magic = CURVE_BEZIER_MAGIC;
2506  crv->segment[j] = (void *)bsg;
2507  } else if (BU_STR_EQUAL(type, "carc")) {
2508  struct carc_seg *csg;
2509  double tmp;
2510 
2511  BU_ALLOC(csg, struct carc_seg);
2512  for (k=1; k<seg_len; k += 2) {
2513  ret=Tcl_ListObjIndex(interp, seg, k, &seg_elem);
2514  if (ret)
2515  return ret;
2516 
2517  ret=Tcl_ListObjIndex(interp, seg, k+1, &seg_val);
2518  if (ret)
2519  return ret;
2520 
2521  elem = Tcl_GetString(seg_elem);
2522  switch (*elem) {
2523  case 'S':
2524  Tcl_GetIntFromObj(interp, seg_val, &csg->start);
2525  break;
2526  case 'E':
2527  Tcl_GetIntFromObj(interp, seg_val, &csg->end);
2528  break;
2529  case 'R':
2530  Tcl_GetDoubleFromObj(interp, seg_val, &tmp);
2531  csg->radius = tmp;
2532  break;
2533  case 'L' :
2534  Tcl_GetBooleanFromObj(interp, seg_val, &csg->center_is_left);
2535  break;
2536  case 'O':
2537  Tcl_GetBooleanFromObj(interp, seg_val, &csg->orientation);
2538  break;
2539  }
2540  }
2541  csg->magic = CURVE_CARC_MAGIC;
2542  crv->segment[j] = (void *)csg;
2543  } else if (BU_STR_EQUAL(type, "nurb")) {
2544  struct nurb_seg *nsg;
2545 
2546  BU_ALLOC(nsg, struct nurb_seg);
2547  for (k=1; k<seg_len; k += 2) {
2548  ret=Tcl_ListObjIndex(interp, seg, k, &seg_elem);
2549  if (ret)
2550  return ret;
2551 
2552  ret=Tcl_ListObjIndex(interp, seg, k+1, &seg_val);
2553  if (ret)
2554  return ret;
2555 
2556  elem = Tcl_GetString(seg_elem);
2557  switch (*elem) {
2558  case 'O':
2559  Tcl_GetIntFromObj(interp, seg_val, &nsg->order);
2560  break;
2561  case 'T':
2562  Tcl_GetIntFromObj(interp, seg_val, &nsg->pt_type);
2563  break;
2564  case 'K':
2565  tcl_obj_to_fastf_array(interp, seg_val, &nsg->k.knots, &nsg->k.k_size);
2566  break;
2567  case 'P' :
2568  tcl_obj_to_int_array(interp, seg_val, &nsg->ctl_points, &nsg->c_size);
2569  break;
2570  case 'W':
2571  tcl_obj_to_fastf_array(interp, seg_val, &nsg->weights, &nsg->c_size);
2572  break;
2573  }
2574  }
2575  nsg->magic = CURVE_NURB_MAGIC;
2576  crv->segment[j] = (void *)nsg;
2577  } else {
2578  Tcl_ResetResult(interp);
2579  Tcl_AppendResult(interp, "ERROR: Unrecognized segment type: ",
2580  Tcl_GetString(seg), (char *)NULL);
2581  return TCL_ERROR;
2582  }
2583  }
2584 
2585  return TCL_OK;
2586 }
2587 
2588 
2589 int
2590 rt_sketch_adjust(struct bu_vls *logstr, struct rt_db_internal *intern, int argc, const char **argv)
2591 {
2592  struct rt_sketch_internal *skt;
2593  int ret, array_len;
2594  fastf_t *newval;
2595 
2596  RT_CK_DB_INTERNAL(intern);
2597  skt = (struct rt_sketch_internal *)intern->idb_ptr;
2598  RT_SKETCH_CK_MAGIC(skt);
2599 
2600  while (argc >= 2) {
2601  if (BU_STR_EQUAL(argv[0], "V")) {
2602  newval = skt->V;
2603  array_len = 3;
2604  if (tcl_list_to_fastf_array(brlcad_interp, argv[1], &newval, &array_len) !=
2605  array_len) {
2606  bu_vls_printf(logstr, "ERROR: Incorrect number of coordinates for vertex\n");
2607  return BRLCAD_ERROR;
2608  }
2609  } else if (BU_STR_EQUAL(argv[0], "A")) {
2610  newval = skt->u_vec;
2611  array_len = 3;
2612  if (tcl_list_to_fastf_array(brlcad_interp, argv[1], &newval, &array_len) !=
2613  array_len) {
2614  bu_vls_printf(logstr, "ERROR: Incorrect number of coordinates for vertex\n");
2615  return BRLCAD_ERROR;
2616  }
2617  } else if (BU_STR_EQUAL(argv[0], "B")) {
2618  newval = skt->v_vec;
2619  array_len = 3;
2620  if (tcl_list_to_fastf_array(brlcad_interp, argv[1], &newval, &array_len) !=
2621  array_len) {
2622  bu_vls_printf(logstr, "ERROR: Incorrect number of coordinates for vertex\n");
2623  return BRLCAD_ERROR;
2624  }
2625  } else if (BU_STR_EQUAL(argv[0], "VL")) {
2626  fastf_t *new_verts=(fastf_t *)NULL;
2627  int len;
2628  char *ptr;
2629  char *dupstr;
2630 
2631  /* the vertex list is a list of lists (each element is a
2632  * list of two coordinates) so eliminate all the '{' and
2633  * '}' chars in the list
2634  */
2635  dupstr = bu_strdup(argv[1]);
2636 
2637  ptr = dupstr;
2638  while (*ptr != '\0') {
2639  if (*ptr == '{' || *ptr == '}')
2640  *ptr = ' ';
2641  ptr++;
2642  }
2643 
2644  len = 0;
2645  (void)tcl_list_to_fastf_array(brlcad_interp, dupstr, &new_verts, &len);
2646  bu_free(dupstr, "sketch adjust strdup");
2647 
2648  if (len%2) {
2649  bu_vls_printf(logstr, "ERROR: Incorrect number of coordinates for vertices\n");
2650  return BRLCAD_ERROR;
2651  }
2652 
2653  if (skt->verts)
2654  bu_free((char *)skt->verts, "verts");
2655  skt->verts = (point2d_t *)new_verts;
2656  skt->vert_count = len / 2;
2657  } else if (BU_STR_EQUAL(argv[0], "SL")) {
2658  /* the entire segment list */
2659  Tcl_Obj *tmp;
2660  struct rt_curve *crv;
2661 
2662  /* create a Tcl object */
2663  tmp = Tcl_NewStringObj(argv[1], -1);
2664 
2665  crv = &skt->curve;
2666  crv->count = 0;
2667  crv->reverse = (int *)NULL;
2668  crv->segment = (void **)NULL;
2669 
2670  if ((ret=get_tcl_curve(brlcad_interp, crv, tmp)) != TCL_OK)
2671  return ret;
2672  } else if (*argv[0] == 'V' && isdigit((int)*(argv[0]+1))) {
2673  /* changing a specific vertex */
2674  long vert_no;
2675  fastf_t *new_vert;
2676 
2677  vert_no = atol(argv[0] + 1);
2678  new_vert = skt->verts[vert_no];
2679  if (vert_no < 0 || (size_t)vert_no > skt->vert_count) {
2680  bu_vls_printf(logstr, "ERROR: Illegal vertex number\n");
2681  return BRLCAD_ERROR;
2682  }
2683  array_len = 2;
2684  if (tcl_list_to_fastf_array(brlcad_interp, argv[1], &new_vert, &array_len) != array_len) {
2685  bu_vls_printf(logstr, "ERROR: Incorrect number of coordinates for vertex\n");
2686  return BRLCAD_ERROR;
2687  }
2688  }
2689 
2690  argc -= 2;
2691  argv += 2;
2692  }
2693 
2694  return BRLCAD_OK;
2695 }
2696 
2697 
2698 int
2699 rt_sketch_params(struct pc_pc_set *UNUSED(ps), const struct rt_db_internal *ip)
2700 {
2701  if (ip) RT_CK_DB_INTERNAL(ip);
2702 
2703  return 0; /* OK */
2704 }
2705 
2706 
2707 void
2709 {
2710  struct line_seg *lsg;
2711  struct carc_seg *csg;
2712  struct bezier_seg *bsg;
2713  int tmp, i;
2714 
2715  switch (*lng) {
2716  case CURVE_LSEG_MAGIC:
2717  lsg = (struct line_seg *)lng;
2718  tmp = lsg->start;
2719  lsg->start = lsg->end;
2720  lsg->end = tmp;
2721  break;
2722  case CURVE_CARC_MAGIC:
2723  csg = (struct carc_seg *)lng;
2724  if (csg->radius < 0.0) {
2725  /* this is a full circle */
2726  csg->orientation = !csg->orientation; /* no real effect, but just for completeness */
2727  } else {
2728  tmp = csg->start;
2729  csg->start = csg->end;
2730  csg->end = tmp;
2731  csg->center_is_left = !csg->center_is_left;
2732  csg->orientation = !csg->orientation;
2733  }
2734  break;
2735  case CURVE_BEZIER_MAGIC:
2736  bsg = (struct bezier_seg *)lng;
2737  for (i=0; i<bsg->degree/2; i++) {
2738  tmp = bsg->ctl_points[i];
2739  bsg->ctl_points[i] = bsg->ctl_points[bsg->degree-i];
2740  bsg->ctl_points[bsg->degree-i] = tmp;
2741  }
2742  break;
2743  }
2744 }
2745 
2746 
2747 void
2748 rt_curve_order_segments(struct rt_curve *crv)
2749 {
2750  int i, j, k;
2751  int count;
2752  int start1, end1, start2, end2, start3, end3;
2753 
2754  count = crv->count;
2755  if (count < 2) {
2756  return;
2757  }
2758 
2759  for (j=1; j<count; j++) {
2760  int tmp_reverse;
2761  void *tmp_seg;
2762  int fixed=0;
2763 
2764  i = j - 1;
2765 
2766  get_indices(crv->segment[i], &start1, &end1);
2767  get_indices(crv->segment[j], &start2, &end2);
2768 
2769  if (end1 == start2)
2770  continue;
2771 
2772  for (k=j+1; k<count; k++) {
2773  get_indices(crv->segment[k], &start3, &end3);
2774  if (start3 != end1)
2775  continue;
2776 
2777  /* exchange j and k segments */
2778  tmp_seg = crv->segment[j];
2779  crv->segment[j] = crv->segment[k];
2780  crv->segment[k] = tmp_seg;
2781 
2782  tmp_reverse = crv->reverse[j];
2783  crv->reverse[j] = crv->reverse[k];
2784  crv->reverse[k] = tmp_reverse;
2785  fixed = 1;
2786  break;
2787  }
2788 
2789  if (fixed)
2790  continue;
2791 
2792  /* try reversing a segment */
2793  for (k=j; k<count; k++) {
2794  get_indices(crv->segment[k], &start3, &end3);
2795  if (end3 != end1)
2796  continue;
2797 
2798  rt_curve_reverse_segment((uint32_t *)crv->segment[k]);
2799 
2800  if (k != j) {
2801  /* exchange j and k segments */
2802  tmp_seg = crv->segment[j];
2803  crv->segment[j] = crv->segment[k];
2804  crv->segment[k] = tmp_seg;
2805 
2806  tmp_reverse = crv->reverse[j];
2807  crv->reverse[j] = crv->reverse[k];
2808  crv->reverse[k] = tmp_reverse;
2809  }
2810  fixed = 1;
2811  break;
2812  }
2813  }
2814 }
2815 
2816 
2817 /*
2818  * Local Variables:
2819  * mode: C
2820  * tab-width: 8
2821  * indent-tabs-mode: t
2822  * c-file-style: "stroustrup"
2823  * End:
2824  * ex: shiftwidth=4 tabstop=8
2825  */
Definition: raytrace.h:800
#define RT_CK_FUNCTAB(_p)
Definition: raytrace.h:2242
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define SIZEOF_NETWORK_DOUBLE
Definition: cv.h:48
int rt_sketch_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: sketch.c:1497
Definition: list.h:118
ustring interp
#define BU_DEBUG_MEM_CHECK
Definition: debug.h:54
void rt_sketch_norm(struct hit *hitp, struct soltab *stp, struct xray *rp)
Definition: sketch.c:186
int rt_sketch_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: sketch.c:887
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
#define RT_CK_RTI(_p)
Definition: raytrace.h:1833
int curve_to_vlist(struct bu_list *vhead, const struct rt_tess_tol *ttol, fastf_t *V, fastf_t *u_vec, fastf_t *v_vec, struct rt_sketch_internal *sketch_ip, struct rt_curve *crv)
Definition: sketch.c:861
vect_t crv_pdir
Principle direction.
Definition: raytrace.h:307
const mat_t bn_mat_identity
Matrix and vector functionality.
Definition: mat.c:46
void rt_sketch_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
Definition: sketch.c:225
int seg_to_vlist(struct bu_list *vhead, const struct rt_tess_tol *ttol, fastf_t *V, fastf_t *u_vec, fastf_t *v_vec, struct rt_sketch_internal *sketch_ip, void *seg)
Definition: sketch.c:469
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
#define VSETALL(a, s)
Definition: color.c:54
Definition: raytrace.h:215
Definition: nmg_tri.c:75
#define SIZEOF_NETWORK_LONG
Definition: cv.h:46
Definition: pc.h:108
Definition: raytrace.h:368
#define CURVE_CARC_MAGIC
Definition: magic.h:198
Definition: raytrace.h:248
#define SMALL_FASTF
Definition: defines.h:342
Header file for the BRL-CAD common definitions.
int rt_sketch_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
Definition: sketch.c:1103
void rt_sketch_bounds(struct rt_sketch_internal *sk, fastf_t *bounds)
Definition: sketch.c:355
int rt_sketch_get(struct bu_vls *logstr, const struct rt_db_internal *intern, const char *attr)
Definition: sketch.c:2352
#define RT_CK_RAY(_p)
Definition: raytrace.h:224
fastf_t rt_cnurb_par_edge(const struct edge_g_cnurb *crv, fastf_t epsilon)
Definition: nurb_tess.c:154
#define CURVE_NURB_MAGIC
Definition: magic.h:200
void bu_cv_htond(unsigned char *out, const unsigned char *in, size_t count)
void rt_sketch_ifree(struct rt_db_internal *ip)
Definition: sketch.c:2142
#define MAX_FASTF
Definition: defines.h:340
void rt_curve_free(struct rt_curve *crv)
Definition: sketch.c:2092
void rt_sketch_free(struct soltab *stp)
Definition: sketch.c:236
#define CURVE_BEZIER_MAGIC
Definition: magic.h:197
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
double rel
rel dist tol
Definition: raytrace.h:181
int rt_check_curve(const struct rt_curve *crv, const struct rt_sketch_internal *skt, int noisy)
Definition: sketch.c:56
if(share_geom)
Definition: nmg_mod.c:3829
int idb_major_type
Definition: raytrace.h:192
Definition: color.c:49
#define BU_CK_VLS(_vp)
Definition: vls.h:69
int get_tcl_curve(Tcl_Interp *interp, struct rt_curve *crv, Tcl_Obj *seg_list)
Definition: sketch.c:2407
#define RT_ADD_VLIST(hd, pnt, draw)
Definition: raytrace.h:1865
#define RT_CK_DB_INTERNAL(_p)
Definition: raytrace.h:207
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
fastf_t crv_c2
curvature in other direction
Definition: raytrace.h:309
#define RT_CK_HIT(_p)
Definition: raytrace.h:259
int rt_sketch_degree(struct rt_sketch_internal *sk)
Definition: sketch.c:428
#define BN_VLIST_LINE_MOVE
Definition: vlist.h:82
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
void rt_sketch_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
Definition: sketch.c:203
#define V3ARGS(a)
Definition: color.c:56
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
#define BRLCAD_OK
Definition: defines.h:71
uint8_t * ext_buf
Definition: parse.h:216
point_t hit_point
DEPRECATED: Intersection point, use VJOIN1 hit_dist.
Definition: raytrace.h:251
int rt_sketch_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: sketch.c:1295
#define BN_VLIST_LINE_DRAW
Definition: vlist.h:83
void get_indices(void *seg, int *start, int *end)
Definition: extrude.c:1501
int rt_sketch_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
Definition: sketch.c:136
oldeumate l2 magic
Definition: nmg_mod.c:3843
#define UNUSED(parameter)
Definition: common.h:239
goto out
Definition: nmg_mod.c:3846
int rt_sketch_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
Definition: sketch.c:1090
Support for uniform tolerances.
Definition: tol.h:71
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
int rt_sketch_form(struct bu_vls *logstr, const struct rt_functab *ftp)
Definition: sketch.c:2340
int bu_mem_barriercheck(void)
Definition: malloc.c:660
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
int rt_sketch_shot(struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead)
Definition: sketch.c:165
int rt_sketch_adjust(struct bu_vls *logstr, struct rt_db_internal *intern, int argc, const char **argv)
Definition: sketch.c:2590
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
int curve_to_tcl_list(struct bu_vls *vls, struct rt_curve *crv)
Definition: sketch.c:2283
int tcl_obj_to_fastf_array(Tcl_Interp *interp, Tcl_Obj *list, fastf_t **array, int *array_len)
Definition: tcl.c:802
int bu_debug
Definition: globals.c:87
#define BU_LIST_INIT(_hp)
Definition: list.h:148
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
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 NMG_EDGE_G_CNURB_MAGIC
Definition: magic.h:121
void bn_vec_ortho(vect_t out, const vect_t in)
void rt_copy_curve(struct rt_curve *crv_out, const struct rt_curve *crv_in)
Definition: sketch.c:2176
#define FMAX(a, b)
Definition: common.h:102
void rt_sketch_centroid(point_t *cent, const struct rt_db_internal *ip)
Definition: sketch.c:1036
double abs
absolute dist tol
Definition: raytrace.h:180
#define RT_CK_SOLTAB(_p)
Definition: raytrace.h:453
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
#define RT_SKETCH_INTERNAL_MAGIC
Definition: magic.h:108
int rt_sketch_contains(struct rt_sketch_internal *sk, point2d_t pt)
Definition: sketch.c:253
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
void rt_sketch_print(const struct soltab *stp)
Definition: sketch.c:150
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
double norm
normal tol
Definition: raytrace.h:182
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
void rt_nurb_c_eval(const struct edge_g_cnurb *crv, fastf_t param, fastf_t *final_value)
Definition: nurb_eval.c:125
void rt_curve_reverse_segment(uint32_t *lng)
Definition: sketch.c:2708
void rt_curve_order_segments(struct rt_curve *crv)
Definition: sketch.c:2748
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
size_t ext_nbytes
Definition: parse.h:210
int rt_sketch_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
Definition: sketch.c:1686
#define CURVE_LSEG_MAGIC
Definition: magic.h:199
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
int rt_sketch_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
Definition: sketch.c:1899
#define BRLCAD_ERROR
Definition: defines.h:72
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
HIDDEN const point_t delta
Definition: sh_prj.c:618
double fastf_t
Definition: defines.h:300
int rt_sketch_params(struct pc_pc_set *ps, const struct rt_db_internal *ip)
Definition: sketch.c:2699
#define ID_SKETCH
2D sketch
Definition: raytrace.h:484
Tcl_Interp * brlcad_interp
Definition: tcl.c:41
int tcl_obj_to_int_array(Tcl_Interp *interp, Tcl_Obj *list, int **array, int *array_len)
Definition: tcl.c:762
struct bezier_2d_list * bezier_subdivide(struct bezier_2d_list *bezier_in, int degree, fastf_t epsilon, int depth)
Definition: bezier.c:405
Definition: color.c:50
#define BU_LIST_FIRST(structure, hp)
Definition: list.h:312
#define bu_strdup(s)
Definition: str.h:71
#define FMIN(a, b)
Definition: common.h:105
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126