BRL-CAD
tire.c
Go to the documentation of this file.
1 /* T I R E . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-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 /** @file libged/tire.c
21  *
22  * Tire Generator
23  *
24  * Program to create basic tire shapes.
25  */
26 
27 #include "common.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 
34 #include "bu/getopt.h"
35 #include "bu/units.h"
36 #include "vmath.h"
37 #include "bn.h"
38 #include "raytrace.h"
39 #include "wdb.h"
40 #include "ged.h"
41 
42 #define D2R(x) (x * DEG2RAD)
43 #define R2D(x) (x / DEG2RAD)
44 
45 #define ROWS 5
46 #define COLS 5
47 
48 static char *options="an:c:d:W:R:D:g:j:p:s:t:u:w:h?";
49 
50 /**
51  * Help message printed when -h option is supplied
52  */
53 static void
54 show_help(struct ged *gedp, const char *name)
55 {
56  struct bu_vls str = BU_VLS_INIT_ZERO;
57  const char *cp = options;
58 
59  while (cp && *cp != '\0') {
60  if (*cp == ':' || *cp == 'h' || *cp == '?') {
61  cp++;
62  continue;
63  }
64  bu_vls_strncat(&str, cp, 1);
65  cp++;
66  }
67 
68  bu_vls_printf(gedp->ged_result_str, "Usage: %s [-%s] [tire_name]\n", name, bu_vls_addr(&str));
69  bu_vls_printf(gedp->ged_result_str, "options:\n");
70  bu_vls_printf(gedp->ged_result_str, "\t-a\n\t\tAuto-generate top-level object name using\n");
71  bu_vls_printf(gedp->ged_result_str, "\t\ttire-<width>-<aspect>R<rim diameter>\n");
72  bu_vls_printf(gedp->ged_result_str, "\t\t(\"tire\" overridden by -n argument, and ultimately by tire_name , if that is supplied)\n");
73  bu_vls_printf(gedp->ged_result_str, "\t\t(rest of name is derived from the ISO Metric system)\n");
74  bu_vls_printf(gedp->ged_result_str, "\t-n <name>\n\t\tSpecify custom top-level object name\n");
75  bu_vls_printf(gedp->ged_result_str, "\t\t(overridden by tire_name , if that is supplied)\n");
76  bu_vls_printf(gedp->ged_result_str, "\t-c <count>\n\t\tSpecify number of tread patterns around tire\n");
77  bu_vls_printf(gedp->ged_result_str, "\t-d <width>/<aspect>R<rim diameter>\n\t\tSpecify tire dimensions\n");
78  bu_vls_printf(gedp->ged_result_str, "\t\t(U.S. customary units in the ISO metric system; integer values only)\n");
79  bu_vls_printf(gedp->ged_result_str, "\t-W <width>\n\t\tSpecify tire width in inches (overrides -d)\n");
80  bu_vls_printf(gedp->ged_result_str, "\t-R <aspect>\n\t\tSpecify tire aspect ratio (#/100) (overrides -d)\n");
81  bu_vls_printf(gedp->ged_result_str, "\t-D <rim diameter>\n\t\tSpecify rim diameter in inches (overrides -d)\n");
82  bu_vls_printf(gedp->ged_result_str, "\t-g <depth>\n\t\tSpecify tread depth in 32nds of an inch\n");
83  bu_vls_printf(gedp->ged_result_str, "\t-j <width>\n\t\tSpecify rim width in inches\n");
84  bu_vls_printf(gedp->ged_result_str, "\t-p <type>\n\t\tGenerate tread with tread pattern as specified\n");
85  bu_vls_printf(gedp->ged_result_str, "\t-s <radius>\n\t\tSpecify radius of the maximum sidewall width, in mm\n");
86  bu_vls_printf(gedp->ged_result_str, "\t-t <type>\n\t\tGenerate tread with tread type as specified\n");
87  bu_vls_printf(gedp->ged_result_str, "\t-u <thickness>\n\t\tSpecify tire thickness in mm\n");
88  bu_vls_printf(gedp->ged_result_str, "\t-w <0|1>\n\t\tWhether to include the wheel or not (default is 1, yes)\n");
89 
90  bu_vls_free(&str);
91  return;
92 }
93 
94 
95 /**
96  * Return matrix needed to rotate an object around the y axis by theta
97  * degrees
98  */
99 static void
100 getYRotMat(mat_t (*t), fastf_t theta)
101 {
102  fastf_t sin_ = sin(theta);
103  fastf_t cos_ = cos(theta);
104  mat_t r;
105  MAT_ZERO(r);
106  r[0] = cos_;
107  r[2] = sin_;
108  r[5] = 1;
109  r[8] = -sin_;
110  r[10] = cos_;
111  r[15] = 1;
112  memcpy(*t, r, sizeof(*t));
113 }
114 
115 
116 /**********************************************************************
117  * *
118  * Explicit Solvers for Ellipse Equations *
119  * *
120  **********************************************************************/
121 
122 
123 /**
124  * Evaluate Partial Derivative of Ellipse Equation at a point
125  */
126 static fastf_t
127 GetEllPartialAtPoint(fastf_t *inarray, fastf_t x, fastf_t y)
128 {
129  fastf_t A, B, C, D, E, partial;
130  A = inarray[0];
131  B = inarray[1];
132  C = inarray[2];
133  D = inarray[3];
134  E = inarray[4];
135  partial = -(D + y * B + 2 * x * A) / (E + 2 * y * C + x * B);
136  return partial;
137 }
138 
139 
140 /**
141  * Evaluate z value of Ellipse Equation at a point
142  */
143 static fastf_t
144 GetValueAtZPoint(fastf_t *inarray, fastf_t y)
145 {
146  fastf_t A, B, C, D, E, F, z;
147  A = inarray[0];
148  B = inarray[1];
149  C = inarray[2];
150  D = inarray[3];
151  E = inarray[4];
152  F = 1;
153  z = (sqrt(-4 * A * F - 4 * y * A * E + D * D + 2 * y * B * D - 4 * y * y * A * C + y * y * B * B) - D - y * B) / (2 * A);
154  return z;
155 }
156 
157 
158 /**********************************************************************
159  * *
160  * Matrix Definitions for General Conic *
161  * Equations. *
162  * *
163  **********************************************************************/
164 
165 
166 /**
167  * Create General Conic Matrix for Ellipse describing tire slick
168  * (non-tread) surfaces
169  */
170 static void
171 Create_Ell1_Mat(fastf_t **mat, fastf_t dytred, fastf_t dztred, fastf_t d1, fastf_t ztire)
172 {
173  fastf_t y_1, z_1, y_2, z_2, y_3, z_3, y_4, z_4, y_5, z_5;
174 
175  y_1 = dytred / 2;
176  z_1 = ztire - dztred;
177  y_2 = dytred / 2;
178  z_2 = ztire - (dztred + 2 * (d1 - dztred));
179  y_3 = 0.0;
180  z_3 = ztire;
181  y_4 = 0.0;
182  z_4 = ztire - 2 * d1;
183  y_5 = -dytred / 2;
184  z_5 = ztire - dztred;
185 
186  mat[0][0] = y_1 * y_1;
187  mat[0][1] = y_1 * z_1;
188  mat[0][2] = z_1 * z_1;
189  mat[0][3] = y_1;
190  mat[0][4] = z_1;
191  mat[0][5] = -1;
192  mat[1][0] = y_2 * y_2;
193  mat[1][1] = y_2 * z_2;
194  mat[1][2] = z_2 * z_2;
195  mat[1][3] = y_2;
196  mat[1][4] = z_2;
197  mat[1][5] = -1;
198  mat[2][0] = y_3 * y_3;
199  mat[2][1] = y_3 * z_3;
200  mat[2][2] = z_3 * z_3;
201  mat[2][3] = y_3;
202  mat[2][4] = z_3;
203  mat[2][5] = -1;
204  mat[3][0] = y_4 * y_4;
205  mat[3][1] = y_4 * z_4;
206  mat[3][2] = z_4 * z_4;
207  mat[3][3] = y_4;
208  mat[3][4] = z_4;
209  mat[3][5] = -1;
210  mat[4][0] = y_5 * y_5;
211  mat[4][1] = y_5 * z_5;
212  mat[4][2] = z_5 * z_5;
213  mat[4][3] = y_5;
214  mat[4][4] = z_5;
215  mat[4][5] = -1;
216 }
217 
218 
219 /**
220  * Create General Conic Matrix for Ellipse describing the top part of
221  * the tire side
222  *
223  * Note: zside1 is the z height of the maximum tire width
224  *
225  * This is the most complex of the required solutions. There are four
226  * constraints used that result in five equations:
227  * 1. Equality of the new ellipse with the ellipse defining the top surface
228  * at the intersection,
229  * 2. Equality of the partial derivative of the new ellipse with the
230  * partial derivative of the top surface ellipse at
231  * the point of intersection,
232  * 3. The new ellipse must intersect the point zside1, dyside1/2
233  * 4. The new ellipse must have its maximum y value equal to dyside1/2.
234  *
235  * The last constraint does not directly provide an instance of the
236  * general conic equation that can be used, but we use the fact that
237  * an ellipse is symmetric about that point plus the fact that conditions
238  * one and two give us a point and a partial derivative on the ellipse
239  * allow for the definition of two more equations. First, the symmetric
240  * intersection point's y and z values must be found. The y value is the
241  * same y value as the y value at intersection. To find that value, we
242  * first define the magnitude of the z component of the distance from
243  * the intersection point to the max point as:
244  *
245  * ztire - dztred - zside1
246  *
247  * That will place the symmetric point at twice this distance down the
248  * z axis from the intersection point:
249  *
250  * (ztire - dztred) - 2 * (ztire - dztred - zside1)
251  *
252  * Simplifying, that gives the expression:
253  *
254  * 2 * zside1 - ztire + dztred
255  *
256  * Knowing this point must be on the ellipse, and the partial derivative
257  * is constrained to be the negative of the partial derivative at the
258  * intersection point, five equations are now known and the conic equation
259  * coefficients can be found.
260  *
261  */
262 static void
263 Create_Ell2_Mat(fastf_t **mat, fastf_t dytred, fastf_t dztred,
264  fastf_t dyside1, fastf_t zside1, fastf_t ztire,
265  fastf_t UNUSED(dyhub), fastf_t UNUSED(zhub), fastf_t ell1partial)
266 {
267  mat[0][0] = (dyside1 / 2) * (dyside1 / 2);
268  mat[0][1] = (zside1 * dyside1 / 2);
269  mat[0][2] = zside1 * zside1;
270  mat[0][3] = dyside1 / 2;
271  mat[0][4] = zside1;
272  mat[0][5] = -1;
273  mat[1][0] = (dytred / 2) * (dytred / 2);
274  mat[1][1] = (ztire - dztred) * (dytred / 2);
275  mat[1][2] = (ztire - dztred) * (ztire - dztred);
276  mat[1][3] = (dytred / 2);
277  mat[1][4] = (ztire - dztred);
278  mat[1][5] = -1;
279  mat[2][0] = (dytred / 2) * (dytred / 2);
280  mat[2][1] = (dytred / 2) * (2 * zside1 - ztire + dztred);
281  mat[2][2] = (2 * zside1 - ztire + dztred) * (2 * zside1 - ztire + dztred);
282  mat[2][3] = (dytred / 2);
283  mat[2][4] = (2 * zside1 - ztire + dztred);
284  mat[2][5] = -1;
285  mat[3][0] = 2 * (dytred / 2);
286  mat[3][1] = (ztire - dztred) + (dytred / 2) * ell1partial;
287  mat[3][2] = 2 * (ztire - dztred) * ell1partial;
288  mat[3][3] = 1;
289  mat[3][4] = ell1partial;
290  mat[3][5] = 0;
291  mat[4][0] = 2 * (dytred / 2);
292  mat[4][1] = (2 * zside1 - ztire + dztred) + (dytred / 2) * -ell1partial;
293  mat[4][2] = 2 * (2 * zside1 - ztire + dztred) * -ell1partial;
294  mat[4][3] = 1;
295  mat[4][4] = -ell1partial;
296  mat[4][5] = 0;
297 }
298 
299 
300 /**
301  * Create General Conic Matrix for Ellipse describing the bottom part
302  * of the tire side.
303  *
304  * This ellipse is used to define the surface for both sides of the
305  * tire, so it uses symmetry about the z axis to define four of its points.
306  * The fifth is defined by mandating that the point at dyside1/2, zside1 be
307  * a maximum, and using the additional symmetry requirements. This ensures
308  * both that the maximum tire width is respected and that the transition from
309  * the top ellipse(s) to the bottom one is smooth.
310  */
311 static void
312 Create_Ell3_Mat(fastf_t **mat, fastf_t UNUSED(dytred), fastf_t UNUSED(dztred),
313  fastf_t dyside1, fastf_t zside1, fastf_t UNUSED(ztire),
314  fastf_t dyhub, fastf_t zhub, fastf_t UNUSED(ell1partial))
315 {
316  mat[0][0] = (dyside1 / 2) * (dyside1 / 2);
317  mat[0][1] = (zside1 * dyside1 / 2);
318  mat[0][2] = zside1 * zside1;
319  mat[0][3] = dyside1 / 2;
320  mat[0][4] = zside1;
321  mat[0][5] = -1;
322  mat[1][0] = (dyhub / 2) * (dyhub / 2);
323  mat[1][1] = (zhub) * (dyhub / 2);
324  mat[1][2] = (zhub) * (zhub);
325  mat[1][3] = (dyhub / 2);
326  mat[1][4] = (zhub);
327  mat[1][5] = -1;
328  mat[2][0] = (dyhub / 2) * (dyhub / 2);
329  mat[2][1] = (dyhub / 2) * (2 * zside1 - zhub);
330  mat[2][2] = (2 * zside1 - zhub) * (2 * zside1 - zhub);
331  mat[2][3] = (dyhub / 2);
332  mat[2][4] = (2 * zside1 - zhub);
333  mat[2][5] = -1;
334  mat[3][0] = -(dyside1 / 2) * -(dyside1 / 2);
335  mat[3][1] = (zside1 * -dyside1 / 2);
336  mat[3][2] = zside1 * zside1;
337  mat[3][3] = -dyside1 / 2;
338  mat[3][4] = zside1;
339  mat[3][5] = -1;
340  mat[4][0] = -(dyhub / 2) * -(dyhub / 2);
341  mat[4][1] = (zhub) * -(dyhub / 2);
342  mat[4][2] = (zhub) * (zhub);
343  mat[4][3] = -(dyhub / 2);
344  mat[4][4] = (zhub);
345  mat[4][5] = -1;
346 }
347 
348 
349 /**********************************************************************
350  * *
351  * Matrix Routines for Solving General *
352  * Conic Equations. *
353  * *
354  **********************************************************************/
355 
356 
357 /**
358  * Sort Rows of 5x6 matrix - for use in Gaussian Elimination
359  */
360 static void
361 SortRows(fastf_t **mat, int colnum)
362 {
363  int high_row, exam_row;
364  int colcount;
365  fastf_t temp_elem;
366  high_row = colnum;
367  for (exam_row = high_row + 1; exam_row < 5; exam_row++) {
368  if (fabs(mat[exam_row][colnum]) > fabs(mat[high_row][colnum]))
369  high_row = exam_row;
370  }
371  if (high_row != colnum) {
372  for (colcount = colnum; colcount < 6; colcount++) {
373  temp_elem = mat[colnum][colcount];
374  mat[colnum][colcount] = mat[high_row][colcount];
375  mat[high_row][colcount] = temp_elem;
376  }
377  }
378 }
379 
380 
381 /**
382  * Convert 5x6 matrix to Reduced Echelon Form
383  */
384 static void
385 Echelon(fastf_t **mat)
386 {
387  int i, j, k;
388  fastf_t pivot, rowmult;
389  for (i = 0; i < 5; i++) {
390  SortRows(mat, i);
391  pivot = mat[i][i];
392  for (j = i; j < 6; j++) {
393  mat[i][j] = mat[i][j] / pivot;
394  }
395  for (k = i + 1; k < 5 ; k++) {
396  rowmult = mat[k][i];
397  for (j = i; j < 6; j++) {
398  mat[k][j] -= rowmult * mat[i][j];
399  }
400  }
401  }
402 }
403 
404 
405 /**
406  * Take Reduced Echelon form of Matrix and solve for General Conic
407  * Coefficients
408  */
409 static void
410 SolveEchelon(fastf_t **mat, fastf_t *result1)
411 {
412  int i, j;
413  fastf_t inter;
414  for (i = 4; i >= 0; i--) {
415  inter = mat[i][5];
416  for (j = 4; j > i; j--)
417  inter -= mat[i][j] * result1[j];
418  result1[i]=inter;
419  }
420 }
421 
422 
423 /**********************************************************************
424  * *
425  * Convert General Conic Equation *
426  * Coefficients to BRL-CAD eto input *
427  * Parameters *
428  * *
429  * Note: The general procedure here is to rotate and translate *
430  * the general conic equation into a form where the various *
431  * geometric parameters may be more easily obtained. The solution *
432  * below is probably neither unique nor optimal, but appears to *
433  * function in most "common" tire cases. To explore the problem *
434  * start by looking into methods of graphing the General Conic. *
435  * In particular, either here or even earlier in the process a *
436  * type check should be done to ensure an elliptical geometry has *
437  * been found, rather than parabolic or hyperbolic. *
438  * *
439  **********************************************************************/
440 static void
441 CalcInputVals(fastf_t *inarray, fastf_t *outarray)
442 {
443  fastf_t A, B, C, D, E, Fp;
444  fastf_t App, Cpp;
445  fastf_t x_0, y_0;
446  fastf_t theta;
447  fastf_t length1, length2;
448  fastf_t semiminor;
449  fastf_t semimajorx, semimajory;
450 
451  A = inarray[0];
452  B = inarray[1];
453  C = inarray[2];
454  D = inarray[3];
455  E = inarray[4];
456 
457  /* Translation to Center of Ellipse */
458  x_0 = -(B * E - 2 * C * D) / (4 * A * C - B * B);
459  y_0 = -(B * D - 2 * A * E) / (4 * A * C - B * B);
460 
461  /* Translate to the Origin for Rotation */
462  Fp = 1 - y_0 * E - x_0 * D + y_0 * y_0 * C+x_0 * y_0 * B + x_0 * x_0 * A;
463 
464  /* Rotation Angle */
465  theta = .5 * atan(1000 * B / (1000 * A - 1000 * C));
466 
467  /* Calculate A'', B'' and C'' - B'' is zero with above theta choice */
468  App = A * cos(theta) * cos(theta) + B * cos(theta) * sin(theta) + C * sin(theta) * sin(theta);
469  /* Bpp = 2 * (C - A) * cos(theta) * sin(theta) + B * cos(theta) * cos(theta) - B * sin(theta) * sin(theta); */
470  Cpp = A * sin(theta) * sin(theta) - B * sin(theta) * cos(theta) + C * cos(theta) * cos(theta);
471 
472  /* Solve for semimajor and semiminor lengths*/
473  length1 = sqrt(-Fp / App);
474  length2 = sqrt(-Fp / Cpp);
475 
476  /* BRL-CAD's eto primitive requires that C is the semimajor */
477  if (length1 > length2) {
478  semimajorx = length1 * cos(-theta);
479  semimajory = length1 * sin(-theta);
480  semiminor = length2;
481  } else {
482  semimajorx = length2 * sin(-theta);
483  semimajory = length2 * cos(-theta);
484  semiminor = length1;
485  }
486 
487  /* Return final BRL-CAD input parameters */
488  outarray[0] = -x_0;
489  outarray[1] = -y_0;
490  outarray[2] = semimajorx;
491  outarray[3] = semimajory;
492  outarray[4] = semiminor;
493 }
494 
495 
496 /**********************************************************************
497  * *
498  * Create Wheel Structure to fit *
499  * Specified Tire Parameters *
500  * *
501  **********************************************************************/
502 static void
503 MakeWheelCenter(struct rt_wdb (*file), char *suffix,
504  fastf_t fixing_start_middle, fastf_t fixing_width,
505  fastf_t rim_thickness, fastf_t bead_height, fastf_t zhub,
506  fastf_t dyhub, fastf_t spigot_diam, int bolts,
507  fastf_t bolt_circ_diam, fastf_t bolt_diam)
508 {
509  vect_t height, a, b, c;
510  point_t origin, vertex;
511  mat_t y;
512  struct bu_vls str = BU_VLS_INIT_ZERO;
513  int i;
514  struct wmember bolthole, boltholes, hubhole, hubholes, innerhub;
515 
516  bu_vls_sprintf(&str, "Inner-Hub%s.s", suffix);
517  VSET(origin, 0, fixing_start_middle + fixing_width / 4, 0);
518  VSET(a, (zhub - 2 * bead_height), 0, 0);
519  VSET(b, 0, -dyhub / 3, 0);
520  VSET(c, 0, 0, (zhub - 2 * bead_height));
521  mk_ell(file, bu_vls_addr(&str), origin, a, b, c);
522 
523  bu_vls_sprintf(&str, "Inner-Hub-Cut1%s.s", suffix);
524  VSET(origin, 0, fixing_start_middle + fixing_width / 4 - rim_thickness * 1.5, 0);
525  mk_ell(file, bu_vls_addr(&str), origin, a, b, c);
526 
527  VSET(origin, 0, 0, 0);
528  VSET(height, 0, dyhub / 2, 0);
529  bu_vls_sprintf(&str, "Inner-Hub-Cut2%s.s", suffix);
530  mk_rcc(file, bu_vls_addr(&str), origin, height, spigot_diam / 2);
531 
532  /* Make the circular pattern of holes in the hub - this involves
533  * the creation of one primitive, a series of transformed
534  * combinations which use that primitive, and a combination
535  * combining all of the previous combinations. Since it requires
536  * both primitives and combinations it is placed between the two
537  * sections.
538  */
539 
540  VSET(vertex, 0, 0, (zhub - (bolt_circ_diam / 2 + bolt_diam / 2)) / 1.25);
541  VSET(height, 0, dyhub / 2, 0);
542  bu_vls_sprintf(&str, "Hub-Hole%s.s", suffix);
543  mk_rcc(file, bu_vls_addr(&str), vertex, height,
544  (zhub - (bolt_circ_diam / 2 + bolt_diam / 2)) / 6.5);
545 
546 
547  BU_LIST_INIT(&hubhole.l);
548  BU_LIST_INIT(&hubholes.l);
549  for (i = 1; i <= 10; i++) {
550  bu_vls_sprintf(&str, "Hub-Hole%s.s", suffix);
551  getYRotMat(&y, D2R(i * 360 / 10));
552  (void)mk_addmember(bu_vls_addr(&str), &hubhole.l, y, WMOP_UNION);
553  bu_vls_sprintf(&str, "Hub-Hole-%1.0d%s.c", i, suffix);
554  mk_lcomb(file, bu_vls_addr(&str), &hubhole, 0, NULL, NULL, NULL, 0);
555  (void)mk_addmember(bu_vls_addr(&str), &hubholes.l, NULL, WMOP_UNION);
556  (void)BU_LIST_POP_T(&hubhole.l, struct wmember);
557  }
558  bu_vls_sprintf(&str, "Hub-Holes%s.c", suffix);
559  mk_lcomb(file, bu_vls_addr(&str), &hubholes, 0, NULL, NULL, NULL, 0);
560 
561  /* Make the bolt holes in the hub */
562 
563  VSET(vertex, 0, 0, bolt_circ_diam / 2);
564  VSET(height, 0, dyhub / 2, 0);
565  bu_vls_sprintf(&str, "Bolt-Hole%s.s", suffix);
566  mk_rcc(file, bu_vls_addr(&str), vertex, height, bolt_diam / 2);
567 
568 
569  BU_LIST_INIT(&bolthole.l);
570  BU_LIST_INIT(&boltholes.l);
571  for (i = 1; i <= bolts; i++) {
572  bu_vls_sprintf(&str, "Bolt-Hole%s.s", suffix);
573  getYRotMat(&y, D2R(i * 360 / bolts));
574  (void)mk_addmember(bu_vls_addr(&str), &bolthole.l, y, WMOP_UNION);
575  bu_vls_sprintf(&str, "Bolt-Hole-%1.0d%s.c", i, suffix);
576  mk_lcomb(file, bu_vls_addr(&str), &bolthole, 0, NULL, NULL, NULL, 0);
577  (void)mk_addmember(bu_vls_addr(&str), &boltholes.l, NULL, WMOP_UNION);
578  (void)BU_LIST_POP_T(&bolthole.l, struct wmember);
579  }
580  bu_vls_sprintf(&str, "Bolt-Holes%s.c", suffix);
581  mk_lcomb(file, bu_vls_addr(&str), &boltholes, 0, NULL, NULL, NULL, 0);
582 
583  /* Make combination for Inner-Hub */
584 
585  BU_LIST_INIT(&innerhub.l);
586  bu_vls_sprintf(&str, "Inner-Hub%s.s", suffix);
587  (void)mk_addmember(bu_vls_addr(&str), &innerhub.l, NULL, WMOP_UNION);
588  bu_vls_sprintf(&str, "Inner-Hub-Cut1%s.s", suffix);
589  (void)mk_addmember(bu_vls_addr(&str), &innerhub.l, NULL, WMOP_SUBTRACT);
590  bu_vls_sprintf(&str, "Inner-Hub-Cut2%s.s", suffix);
591  (void)mk_addmember(bu_vls_addr(&str), &innerhub.l, NULL, WMOP_SUBTRACT);
592  bu_vls_sprintf(&str, "Hub-Holes%s.c", suffix);
593  (void)mk_addmember(bu_vls_addr(&str), &innerhub.l, NULL, WMOP_SUBTRACT);
594  bu_vls_sprintf(&str, "Bolt-Holes%s.c", suffix);
595  (void)mk_addmember(bu_vls_addr(&str), &innerhub.l, NULL, WMOP_SUBTRACT);
596  bu_vls_sprintf(&str, "Inner-Hub%s.c", suffix);
597  mk_lcomb(file, bu_vls_addr(&str), &innerhub, 0, NULL, NULL, NULL, 0);
598 
599  bu_vls_free(&str);
600 }
601 
602 
603 static void
604 MakeWheelRims(struct rt_wdb (*file), char *suffix, fastf_t dyhub,
605  fastf_t zhub, int bolts, fastf_t bolt_diam,
606  fastf_t bolt_circ_diam, fastf_t spigot_diam,
607  fastf_t fixing_offset, fastf_t bead_height,
608  fastf_t bead_width, fastf_t rim_thickness)
609 {
610  struct wmember wheelrimsolid, wheelrimcut;
611  struct wmember wheelrim, wheel;
612  fastf_t inner_width, left_width, right_width, fixing_width;
613  fastf_t inner_width_left_start, inner_width_right_start;
614  fastf_t fixing_width_left_trans;
615  fastf_t fixing_width_right_trans;
616  fastf_t fixing_width_middle;
617  fastf_t fixing_start_left, fixing_start_right, fixing_start_middle;
618  unsigned char rgb[3];
619  vect_t normal, height;
620  point_t vertex;
621  struct bu_vls str = BU_VLS_INIT_ZERO;
622 
623  /* Set wheel color */
624 
625  VSET(rgb, 217, 217, 217);
626 
627  /* Insert primitives */
628 
629  VSET(vertex, 0, -dyhub / 2, 0);
630  VSET(height, 0, bead_width, 0);
631  bu_vls_sprintf(&str, "Left-Bead%s.s", suffix);
632  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub);
633 
634  bu_vls_sprintf(&str, "Left-Bead-Cut%s.s", suffix);
635  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - rim_thickness);
636 
637  VSET(vertex, 0, dyhub / 2, 0);
638  VSET(height, 0, -bead_width, 0);
639  bu_vls_sprintf(&str, "Right-Bead%s.s", suffix);
640  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub);
641 
642  bu_vls_sprintf(&str, "Right-Bead-Cut%s.s", suffix);
643  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - rim_thickness);
644 
645  VSET(vertex, 0, -dyhub / 2 + bead_width, 0);
646  VSET(normal, 0, 1, 0);
647  bu_vls_sprintf(&str, "Left-Bead-Trans%s.s", suffix);
648  mk_cone(file, bu_vls_addr(&str), vertex, normal, bead_width, zhub, zhub-bead_height);
649 
650  bu_vls_sprintf(&str, "Left-Bead-Trans-cut%s.s", suffix);
651  mk_cone(file, bu_vls_addr(&str), vertex, normal, bead_width, zhub-rim_thickness, zhub-bead_height-rim_thickness);
652 
653  VSET(vertex, 0, dyhub / 2 - bead_width, 0);
654  VSET(normal, 0, -1, 0);
655  bu_vls_sprintf(&str, "Right-Bead-Trans%s.s", suffix);
656  mk_cone(file, bu_vls_addr(&str), vertex, normal, bead_width, zhub, zhub-bead_height);
657 
658  bu_vls_sprintf(&str, "Right-Bead-Trans-cut%s.s", suffix);
659  mk_cone(file, bu_vls_addr(&str), vertex, normal, bead_width, zhub-rim_thickness, zhub-bead_height-rim_thickness);
660 
661  /* At this point, some intermediate values are calculated to ease
662  * the bookkeeping
663  */
664 
665  inner_width = dyhub - 4 * bead_width;
666  inner_width_left_start = -dyhub / 2 + 2 * bead_width;
667  inner_width_right_start = dyhub / 2 - 2 * bead_width;
668  fixing_width = .25 * inner_width;
669  fixing_width_left_trans = .25 * fixing_width;
670  fixing_width_right_trans = .25 * fixing_width;
671  fixing_width_middle = .5 * fixing_width;
672  fixing_start_middle = fixing_offset - fixing_width_middle / 2;
673  fixing_start_left = fixing_start_middle - fixing_width_left_trans;
674  fixing_start_right = fixing_offset + fixing_width_middle;
675  right_width = inner_width_right_start - fixing_start_left - fixing_width;
676  left_width = inner_width_left_start - fixing_start_left;
677 
678  VSET(vertex, 0, inner_width_left_start, 0);
679  VSET(height, 0, -left_width, 0);
680  bu_vls_sprintf(&str, "LeftInnerRim%s.s", suffix);
681  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - bead_height);
682 
683  bu_vls_sprintf(&str, "LeftInnerRim-cut%s.s", suffix);
684  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - rim_thickness - bead_height);
685  VSET(vertex, 0, inner_width_right_start, 0);
686  VSET(height, 0, -right_width, 0);
687  bu_vls_sprintf(&str, "RightInnerRim%s.s", suffix);
688  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - bead_height);
689 
690  bu_vls_sprintf(&str, "RightInnerRim-cut%s.s", suffix);
691  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - rim_thickness - bead_height);
692  VSET(vertex, 0, fixing_start_left, 0);
693  VSET(normal, 0, 1, 0);
694  bu_vls_sprintf(&str, "Left-Fixing-Trans%s.s", suffix);
695  mk_cone(file, bu_vls_addr(&str), vertex, normal, fixing_width_left_trans,
696  zhub - bead_height, zhub - 2 * bead_height);
697 
698  bu_vls_sprintf(&str, "Left-Fixing-Trans-cut%s.s", suffix);
699  mk_cone(file, bu_vls_addr(&str), vertex, normal, fixing_width_left_trans,
700  zhub - bead_height - rim_thickness,
701  zhub - 2 * bead_height - rim_thickness);
702 
703  VSET(vertex, 0, fixing_start_right, 0);
704  VSET(normal, 0, -1, 0);
705  bu_vls_sprintf(&str, "Right-Fixing-Trans%s.s", suffix);
706  mk_cone(file, bu_vls_addr(&str), vertex, normal, fixing_width_right_trans,
707  zhub - bead_height, zhub - 2 * bead_height);
708 
709  bu_vls_sprintf(&str, "Right-Fixing-Trans-cut%s.s", suffix);
710  mk_cone(file, bu_vls_addr(&str), vertex, normal, fixing_width_right_trans,
711  zhub - bead_height - rim_thickness,
712  zhub - 2 * bead_height - rim_thickness);
713 
714  VSET(vertex, 0, fixing_start_middle, 0);
715  VSET(height, 0, fixing_width_middle, 0);
716  bu_vls_sprintf(&str, "Inner-Fixing%s.s", suffix);
717  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - 2 * bead_height);
718 
719  bu_vls_sprintf(&str, "Inner-Fixing-cut%s.s", suffix);
720  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub - rim_thickness - 2 * bead_height);
721 
722  /* Make combination for solid */
723 
724  BU_LIST_INIT(&wheelrimsolid.l);
725  bu_vls_sprintf(&str, "Left-Bead%s.s", suffix);
726  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
727  bu_vls_sprintf(&str, "Right-Bead%s.s", suffix);
728  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
729  bu_vls_sprintf(&str, "Left-Bead-Trans%s.s", suffix);
730  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
731  bu_vls_sprintf(&str, "Right-Bead-Trans%s.s", suffix);
732  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
733  bu_vls_sprintf(&str, "LeftInnerRim%s.s", suffix);
734  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
735  bu_vls_sprintf(&str, "RightInnerRim%s.s", suffix);
736  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
737  bu_vls_sprintf(&str, "Left-Fixing-Trans%s.s", suffix);
738  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
739  bu_vls_sprintf(&str, "Right-Fixing-Trans%s.s", suffix);
740  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
741  bu_vls_sprintf(&str, "Inner-Fixing%s.s", suffix);
742  (void)mk_addmember(bu_vls_addr(&str), &wheelrimsolid.l, NULL, WMOP_UNION);
743  bu_vls_sprintf(&str, "wheel-rim-solid%s.c", suffix);
744  mk_lcomb(file, bu_vls_addr(&str), &wheelrimsolid, 0, NULL, NULL, NULL, 0);
745 
746  /* Make combination for cutout */
747 
748  BU_LIST_INIT(&wheelrimcut.l);
749  bu_vls_sprintf(&str, "Left-Bead-Cut%s.s", suffix);
750  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
751  bu_vls_sprintf(&str, "Right-Bead-Cut%s.s", suffix);
752  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
753  bu_vls_sprintf(&str, "Left-Bead-Trans-cut%s.s", suffix);
754  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
755  bu_vls_sprintf(&str, "Right-Bead-Trans-cut%s.s", suffix);
756  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
757  bu_vls_sprintf(&str, "LeftInnerRim-cut%s.s", suffix);
758  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
759  bu_vls_sprintf(&str, "RightInnerRim-cut%s.s", suffix);
760  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
761  bu_vls_sprintf(&str, "Left-Fixing-Trans-cut%s.s", suffix);
762  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
763  bu_vls_sprintf(&str, "Right-Fixing-Trans-cut%s.s", suffix);
764  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
765  bu_vls_sprintf(&str, "Inner-Fixing-cut%s.s", suffix);
766  (void)mk_addmember(bu_vls_addr(&str), &wheelrimcut.l, NULL, WMOP_UNION);
767  bu_vls_sprintf(&str, "wheel-rim-cut%s.c", suffix);
768  mk_lcomb(file, bu_vls_addr(&str), &wheelrimcut, 0, NULL, NULL, NULL, 0);
769 
770  /* Make wheel rim combination */
771 
772  BU_LIST_INIT(&wheelrim.l);
773  bu_vls_sprintf(&str, "wheel-rim-solid%s.c", suffix);
774  (void)mk_addmember(bu_vls_addr(&str), &wheelrim.l, NULL, WMOP_UNION);
775  bu_vls_sprintf(&str, "wheel-rim-cut%s.c", suffix);
776  (void)mk_addmember(bu_vls_addr(&str), &wheelrim.l, NULL, WMOP_SUBTRACT);
777  bu_vls_sprintf(&str, "Wheel-Rim%s.c", suffix);
778  mk_lcomb(file, bu_vls_addr(&str), &wheelrim, 0, NULL, NULL, NULL, 0);
779 
780  MakeWheelCenter(file, suffix, fixing_start_middle, fixing_width,
781  rim_thickness, bead_height, zhub, dyhub, spigot_diam,
782  bolts, bolt_circ_diam, bolt_diam);
783 
784  /* Make combination for Wheel */
785 
786  BU_LIST_INIT(&wheel.l);
787  bu_vls_sprintf(&str, "Inner-Hub%s.c", suffix);
788  (void)mk_addmember(bu_vls_addr(&str), &wheel.l, NULL, WMOP_UNION);
789  bu_vls_sprintf(&str, "Wheel-Rim%s.c", suffix);
790  (void)mk_addmember(bu_vls_addr(&str), &wheel.l, NULL, WMOP_UNION);
791  bu_vls_sprintf(&str, "wheel%s.r", suffix);
792  mk_lcomb(file, bu_vls_addr(&str), &wheel, 1, "plastic", "di=.8 sp=.2", rgb, 0);
793 
794  bu_vls_free(&str);
795 }
796 
797 
798 /**********************************************************************
799  * *
800  * Extrusion Creation Routines for Tire *
801  * Tread Patterns - makes sketch and *
802  * uses sketch to make extrusion *
803  * *
804  **********************************************************************/
805 static void
806 MakeExtrude(struct rt_wdb (*file), char *suffix, point2d_t *verts,
807  size_t vertcount, fastf_t patternwidth1, fastf_t patternwidth2,
808  fastf_t tirewidth, fastf_t zbase, fastf_t ztire)
809 {
810  struct rt_sketch_internal skt;
811  struct line_seg *lsg;
812  point_t V;
813  vect_t u_vec, v_vec, h;
814  size_t i;
815  struct bu_vls str = BU_VLS_INIT_ZERO;
816  struct bu_vls str2 = BU_VLS_INIT_ZERO;
817 
818  /* Basic allocation of structure */
819  skt.magic = RT_SKETCH_INTERNAL_MAGIC;
820 
821  /* Set vertex and orientation vectors?? */
822  VSET(V, 0, -tirewidth/2, zbase-.1*zbase);
823  VSET(u_vec, 1, 0, 0);
824  VSET(v_vec, 0, 1, 0);
825  VMOVE(skt.V, V);
826  VMOVE(skt.u_vec, u_vec);
827  VMOVE(skt.v_vec, v_vec);
828 
829  /* Define links between/order of vertices */
830  skt.vert_count = vertcount;
831  skt.verts = (point2d_t *)bu_calloc(skt.vert_count, sizeof(point2d_t), "verts");
832  for (i = 0; i < skt.vert_count; i++) {
833  V2SET(skt.verts[i],
834  verts[i][0] * patternwidth2 - patternwidth2 / 2,
835  verts[i][1] * tirewidth);
836  }
837 
838  /* Specify number of segments and allocate memory for reverse??
839  * and segments.
840  */
841  skt.curve.count = vertcount;
842  skt.curve.reverse = (int *)bu_calloc(skt.curve.count, sizeof(int), "sketch: reverse");
843  skt.curve.segment = (void **)bu_calloc(skt.curve.count, sizeof(void *), "segs");
844 
845 
846  /* Insert all line segments except the last one */
847  for (i = 0; i < vertcount-1; i++) {
848  BU_ALLOC(lsg, struct line_seg);
849  lsg->magic = CURVE_LSEG_MAGIC;
850  lsg->start = i;
851  lsg->end = i + 1;
852  skt.curve.segment[i] = (void *)lsg;
853  }
854 
855  /* Connect the last connected vertex to the first vertex */
856  BU_ALLOC(lsg, struct line_seg);
857  lsg->magic = CURVE_LSEG_MAGIC;
858  lsg->start = vertcount - 1;
859  lsg->end = 0;
860  skt.curve.segment[vertcount - 1] = (void *)lsg;
861 
862  /* Make the sketch */
863  bu_vls_sprintf(&str, "sketch%s", suffix);
864  mk_sketch(file, bu_vls_addr(&str), &skt);
865 
866  /* release dynamic sketch memory */
867  bu_free(skt.verts, "verts");
868  rt_curve_free(&skt.curve);
869 
870  /* Make first slanted extrusion for depth vs. width of tread effect */
871  VSET(h, patternwidth1 / 2 - patternwidth2 / 2, 0, ztire - (zbase - .11 * zbase));
872  bu_vls_sprintf(&str2, "extrude1%s", suffix);
873  mk_extrusion(file, bu_vls_addr(&str2), bu_vls_addr(&str), V, h, u_vec, v_vec, 0);
874 
875  /* Make second slanted extrusion for depth vs. width effect */
876  VSET(h, -patternwidth1 / 2 + patternwidth2 / 2, 0, ztire - (zbase - .11 * zbase));
877  bu_vls_sprintf(&str2, "extrude2%s", suffix);
878  mk_extrusion(file, bu_vls_addr(&str2), bu_vls_addr(&str), V, h, u_vec, v_vec, 0);
879 
880  /* Direct extrusion */
881  VSET(h, 0, 0, ztire - (zbase - .11 * zbase));
882  bu_vls_sprintf(&str2, "extrude3%s", suffix);
883  mk_extrusion(file, bu_vls_addr(&str2), bu_vls_addr(&str), V, h, u_vec, v_vec, 0);
884 
885  bu_vls_free(&str);
886  bu_vls_free(&str2);
887 }
888 
889 
890 #define SKETCHNUM2 4
891 static void
892 MakeTreadPattern2(struct rt_wdb (*file), char *suffix, fastf_t dwidth,
893  fastf_t z_base, fastf_t ztire, int number_of_patterns)
894 {
895  struct bu_vls str = BU_VLS_INIT_ZERO;
896  struct bu_vls str2 = BU_VLS_INIT_ZERO;
897  struct wmember treadpattern, tread, treadrotated;
898  fastf_t patternwidth1, patternwidth2;
899  mat_t y;
900  int i, j;
901  int vertcounts[SKETCHNUM2];
902  point2d_t *verts[SKETCHNUM2];
903  point2d_t verts1[] = {
904  { 0, 0 },
905  { 0, .1 },
906  { .66, .34 },
907  { .34, .66 },
908  { 1, .9 },
909  { 1, 1 },
910 
911  { 1.4, 1 },
912  { 1.33, .9 },
913  { .66, .66 },
914  { 1, .34 },
915  { .33, .1 },
916  { .4, 0 }
917  };
918  point2d_t verts2[] = {
919  { .2, .13 },
920  { -.6, .2 },
921  { -.5, .27 },
922  { .4, .2 }
923  };
924  point2d_t verts3[] = {
925  { .5, .45 },
926  { -.5, .4 },
927  { -.6, .5 },
928  { .5, .55 }
929  };
930  point2d_t verts4[] = {
931  { .6, .73 },
932  { -.3, .8 },
933  { -.1, .87 },
934  { .8, .8 }
935  };
936 
937  patternwidth1 = ztire * sin(M_PI / number_of_patterns);
938  patternwidth2 = z_base * sin(M_PI / number_of_patterns);
939 
940  verts[0] = verts1;
941  vertcounts[0] = 12;
942 
943  verts[1] = verts2;
944  vertcounts[1] = 4;
945 
946  verts[2] = verts3;
947  vertcounts[2] = 4;
948 
949  verts[3] = verts4;
950  vertcounts[3] = 4;
951 
952  BU_LIST_INIT(&treadpattern.l);
953 
954  for (i = 0; i < SKETCHNUM2; i++) {
955  bu_vls_sprintf(&str, "-%d%s", i + 1, suffix);
956  MakeExtrude(file, bu_vls_addr(&str), verts[i], vertcounts[i],
957  2 * patternwidth1, 2 * patternwidth2, dwidth, z_base,
958  ztire);
959  for (j = 1; j <= 3; j++) {
960  bu_vls_sprintf(&str, "extrude%d-%d%s", j, i + 1, suffix);
961  (void)mk_addmember(bu_vls_addr(&str), &treadpattern.l, NULL, WMOP_UNION);
962  }
963  }
964 
965  bu_vls_sprintf(&str, "tread_master%s.c", suffix);
966  mk_lcomb(file, bu_vls_addr(&str), &treadpattern, 0, NULL, NULL, NULL, 0);
967 
968  BU_LIST_INIT(&tread.l);
969  BU_LIST_INIT(&treadrotated.l);
970 
971  bu_vls_sprintf(&str2, "tire-tread-shape%s.c", suffix);
972  (void)mk_addmember(bu_vls_addr(&str2), &tread.l, NULL, WMOP_UNION);
973  for (i = 1; i <= number_of_patterns; i++) {
974  bu_vls_sprintf(&str, "tread_master%s.c", suffix);
975  getYRotMat(&y, i * M_2PI / number_of_patterns);
976  (void)mk_addmember(bu_vls_addr(&str), &tread.l, y, WMOP_SUBTRACT);
977  }
978 
979 
980  bu_vls_sprintf(&str, "tread%s.c", suffix);
981  mk_lcomb(file, bu_vls_addr(&str), &tread, 0, NULL, NULL, NULL , 0);
982 
983  bu_vls_free(&str);
984  bu_vls_free(&str2);
985 }
986 
987 
988 #define SKETCHNUM1 9
989 static void
990 MakeTreadPattern1(struct rt_wdb (*file), char *suffix, fastf_t dwidth,
991  fastf_t z_base, fastf_t ztire, int number_of_patterns)
992 {
993  struct bu_vls str = BU_VLS_INIT_ZERO;
994  struct bu_vls str2 = BU_VLS_INIT_ZERO;
995  struct wmember treadpattern, tread, treadrotated;
996  fastf_t patternwidth1, patternwidth2;
997  mat_t y;
998  int i, j;
999  int vertcounts[SKETCHNUM1];
1000  point2d_t *verts[SKETCHNUM1];
1001  point2d_t verts1[] = {
1002  { .9, 0 },
1003  { .6, .3 },
1004  { .94, .7 },
1005  { .45, 1 },
1006 
1007  { .58, 1 },
1008  { 1.07, .7 },
1009  { .73, .3 },
1010  { 1.03, 0 }
1011  };
1012  point2d_t verts2[] = {
1013  { .3, 0 },
1014  { .0, .3 },
1015  { .34, .7 },
1016  { -.15, 1 },
1017 
1018  { 0.05, 1 },
1019  { .47, .7 },
1020  { .13, .3 },
1021  { .43, 0 }
1022  };
1023  point2d_t verts3[] = {
1024  { -.1, .1 },
1025  { -.1, .12 },
1026  { 1.1, .12 },
1027  { 1.1, .1 }
1028  };
1029  point2d_t verts4[] = {
1030  { -.1, .20 },
1031  { -.1, .23 },
1032  { 1.1, .23 },
1033  { 1.1, .20 }
1034  };
1035  point2d_t verts5[] = {
1036  { -.1, .37 },
1037  { -.1, .4 },
1038  { 1.1, .4 },
1039  { 1.1, .37 }
1040  };
1041  point2d_t verts6[] = {
1042  { -.1, .49 },
1043  { -.1, .51},
1044  { 1.1, .51 },
1045  { 1.1, .49 }
1046  };
1047  point2d_t verts7[] = {
1048  { -.1, .6 },
1049  { -.1, .63 },
1050  { 1.1, .63 },
1051  { 1.1, .6 }
1052  };
1053  point2d_t verts8[] = {
1054  { -.1, .77 },
1055  { -.1, .80 },
1056  { 1.1, .80 },
1057  { 1.1, .77 }
1058  };
1059  point2d_t verts9[] = {
1060  { -.1, .88 },
1061  { -.1, .9 },
1062  { 1.1, .9 },
1063  { 1.1, .88 }
1064  };
1065 
1066  patternwidth1 = ztire * sin(M_PI / number_of_patterns);
1067  patternwidth2 = z_base * sin(M_PI / number_of_patterns);
1068 
1069  verts[0] = verts1;
1070  vertcounts[0] = 8;
1071 
1072  verts[1] = verts2;
1073  vertcounts[1] = 8;
1074 
1075  verts[2] = verts3;
1076  vertcounts[2] = 4;
1077 
1078  verts[3] = verts4;
1079  vertcounts[3] = 4;
1080 
1081  verts[4] = verts5;
1082  vertcounts[4] = 4;
1083 
1084  verts[5] = verts6;
1085  vertcounts[5] = 4;
1086 
1087  verts[6] = verts7;
1088  vertcounts[6] = 4;
1089 
1090  verts[7] = verts8;
1091  vertcounts[7] = 4;
1092 
1093  verts[8] = verts9;
1094  vertcounts[8] = 4;
1095 
1096  BU_LIST_INIT(&treadpattern.l);
1097 
1098  for (i = 0; i < SKETCHNUM1; i++) {
1099  bu_vls_sprintf(&str, "-%d%s", i+1, suffix);
1100  MakeExtrude(file, bu_vls_addr(&str), verts[i], vertcounts[i],
1101  2 * patternwidth1, 2 * patternwidth2, dwidth, z_base,
1102  ztire);
1103  for (j = 1; j <= 3; j++) {
1104  bu_vls_sprintf(&str, "extrude%d-%d%s", j, i+1, suffix);
1105  (void)mk_addmember(bu_vls_addr(&str), &treadpattern.l, NULL, WMOP_UNION);
1106  }
1107  }
1108 
1109  bu_vls_sprintf(&str, "tread_master%s.c", suffix);
1110  mk_lcomb(file, bu_vls_addr(&str), &treadpattern, 0, NULL, NULL, NULL, 0);
1111 
1112  BU_LIST_INIT(&tread.l);
1113  BU_LIST_INIT(&treadrotated.l);
1114 
1115  bu_vls_sprintf(&str2, "tire-tread-shape%s.c", suffix);
1116  (void)mk_addmember(bu_vls_addr(&str2), &tread.l, NULL, WMOP_UNION);
1117  for (i = 1; i <= number_of_patterns; i++) {
1118  bu_vls_sprintf(&str, "tread_master%s.c", suffix);
1119  getYRotMat(&y, i * M_2PI / number_of_patterns);
1120  (void)mk_addmember(bu_vls_addr(&str), &tread.l, y, WMOP_SUBTRACT);
1121  }
1122 
1123 
1124  bu_vls_sprintf(&str, "tread%s.c", suffix);
1125  mk_lcomb(file, bu_vls_addr(&str), &tread, 0, NULL, NULL, NULL , 0);
1126 
1127  bu_vls_free(&str);
1128  bu_vls_free(&str2);
1129 }
1130 
1131 
1132 static void
1133 TreadPattern(struct rt_wdb (*file), char *suffix, fastf_t dwidth,
1134  fastf_t z_base, fastf_t ztire, int number_of_patterns,
1135  int patterntype)
1136 {
1137  typedef void (* MakeTreadPattern)(struct rt_wdb (*), char *, fastf_t, fastf_t, fastf_t, int);
1138  MakeTreadPattern TreadPatterns[2];
1139  TreadPatterns[0] = &MakeTreadPattern1;
1140  TreadPatterns[1] = &MakeTreadPattern2;
1141  (*TreadPatterns[patterntype-1])(file, suffix, dwidth, z_base, ztire,
1142  number_of_patterns);
1143 }
1144 
1145 
1146 /**********************************************************************
1147  * *
1148  * Routine which does actual primitive insertion *
1149  * to form slick tire surfaces, using results *
1150  * of General Conic Equation solver. Also forms *
1151  * proper combinations of inserted primitives. *
1152  * *
1153  **********************************************************************/
1154 static void
1155 MakeTireSurface(struct rt_wdb (*file), char *suffix,
1156  fastf_t *ell1cadparams, fastf_t *ell2cadparams,
1157  fastf_t *ell3cadparams, fastf_t ztire, fastf_t dztred,
1158  fastf_t dytred, fastf_t dyhub, fastf_t zhub,
1159  fastf_t dyside1, fastf_t zside1)
1160 {
1161  struct wmember tireslicktread, tireslicktopsides, tireslickbottomshapes, tireslickbottomsides;
1162  struct wmember tireslick;
1163  struct wmember innersolid;
1164  struct bu_vls str = BU_VLS_INIT_ZERO;
1165  vect_t vertex, height;
1166  point_t origin, normal, C;
1167 
1168  /* Insert primitives */
1169  VSET(origin, 0, ell1cadparams[0], 0);
1170  VSET(normal, 0, 1, 0);
1171  VSET(C, 0, ell1cadparams[2], ell1cadparams[3]);
1172  bu_vls_sprintf(&str, "Ellipse1%s.s", suffix);
1173  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell1cadparams[1], ell1cadparams[4]);
1174 
1175  VSET(origin, 0, ell2cadparams[0], 0);
1176  VSET(normal, 0, 1, 0);
1177  VSET(C, 0, ell2cadparams[2], ell2cadparams[3]);
1178  bu_vls_sprintf(&str, "Ellipse2%s.s", suffix);
1179  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell2cadparams[1], ell2cadparams[4]);
1180 
1181  VSET(origin, 0, ell3cadparams[0], 0);
1182  VSET(normal, 0, 1, 0);
1183  VSET(C, 0, ell3cadparams[2], ell3cadparams[3]);
1184  bu_vls_sprintf(&str, "Ellipse3%s.s", suffix);
1185  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell3cadparams[1], ell3cadparams[4]);
1186 
1187  VSET(origin, 0, -ell2cadparams[0], 0);
1188  VSET(normal, 0, -1, 0);
1189  VSET(C, 0, -ell2cadparams[2], -ell2cadparams[3]);
1190  bu_vls_sprintf(&str, "Ellipse4%s.s", suffix);
1191  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell2cadparams[1], ell2cadparams[4]);
1192 
1193  VSET(vertex, 0, -ell1cadparams[2] - ell1cadparams[2] * .01, 0);
1194  VSET(height, 0, 2 * (ell1cadparams[2] + ell1cadparams[2] * .01), 0);
1195  bu_vls_sprintf(&str, "TopClip%s.s", suffix);
1196  mk_rcc(file, bu_vls_addr(&str), vertex, height, ztire - dztred);
1197 
1198  VSET(vertex, 0, -dyside1 / 2 - 0.1 * dyside1 / 2, 0);
1199  VSET(height, 0, dyside1 + 0.1 * dyside1, 0);
1200  bu_vls_sprintf(&str, "InnerClip%s.s", suffix);
1201  mk_rcc(file, bu_vls_addr(&str), vertex, height, zhub);
1202 
1203  VSET(vertex, 0, -dyside1 / 2 - 0.1 * dyside1 / 2, 0);
1204  VSET(height, 0, dyside1 + 0.1 * dyside1, 0);
1205  bu_vls_sprintf(&str, "EllClip%s.s", suffix);
1206  mk_rcc(file, bu_vls_addr(&str), vertex, height, zside1);
1207 
1208  /* Insert primitives to ensure a solid interior - based on
1209  * dimensions, either add or subtract cones from the sides of the
1210  * solid.
1211  */
1212  VSET(vertex, 0, -dytred / 2, 0);
1213  VSET(height, 0, dytred, 0);
1214  bu_vls_sprintf(&str, "InnerSolid%s.s", suffix);
1215  mk_rcc(file, bu_vls_addr(&str), vertex, height, ztire-dztred);
1216  if (!ZERO(dytred/2 - dyhub/2)) {
1217  VSET(normal, 0, 1, 0);
1218  bu_vls_sprintf(&str, "LeftCone%s.s", suffix);
1219  mk_cone(file, bu_vls_addr(&str), vertex, normal, dytred / 2 - dyhub / 2,
1220  ztire - dztred, zhub);
1221  VSET(vertex, 0, dytred/2, 0);
1222  VSET(normal, 0, -1, 0);
1223  bu_vls_sprintf(&str, "RightCone%s.s", suffix);
1224  mk_cone(file, bu_vls_addr(&str), vertex, normal, dytred / 2 - dyhub / 2,
1225  ztire - dztred, zhub);
1226  }
1227 
1228  /* Combine inner solid, cones, and cuts to ensure a filled inner
1229  * volume.
1230  */
1231  BU_LIST_INIT(&innersolid.l);
1232  bu_vls_sprintf(&str, "InnerSolid%s.s", suffix);
1233  (void)mk_addmember(bu_vls_addr(&str), &innersolid.l, NULL, WMOP_UNION);
1234  if ((dytred / 2 - dyhub / 2) > 0 &&
1235  !ZERO(dytred / 2 - dyhub / 2)) {
1236  bu_vls_sprintf(&str, "LeftCone%s.s", suffix);
1237  (void)mk_addmember(bu_vls_addr(&str), &innersolid.l, NULL, WMOP_SUBTRACT);
1238  bu_vls_sprintf(&str, "RightCone%s.s", suffix);
1239  (void)mk_addmember(bu_vls_addr(&str), &innersolid.l, NULL, WMOP_SUBTRACT);
1240  }
1241  if ((dytred / 2 - dyhub / 2) < 0 &&
1242  !ZERO(dytred / 2 - dyhub / 2)) {
1243  bu_vls_sprintf(&str, "LeftCone%s.s", suffix);
1244  (void)mk_addmember(bu_vls_addr(&str), &innersolid.l, NULL, WMOP_UNION);
1245  bu_vls_sprintf(&str, "RightCone%s.s", suffix);
1246  (void)mk_addmember(bu_vls_addr(&str), &innersolid.l, NULL, WMOP_UNION);
1247  }
1248  bu_vls_sprintf(&str, "InnerClip%s.s", suffix);
1249  (void)mk_addmember(bu_vls_addr(&str), &innersolid.l, NULL, WMOP_SUBTRACT);
1250  bu_vls_sprintf(&str, "tire-solid%s.c", suffix);
1251  mk_lcomb(file, bu_vls_addr(&str), &innersolid, 0, NULL, NULL, NULL, 0);
1252 
1253  /* Define the tire slick tread */
1254  BU_LIST_INIT(&tireslicktread.l);
1255  bu_vls_sprintf(&str, "Ellipse1%s.s", suffix);
1256  (void)mk_addmember(bu_vls_addr(&str), &tireslicktread.l, NULL, WMOP_UNION);
1257 
1258  bu_vls_sprintf(&str, "TopClip%s.s", suffix);
1259  (void)mk_addmember(bu_vls_addr(&str), &tireslicktread.l, NULL, WMOP_SUBTRACT);
1260 
1261  bu_vls_sprintf(&str, "tire-slick-tread%s.c", suffix);
1262  mk_lcomb(file, bu_vls_addr(&str), &tireslicktread, 0, NULL, NULL, NULL, 0);
1263 
1264  /* Define upper sides */
1265  BU_LIST_INIT(&tireslicktopsides.l);
1266  bu_vls_sprintf(&str, "Ellipse2%s.s", suffix);
1267  (void)mk_addmember(bu_vls_addr(&str), &tireslicktopsides.l, NULL, WMOP_UNION);
1268 
1269  bu_vls_sprintf(&str, "EllClip%s.s", suffix);
1270  (void)mk_addmember(bu_vls_addr(&str), &tireslicktopsides.l, NULL, WMOP_SUBTRACT);
1271 
1272  bu_vls_sprintf(&str, "Ellipse4%s.s", suffix);
1273  (void)mk_addmember(bu_vls_addr(&str), &tireslicktopsides.l, NULL, WMOP_UNION);
1274 
1275  bu_vls_sprintf(&str, "EllClip%s.s", suffix);
1276  (void)mk_addmember(bu_vls_addr(&str), &tireslicktopsides.l, NULL, WMOP_SUBTRACT);
1277 
1278  bu_vls_sprintf(&str, "tire-upper-sides%s.c", suffix);
1279  mk_lcomb(file, bu_vls_addr(&str), &tireslicktopsides, 0, NULL, NULL, NULL, 0);
1280 
1281  /* Define lower sides shapes */
1282  BU_LIST_INIT(&tireslickbottomshapes.l);
1283  bu_vls_sprintf(&str, "Ellipse3%s.s", suffix);
1284  (void)mk_addmember(bu_vls_addr(&str), &tireslickbottomshapes.l, NULL, WMOP_UNION);
1285 
1286  bu_vls_sprintf(&str, "EllClip%s.s", suffix);
1287  (void)mk_addmember(bu_vls_addr(&str), &tireslickbottomshapes.l, NULL, WMOP_INTERSECT);
1288 
1289  bu_vls_sprintf(&str, "tire-lower-sides-shapes%s.c", suffix);
1290  mk_lcomb(file, bu_vls_addr(&str), &tireslickbottomshapes, 0, NULL, NULL, NULL, 0);
1291 
1292  /* Define lower sides */
1293  BU_LIST_INIT(&tireslickbottomsides.l);
1294  bu_vls_sprintf(&str, "tire-lower-sides-shapes%s.c", suffix);
1295  (void)mk_addmember(bu_vls_addr(&str), &tireslickbottomsides.l, NULL, WMOP_UNION);
1296 
1297  bu_vls_sprintf(&str, "InnerClip%s.s", suffix);
1298  (void)mk_addmember(bu_vls_addr(&str), &tireslickbottomsides.l, NULL, WMOP_SUBTRACT);
1299 
1300  bu_vls_sprintf(&str, "tire-lower-sides%s.c", suffix);
1301  mk_lcomb(file, bu_vls_addr(&str), &tireslickbottomsides, 0, NULL, NULL, NULL, 0);
1302 
1303 
1304  /* Combine cuts and primitives to make final tire slick surface */
1305  BU_LIST_INIT(&tireslick.l);
1306  bu_vls_sprintf(&str, "tire-slick-tread%s.c", suffix);
1307  (void)mk_addmember(bu_vls_addr(&str), &tireslick.l, NULL, WMOP_UNION);
1308 
1309  bu_vls_sprintf(&str, "tire-upper-sides%s.c", suffix);
1310  (void)mk_addmember(bu_vls_addr(&str), &tireslick.l, NULL, WMOP_UNION);
1311 
1312  bu_vls_sprintf(&str, "tire-lower-sides%s.c", suffix);
1313  (void)mk_addmember(bu_vls_addr(&str), &tireslick.l, NULL, WMOP_UNION);
1314 
1315  bu_vls_sprintf(&str, "tire-solid%s.c", suffix);
1316  (void)mk_addmember(bu_vls_addr(&str), &tireslick.l, NULL, WMOP_UNION);
1317 
1318  bu_vls_sprintf(&str, "tire%s.c", suffix);
1319  mk_lcomb(file, bu_vls_addr(&str), &tireslick, 0, NULL, NULL, NULL, 0);
1320 
1321  bu_vls_free(&str);
1322 }
1323 
1324 
1325 /**********************************************************************
1326  * *
1327  * Routines to handle creation of tread solids *
1328  * and invocation of the tread pattern creator *
1329  * *
1330  **********************************************************************/
1331 static void
1332 MakeTreadSolid(struct rt_wdb (*file), char *suffix,
1333  fastf_t *ell2coefficients, fastf_t ztire, fastf_t dztred,
1334  fastf_t d1, fastf_t dytred, fastf_t dyhub, fastf_t zhub,
1335  fastf_t UNUSED(dyside1), int number_of_tread_patterns,
1336  int pattern_type)
1337 {
1338  fastf_t **matrixelltread1, **matrixelltread2;
1339  fastf_t ell1treadcoefficients[5], ell2treadcoefficients[5];
1340  fastf_t ell1treadcadparams[5], ell2treadcadparams[5];
1341  fastf_t d1_intercept;
1342  fastf_t elltreadpartial;
1343  struct wmember premtreadshape, tiretreadshape;
1344  vect_t vertex, height;
1345  point_t origin, normal, C;
1346 
1347  int i;
1348  struct bu_vls str = BU_VLS_INIT_ZERO;
1349 
1350  matrixelltread1 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1351  for (i = 0; i < 5; i++)
1352  matrixelltread1[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1353 
1354  matrixelltread2 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1355  for (i = 0; i < 5; i++)
1356  matrixelltread2[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1357 
1358 
1359  /* Find point on side where tread will start */
1360  d1_intercept = GetValueAtZPoint(ell2coefficients, ztire - d1);
1361  Create_Ell1_Mat(matrixelltread1, dytred, dztred, d1, ztire);
1362 
1363  Echelon(matrixelltread1);
1364  SolveEchelon(matrixelltread1, ell1treadcoefficients);
1365  CalcInputVals(ell1treadcoefficients, ell1treadcadparams);
1366  elltreadpartial = GetEllPartialAtPoint(ell1treadcoefficients, dytred / 2, ztire - dztred);
1367  Create_Ell2_Mat(matrixelltread2, dytred, dztred, d1_intercept * 2, ztire - d1, ztire, dyhub, zhub, elltreadpartial);
1368 
1369  Echelon(matrixelltread2);
1370  SolveEchelon(matrixelltread2, ell2treadcoefficients);
1371  CalcInputVals(ell2treadcoefficients, ell2treadcadparams);
1372 
1373  /* Insert primitives */
1374  VSET(origin, 0, ell1treadcadparams[0], 0);
1375  VSET(normal, 0, 1, 0);
1376  VSET(C, 0, ell1treadcadparams[2], ell1treadcadparams[3]);
1377  bu_vls_sprintf(&str, "Ellipse1tread%s.s", suffix);
1378  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell1treadcadparams[1], ell1treadcadparams[4]);
1379 
1380  VSET(origin, 0, ell2treadcadparams[0], 0);
1381  VSET(normal, 0, 1, 0);
1382  VSET(C, 0, ell2treadcadparams[2], ell2treadcadparams[3]);
1383  bu_vls_sprintf(&str, "Ellipse2tread%s.s", suffix);
1384  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell2treadcadparams[1], ell2treadcadparams[4]);
1385 
1386  VSET(origin, 0, -ell2treadcadparams[0], 0);
1387  VSET(normal, 0, -1, 0);
1388  VSET(C, 0, -ell2treadcadparams[2], -ell2treadcadparams[3]);
1389  bu_vls_sprintf(&str, "Ellipse4tread%s.s", suffix);
1390  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell2treadcadparams[1], ell2treadcadparams[4]);
1391 
1392  VSET(vertex, 0, -ell1treadcadparams[2] - ell1treadcadparams[2] * .01, 0);
1393  VSET(height, 0, ell1treadcadparams[2] - dytred/2 + ell1treadcadparams[2] * .01 , 0);
1394  bu_vls_sprintf(&str, "TopTreadClipL%s.s", suffix);
1395  mk_rcc(file, bu_vls_addr(&str), vertex, height, ztire - dztred);
1396 
1397  VSET(vertex, 0, ell1treadcadparams[2] + ell1treadcadparams[2] * .01, 0);
1398  VSET(height, 0, -ell1treadcadparams[2] + dytred/2 - ell1treadcadparams[2] * .01, 0);
1399  bu_vls_sprintf(&str, "TopTreadClipR%s.s", suffix);
1400  mk_rcc(file, bu_vls_addr(&str), vertex, height, ztire - dztred);
1401 
1402  VSET(vertex, 0, -d1_intercept, 0);
1403  VSET(height, 0, d1_intercept * 2, 0);
1404  bu_vls_sprintf(&str, "InnerTreadCut%s.s", suffix);
1405  mk_rcc(file, bu_vls_addr(&str), vertex, height, ztire - d1);
1406 
1407  /* Assemble the primitives into the preliminary tread shape */
1408  BU_LIST_INIT(&premtreadshape.l);
1409  bu_vls_sprintf(&str, "Ellipse1tread%s.s", suffix);
1410  (void)mk_addmember(bu_vls_addr(&str), &premtreadshape.l, NULL, WMOP_UNION);
1411  bu_vls_sprintf(&str, "TopTreadClipL%s.s", suffix);
1412  (void)mk_addmember(bu_vls_addr(&str), &premtreadshape.l, NULL, WMOP_SUBTRACT);
1413  bu_vls_sprintf(&str, "TopTreadClipR%s.s", suffix);
1414  (void)mk_addmember(bu_vls_addr(&str), &premtreadshape.l, NULL, WMOP_SUBTRACT);
1415  bu_vls_sprintf(&str, "Ellipse2tread%s.s", suffix);
1416  (void)mk_addmember(bu_vls_addr(&str), &premtreadshape.l, NULL, WMOP_UNION);
1417  bu_vls_sprintf(&str, "InnerTreadCut%s.s", suffix);
1418  (void)mk_addmember(bu_vls_addr(&str), &premtreadshape.l, NULL, WMOP_SUBTRACT);
1419  bu_vls_sprintf(&str, "Ellipse4tread%s.s", suffix);
1420  (void)mk_addmember(bu_vls_addr(&str), &premtreadshape.l, NULL, WMOP_UNION);
1421  bu_vls_sprintf(&str, "InnerTreadCut%s.s", suffix);
1422  (void)mk_addmember(bu_vls_addr(&str), &premtreadshape.l, NULL, WMOP_SUBTRACT);
1423  bu_vls_sprintf(&str, "tire-tread-prem%s.c", suffix);
1424  mk_lcomb(file, bu_vls_addr(&str), &premtreadshape, 0, NULL, NULL, NULL, 0);
1425 
1426 
1427  /* The tire tread shape needed is the subtraction of the slick
1428  * surface from the tread shape, which is handled here to supply
1429  * the correct shape for later tread work.
1430  */
1431  BU_LIST_INIT(&tiretreadshape.l);
1432  bu_vls_sprintf(&str, "tire-tread-prem%s.c", suffix);
1433  (void)mk_addmember(bu_vls_addr(&str), &tiretreadshape.l, NULL, WMOP_UNION);
1434  bu_vls_sprintf(&str, "tire-solid%s.c", suffix);
1435  (void)mk_addmember(bu_vls_addr(&str), &tiretreadshape.l, NULL, WMOP_SUBTRACT);
1436  bu_vls_sprintf(&str, "tire-tread-shape%s.c", suffix);
1437  mk_lcomb(file, bu_vls_addr(&str), &tiretreadshape, 0, NULL, NULL, NULL, 0);
1438 
1439 
1440  /* Call function to generate primitives and combinations for
1441  * actual tread pattern
1442  */
1443  bu_vls_sprintf(&str, "%s", suffix);
1444  TreadPattern(file, bu_vls_addr(&str), d1_intercept * 2, ztire - d1, ztire,
1445  number_of_tread_patterns, pattern_type);
1446 
1447  for (i = 0; i < 5; i++)
1448  bu_free((char *)matrixelltread1[i], "matrixell1 element");
1449  bu_free((char *)matrixelltread1, "matrixell1");
1450 
1451  for (i = 0; i < 5; i++)
1452  bu_free((char *)matrixelltread2[i], "matrixell2 element");
1453  bu_free((char *)matrixelltread2, "matrixell2");
1454 
1455  bu_vls_free(&str);
1456 }
1457 
1458 
1459 static void
1460 MakeTreadSolid1(struct rt_wdb (*file), char *suffix,
1461  fastf_t *ell2coefficients, fastf_t ztire, fastf_t dztred,
1462  fastf_t d1, fastf_t dytred, fastf_t UNUSED(dyhub), fastf_t UNUSED(zhub),
1463  fastf_t UNUSED(dyside1), int number_of_tread_patterns,
1464  int patterntype)
1465 {
1466  fastf_t **matrixelltred1, **matrixelltred2;
1467  fastf_t ell1tredcoefficients[5];
1468  fastf_t ell1tredcadparams[5];
1469  fastf_t d1_intercept;
1470  struct wmember tiretreadintercept, tiretreadsolid, tiretreadshape;
1471  int i;
1472  struct bu_vls str = BU_VLS_INIT_ZERO;
1473  vect_t vertex, height;
1474  point_t origin, normal, C;
1475 
1476  matrixelltred1 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *),
1477  "matrixrows");
1478  for (i = 0; i < 5; i++)
1479  matrixelltred1[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t),
1480  "matrixcols");
1481 
1482  matrixelltred2 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *),
1483  "matrixrows");
1484  for (i = 0; i < 5; i++)
1485  matrixelltred2[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t),
1486  "matrixcols");
1487 
1488  /* Find point on side where tread will start */
1489  d1_intercept = GetValueAtZPoint(ell2coefficients, ztire - d1);
1490 
1491  Create_Ell1_Mat(matrixelltred1, d1_intercept * 2, dztred, d1, ztire);
1492  Echelon(matrixelltred1);
1493  SolveEchelon(matrixelltred1, ell1tredcoefficients);
1494  CalcInputVals(ell1tredcoefficients, ell1tredcadparams);
1495  VSET(origin, 0, ell1tredcadparams[0], 0);
1496  VSET(normal, 0, 1, 0);
1497  VSET(C, 0, ell1tredcadparams[2], ell1tredcadparams[3]);
1498  bu_vls_sprintf(&str, "Ellipse-tread-outer%s.s", suffix);
1499  mk_eto(file, bu_vls_addr(&str), origin, normal, C, ell1tredcadparams[1], ell1tredcadparams[4]);
1500 
1501  VSET(vertex, 0, -dytred / 2, 0);
1502  VSET(height, 0, dytred, 0);
1503  bu_vls_sprintf(&str, "Ellipse-constrain%s.s", suffix);
1504  mk_rcc(file, bu_vls_addr(&str), vertex, height, ztire);
1505 
1506  VSET(vertex, 0, -dytred / 2, 0);
1507  VSET(normal, 0, -1, 0);
1508  bu_vls_sprintf(&str, "Ellipse-trim1%s.s", suffix);
1509  mk_cone(file, bu_vls_addr(&str), vertex, normal, d1_intercept - dytred / 2, ztire, ztire - d1);
1510 
1511  VSET(vertex, 0, dytred/2, 0);
1512  VSET(normal, 0, 1, 0);
1513  bu_vls_sprintf(&str, "Ellipse-trim2%s.s", suffix);
1514  mk_cone(file, bu_vls_addr(&str), vertex, normal, d1_intercept - dytred / 2, ztire, ztire-d1);
1515 
1516  VSET(vertex, 0, -d1_intercept, 0);
1517  VSET(height, 0, d1_intercept*2, 0);
1518  bu_vls_sprintf(&str, "Ellipse-tread-inner-cut%s.s", suffix);
1519  mk_rcc(file, bu_vls_addr(&str), vertex, height, d1);
1520 
1521  BU_LIST_INIT(&tiretreadintercept.l);
1522  bu_vls_sprintf(&str, "Ellipse-constrain%s.s", suffix);
1523  (void)mk_addmember(bu_vls_addr(&str), &tiretreadintercept.l, NULL, WMOP_UNION);
1524  bu_vls_sprintf(&str, "Ellipse-trim1%s.s", suffix);
1525  (void)mk_addmember(bu_vls_addr(&str), &tiretreadintercept.l, NULL, WMOP_UNION);
1526  bu_vls_sprintf(&str, "Ellipse-trim2%s.s", suffix);
1527  (void)mk_addmember(bu_vls_addr(&str), &tiretreadintercept.l, NULL, WMOP_UNION);
1528  bu_vls_sprintf(&str, "tread-constrain%s.c", suffix);
1529  mk_lcomb(file, bu_vls_addr(&str), &tiretreadintercept, 0, NULL, NULL, NULL, 0);
1530 
1531  BU_LIST_INIT(&tiretreadsolid.l);
1532  bu_vls_sprintf(&str, "Ellipse-tread-outer%s.s", suffix);
1533  (void)mk_addmember(bu_vls_addr(&str), &tiretreadsolid.l, NULL, WMOP_UNION);
1534  bu_vls_sprintf(&str, "tread-constrain%s.c", suffix);
1535  (void)mk_addmember(bu_vls_addr(&str), &tiretreadsolid.l, NULL, WMOP_INTERSECT);
1536  bu_vls_sprintf(&str, "Ellipse-tread-inner-cut%s.s", suffix);
1537  (void)mk_addmember(bu_vls_addr(&str), &tiretreadsolid.l, NULL, WMOP_SUBTRACT);
1538  bu_vls_sprintf(&str, "tire-tread-outer%s.c", suffix);
1539  mk_lcomb(file, bu_vls_addr(&str), &tiretreadsolid, 0, NULL, NULL, NULL, 0);
1540 
1541  /* The tire tread shape needed is the subtraction of the slick
1542  * surface from the tread shape, which is handled here to supply
1543  * the correct shape for later tread work.
1544  */
1545  BU_LIST_INIT(&tiretreadshape.l);
1546  bu_vls_sprintf(&str, "tire-tread-outer%s.c", suffix);
1547  (void)mk_addmember(bu_vls_addr(&str), &tiretreadshape.l, NULL, WMOP_UNION);
1548 
1549  bu_vls_sprintf(&str, "tire-solid%s.c", suffix);
1550  (void)mk_addmember(bu_vls_addr(&str), &tiretreadshape.l, NULL, WMOP_SUBTRACT);
1551 
1552  bu_vls_sprintf(&str, "tire-tread-shape%s.c", suffix);
1553  mk_lcomb(file, bu_vls_addr(&str), &tiretreadshape, 0, NULL, NULL, NULL, 0);
1554 
1555 
1556  /* Call function to generate primitives and combinations for
1557  * actual tread pattern
1558  */
1559  bu_vls_sprintf(&str, "%s", suffix);
1560  TreadPattern(file, bu_vls_addr(&str), d1_intercept * 2, ztire - d1, ztire,
1561  number_of_tread_patterns, patterntype);
1562 
1563  for (i = 0; i < 5; i++)
1564  bu_free((char *)matrixelltred1[i], "matrixell1 element");
1565  bu_free((char *)matrixelltred1, "matrixell1");
1566 
1567  for (i = 0; i < 5; i++)
1568  bu_free((char *)matrixelltred2[i], "matrixell2 element");
1569  bu_free((char *)matrixelltred2, "matrixell2");
1570 
1571  bu_vls_free(&str);
1572 }
1573 
1574 
1575 typedef void (*MakeTreadProfile)
1576 (struct rt_wdb (*file),
1577  char *suffix,
1578  fastf_t *ell2coefficients,
1579  fastf_t ztire,
1580  fastf_t dztred,
1581  fastf_t d1,
1582  fastf_t dytred,
1583  fastf_t dyhub,
1584  fastf_t zhub,
1585  fastf_t dyside1,
1586  int number_of_tread_patterns,
1587  int patterntype);
1588 
1589 /**********************************************************************
1590  * *
1591  * MakeTire is the "top level" tire generation *
1592  * function - it is responsible for managing the *
1593  * matrices, calling the solvers with the correct *
1594  * input parameters, and using the other tire *
1595  * routines to define a hollow tire with tread. *
1596  * *
1597  * Decisions such as tread extrusion type, tread *
1598  * pattern, and whether to insert a wheel are *
1599  * handled at this level. *
1600  * *
1601  **********************************************************************/
1602 static void
1603 MakeTire(struct rt_wdb (*file), char *suffix, fastf_t dytred,
1604  fastf_t dztred, fastf_t d1, fastf_t dyside1, fastf_t zside1,
1605  fastf_t ztire, fastf_t dyhub, fastf_t zhub, fastf_t thickness,
1606  int tread_type, int number_of_tread_patterns,
1607  fastf_t tread_depth, fastf_t patterntype)
1608 {
1609  int i;
1610  fastf_t **matrixell1, **matrixell2, **matrixell3;
1611  fastf_t ell1coefficients[5], ell2coefficients[5], ell3coefficients[5];
1612  fastf_t ell1cadparams[5], ell2cadparams[5], ell3cadparams[5];
1613  fastf_t **matrixcut1, **matrixcut2, **matrixcut3;
1614  fastf_t cut1coefficients[5], cut2coefficients[5], cut3coefficients[5];
1615  fastf_t cut1cadparams[5], cut2cadparams[5], cut3cadparams[5];
1616  fastf_t ell1partial, cut1partial;
1617  fastf_t ztire_with_offset;
1618  fastf_t cut_dytred, cut_dztred;
1619  fastf_t cut_d1, cut_dyside1, cut_zside1, cut_ztire, cut_dyhub, cut_zhub;
1620  struct wmember tire;
1621  unsigned char rgb[3];
1622  MakeTreadProfile TreadProfile[2];
1623 
1624  struct bu_vls str = BU_VLS_INIT_ZERO;
1625  struct bu_vls str2 = BU_VLS_INIT_ZERO;
1626 
1627  /* Set Tire color */
1628  VSET(rgb, 40, 40, 40);
1629 
1630  if (tread_type != 0)
1631  ztire_with_offset = ztire - tread_depth*bu_units_conversion("in");
1632  else
1633  ztire_with_offset = ztire;
1634 
1635  matrixell1 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1636  for (i = 0; i < 5; i++)
1637  matrixell1[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1638 
1639  matrixell2 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1640  for (i = 0; i < 5; i++)
1641  matrixell2[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1642 
1643  matrixell3 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1644  for (i = 0; i < 5; i++)
1645  matrixell3[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1646 
1647 
1648  matrixcut1 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1649  for (i = 0; i < 5; i++)
1650  matrixcut1[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1651 
1652  matrixcut2 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1653  for (i = 0; i < 5; i++)
1654  matrixcut2[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1655 
1656  matrixcut3 = (fastf_t **)bu_malloc(5 * sizeof(fastf_t *), "matrixrows");
1657  for (i = 0; i < 5; i++)
1658  matrixcut3[i] = (fastf_t *)bu_malloc(6 * sizeof(fastf_t), "matrixcols");
1659 
1660  /* Find slick surface ellipse equation */
1661  Create_Ell1_Mat(matrixell1, dytred, dztred, d1, ztire_with_offset);
1662  Echelon(matrixell1);
1663  SolveEchelon(matrixell1, ell1coefficients);
1664  ell1partial = GetEllPartialAtPoint(ell1coefficients, dytred / 2,
1665  ztire_with_offset - dztred);
1666  /* Find outer side top ellipse equation */
1667  Create_Ell2_Mat(matrixell2, dytred, dztred, dyside1, zside1,
1668  ztire_with_offset, dyhub, zhub, ell1partial);
1669  Echelon(matrixell2);
1670  SolveEchelon(matrixell2, ell2coefficients);
1671  /* Find outer side bottom ellipse equation */
1672  Create_Ell3_Mat(matrixell3, dytred, dztred, dyside1, zside1,
1673  ztire_with_offset, dyhub, zhub, ell1partial);
1674  Echelon(matrixell3);
1675  SolveEchelon(matrixell3, ell3coefficients);
1676 
1677 
1678  /* Calculate BRL-CAD input parameters for outer tread ellipse */
1679  CalcInputVals(ell1coefficients, ell1cadparams);
1680  /* Calculate BRL-CAD input parameters for outer side top ellipse */
1681  CalcInputVals(ell2coefficients, ell2cadparams);
1682  /* Calculate BRL-CAD input parameters for outer side bottom ellipse */
1683  CalcInputVals(ell3coefficients, ell3cadparams);
1684 
1685  /* Insert outer tire volume */
1686  bu_vls_sprintf(&str, "-solid%s", suffix);
1687  MakeTireSurface(file, bu_vls_addr(&str), ell1cadparams, ell2cadparams,
1688  ell3cadparams, ztire_with_offset, dztred, dytred, dyhub,
1689  zhub, dyside1, zside1);
1690 
1691  TreadProfile[0] = &MakeTreadSolid;
1692  TreadProfile[1] = &MakeTreadSolid1;
1693 
1694  /* Make Tread solid and call routine to create tread */
1695 
1696  if (tread_type != 0) {
1697  (*TreadProfile[tread_type - 1])(file,
1698  suffix,
1699  ell2coefficients,
1700  ztire,
1701  dztred,
1702  d1,
1703  dytred,
1704  dyhub,
1705  zhub,
1706  dyside1,
1707  number_of_tread_patterns,
1708  patterntype);
1709  }
1710 
1711 
1712  /* Calculate input parameters for inner cut*/
1713  cut_ztire = ztire_with_offset-thickness;
1714  cut_dyside1 = dyside1 - thickness * 2;
1715  cut_zside1 = zside1;
1716  cut_d1 = d1;
1717  cut_dytred = dytred * cut_dyside1 / dyside1;
1718  cut_dztred = dztred * cut_ztire / ztire_with_offset;
1719  cut_dyhub = dyhub - thickness * 2;
1720  cut_zhub = zhub;
1721 
1722  /* Find inner tread cut ellipse equation */
1723  Create_Ell1_Mat(matrixcut1, cut_dytred, cut_dztred, cut_d1, cut_ztire);
1724  Echelon(matrixcut1);
1725  SolveEchelon(matrixcut1, cut1coefficients);
1726  cut1partial = GetEllPartialAtPoint(cut1coefficients, cut_dytred / 2, cut_ztire - cut_dztred);
1727 
1728  /* Find inner cut side top ellipse equation */
1729  Create_Ell2_Mat(matrixcut2, cut_dytred, cut_dztred, cut_dyside1, cut_zside1, cut_ztire, cut_dyhub, cut_zhub, cut1partial);
1730  Echelon(matrixcut2);
1731  SolveEchelon(matrixcut2, cut2coefficients);
1732 
1733  /* Find inner cut side bottom ellipse equation */
1734  Create_Ell3_Mat(matrixcut3, cut_dytred, cut_dztred, cut_dyside1, cut_zside1, cut_ztire, cut_dyhub, cut_zhub, cut1partial);
1735  Echelon(matrixcut3);
1736  SolveEchelon(matrixcut3, cut3coefficients);
1737 
1738  /* Calculate BRL-CAD input parameters for inner cut tread ellipse */
1739  CalcInputVals(cut1coefficients, cut1cadparams);
1740 
1741  /* Calculate BRL-CAD input parameters for inner cut side ellipse */
1742  CalcInputVals(cut2coefficients, cut2cadparams);
1743 
1744  /* Calculate BRL-CAD input parameters for inner cut side ellipse */
1745  CalcInputVals(cut3coefficients, cut3cadparams);
1746 
1747 
1748  /* Insert inner tire cut volume */
1749  bu_vls_sprintf(&str, "-cut%s", suffix);
1750  MakeTireSurface(file, bu_vls_addr(&str), cut1cadparams, cut2cadparams,
1751  cut3cadparams, cut_ztire, cut_dztred, cut_dytred,
1752  cut_dyhub, zhub, cut_dyside1, cut_zside1);
1753 
1754  /* Combine the tire solid, tire cut and tread into the final tire
1755  * region.
1756  */
1757  BU_LIST_INIT(&tire.l);
1758 
1759  bu_vls_sprintf(&str, "tire-solid%s.c", suffix);
1760  (void)mk_addmember(bu_vls_addr(&str), &tire.l, NULL, WMOP_UNION);
1761 
1762  bu_vls_sprintf(&str, "tire-cut%s.c", suffix);
1763  (void)mk_addmember(bu_vls_addr(&str), &tire.l, NULL, WMOP_SUBTRACT);
1764 
1765  bu_vls_sprintf(&str, "tread%s.c", suffix);
1766  if (tread_type != 0)
1767  (void)mk_addmember(bu_vls_addr(&str), &tire.l, NULL, WMOP_UNION);
1768 
1769  bu_vls_sprintf(&str, "tire%s.r", suffix);
1770  mk_lcomb(file, bu_vls_addr(&str), &tire, 1, "plastic", "di=.8 sp=.2", rgb, 0);
1771 
1772 
1773  for (i = 0; i < 5; i++)
1774  bu_free((char *)matrixell1[i], "matrixell1 element");
1775  bu_free((char *)matrixell1, "matrixell1");
1776  for (i = 0; i < 5; i++)
1777  bu_free((char *)matrixell2[i], "matrixell2 element");
1778  bu_free((char *)matrixell2, "matrixell2");
1779 
1780  for (i = 0; i < 5; i++)
1781  bu_free((char *)matrixcut1[i], "matrixcut1 element");
1782  bu_free((char *)matrixcut1, "matrixcut1");
1783  for (i = 0; i < 5; i++)
1784  bu_free((char *)matrixcut2[i], "matrixell2 element");
1785  bu_free((char *)matrixcut2, "matrixell2");
1786 
1787  bu_vls_free(&str);
1788  bu_vls_free(&str2);
1789 }
1790 
1791 
1792 static void
1793 MakeAirRegion(struct rt_wdb (*file), char *suffix, fastf_t dyhub, fastf_t zhub, int usewheel)
1794 {
1795  struct wmember wheelair;
1796  struct bu_list air;
1797  struct bu_vls str = BU_VLS_INIT_ZERO;
1798  point_t origin;
1799  vect_t height;
1800 
1801  VSET(origin, 0, -dyhub/2, 0);
1802  VSET(height, 0, dyhub, 0);
1803  bu_vls_sprintf(&str, "Air-Cyl%s.s", suffix);
1804  mk_rcc(file, bu_vls_addr(&str), origin, height, zhub);
1805 
1806  if (usewheel != 0) {
1807  BU_LIST_INIT(&wheelair.l);
1808  bu_vls_sprintf(&str, "Air-Cyl%s.s", suffix);
1809  (void)mk_addmember(bu_vls_addr(&str), &wheelair.l, NULL, WMOP_UNION);
1810  bu_vls_sprintf(&str, "wheel-rim-solid%s.c", suffix);
1811  (void)mk_addmember(bu_vls_addr(&str), &wheelair.l, NULL, WMOP_SUBTRACT);
1812  bu_vls_sprintf(&str, "wheel-air%s.c", suffix);
1813  mk_lcomb(file, bu_vls_addr(&str), &wheelair, 0, NULL, NULL, NULL, 0);
1814  }
1815 
1816  BU_LIST_INIT(&air);
1817 
1818  if (usewheel != 0) {
1819  bu_vls_sprintf(&str, "wheel-air%s.c", suffix);
1820  (void)mk_addmember(bu_vls_addr(&str), &air, NULL, WMOP_UNION);
1821  }
1822  bu_vls_sprintf(&str, "tire-cut%s.c", suffix);
1823  (void)mk_addmember(bu_vls_addr(&str), &air, NULL, WMOP_UNION);
1824  bu_vls_sprintf(&str, "air%s.r", suffix);
1825  mk_comb(file, bu_vls_addr(&str), &air, 1, "air", NULL, NULL, 0, 1, 0, 0, 0, 0, 0);
1826 
1827  bu_vls_free(&str);
1828 }
1829 
1830 
1831 /* Process command line arguments */
1832 static int
1833 ReadArgs(struct ged *gedp,
1834  int argc,
1835  const char *argv[],
1836  fastf_t *isoarray,
1837  fastf_t *overridearray,
1838  struct bu_vls *name,
1839  struct bu_vls *dimens,
1840  int *gen_name,
1841  int *treadtype,
1842  int *number_of_tread_patterns,
1843  fastf_t *tread_depth,
1844  fastf_t *tire_thickness,
1845  fastf_t *hub_width,
1846  int *pattern_type,
1847  fastf_t *zside1,
1848  int *usewheel)
1849 {
1850  int c = 0;
1851  int d1, d2, d3;
1852  int count;
1853  int tdtype, ptype, usewheelc;
1854  float hwidth, treadep, tthickness, zsideh;
1855  float fd1, fd2, fd3;
1856  char spacer1, tiretype;
1857  int have_name = 0;
1858 
1859  /* skip command name */
1860  bu_optind = 1;
1861 
1862  bu_opterr = 1;
1863 
1864  while ((c=bu_getopt(argc, (char * const *)argv, options)) != -1) {
1865  if (bu_optopt == '?')
1866  c='h';
1867  switch (c) {
1868  case 'a' :
1869  *gen_name = 1;
1870  have_name = 1;
1871  break;
1872  case 'n':
1873  have_name = 1;
1874  bu_vls_sprintf(name, "%s", bu_optarg);
1875  break;
1876  case 'c' :
1877  sscanf(bu_optarg, "%d", &count);
1878  *number_of_tread_patterns = count;
1879  break;
1880  case 'd' :
1881  sscanf(bu_optarg, "%d%c%d%c%d", &d1, &spacer1, &d2, &tiretype, &d3);
1882  bu_vls_printf(gedp->ged_result_str, "Dimensions: Width=%2.0dmm, Ratio=%2.0d, Wheel Diameter=%2.0din\n", d1, d2, d3);
1883  bu_vls_printf(dimens, "%d-%dR%d", d1, d2, d3);
1884  isoarray[0] = d1;
1885  isoarray[1] = d2;
1886  isoarray[2] = d3;
1887  break;
1888  case 'W':
1889  sscanf(bu_optarg, "%f", &fd1);
1890  overridearray[0] = fd1;
1891  break;
1892  case 'R':
1893  sscanf(bu_optarg, "%f", &fd2);
1894  overridearray[1] = fd2;
1895  break;
1896  case 'D':
1897  sscanf(bu_optarg, "%f", &fd3);
1898  overridearray[2] = fd3;
1899  break;
1900  case 'g':
1901  sscanf(bu_optarg, "%f", &treadep);
1902  *tread_depth = treadep;
1903  break;
1904  case 's':
1905  sscanf(bu_optarg, "%f", &zsideh);
1906  *zside1 = zsideh;
1907  break;
1908  case 'j':
1909  sscanf(bu_optarg, "%f", &hwidth);
1910  *hub_width = hwidth;
1911  break;
1912  case 'p':
1913  sscanf(bu_optarg, "%d", &ptype);
1914  *pattern_type = ptype;
1915  break;
1916  case 't':
1917  sscanf(bu_optarg, "%d", &tdtype);
1918  *treadtype = tdtype;
1919  break;
1920  case 'u':
1921  sscanf(bu_optarg, "%f", &tthickness);
1922  *tire_thickness = tthickness;
1923  break;
1924  case 'w':
1925  sscanf(bu_optarg, "%d", &usewheelc);
1926  *usewheel = usewheelc;
1927  break;
1928  default:
1929  show_help(gedp, argv[0]);
1930  if (c=='h')
1931  return GED_HELP;
1932  return GED_ERROR;
1933  }
1934  }
1935 
1936  if ((argc - bu_optind) == 1) {
1937  have_name = 1;
1938  bu_vls_sprintf(name, "%s", argv[bu_optind]);
1939  }
1940 
1941  if (!have_name) {
1942  bu_vls_printf(gedp->ged_result_str, "%s: need top-level object name\n", argv[0]);
1943  show_help(gedp, argv[0]);
1944  return GED_ERROR;
1945  }
1946 
1947  return GED_OK;
1948 }
1949 
1950 
1951 int
1952 ged_tire(struct ged *gedp, int argc, const char *argv[])
1953 {
1954  fastf_t dytred, dztred, dyside1, ztire, dyhub, zhub, d1;
1955  fastf_t width, ratio, wheeldiam;
1956  int bolts;
1957  fastf_t bolt_diam, bolt_circ_diam, spigot_diam, fixing_offset, bead_height, bead_width, rim_thickness;
1958  struct wmember wheel_and_tire;
1959  fastf_t isoarray[3];
1960  fastf_t overridearray[3];
1961  struct bu_vls name = BU_VLS_INIT_ZERO;
1962  struct bu_vls dimen = BU_VLS_INIT_ZERO;
1963  struct bu_vls str = BU_VLS_INIT_ZERO;
1964  int gen_name = 0;
1965  int tread_type = 0;
1966  int usewheel = 1;
1967  int number_of_tread_patterns = 30;
1968  fastf_t tread_depth = 11;
1969  fastf_t tire_thickness = 0;
1970  fastf_t hub_width = 0;
1971  int pattern_type = 0;
1972  fastf_t zside1 = 0;
1973  fastf_t tread_depth_float = tread_depth/32.0;
1974  int ret;
1975 
1978 
1979  /* initialize result */
1980  bu_vls_trunc(gedp->ged_result_str, 0);
1981 
1982  /* Set Default Parameters - 215/55R17 */
1983  isoarray[0] = 215;
1984  isoarray[1] = 55;
1985  isoarray[2] = 17;
1986 
1987  /* No overriding of the iso array by default */
1988  overridearray[0] = 0;
1989  overridearray[1] = 0;
1990  overridearray[2] = 0;
1991 
1992  /* Process arguments */
1993  ret = ReadArgs(gedp, argc, argv,
1994  isoarray, overridearray,
1995  &name, &dimen, &gen_name,
1996  &tread_type, &number_of_tread_patterns,
1997  &tread_depth, &tire_thickness, &hub_width,
1998  &pattern_type, &zside1, &usewheel);
1999 
2000  if (overridearray[0] > 0) isoarray[0] = overridearray[0];
2001  if (overridearray[1] > 0) isoarray[1] = overridearray[1];
2002  if (overridearray[2] > 0) isoarray[2] = overridearray[2];
2003 
2004  if (ret != GED_OK) {
2005  bu_vls_free(&name);
2006  bu_vls_free(&dimen);
2007  return ret;
2008  }
2009 
2011 
2012  /* Calculate floating point value for tread depth */
2013  tread_depth_float = tread_depth/32.0;
2014 
2015  /* Based on arguments, assign name for toplevel object; default of
2016  * "tire" is used unless overridden by user supplied options.
2017  * If -a option was not used, toplevel object keeps its entire name from -n argument (which is
2018  * overridden by the last argument on command line).
2019  */
2020  if (gen_name == 1) {
2021  if (bu_vls_strlen(&name) == 0)
2022  bu_vls_printf(&name,"tire-%d-%dR%d", (int)isoarray[0], (int)isoarray[1], (int)isoarray[2]);
2023  else
2024  bu_vls_printf(&name, "-%d-%dR%d", (int)isoarray[0], (int)isoarray[1], (int)isoarray[2]);
2025  }
2026 
2027  /* Use default dimensional info to create a suffix for names, if
2028  * not supplied in args.
2029  */
2030  if (bu_vls_strlen(&dimen) == 0)
2031  bu_vls_printf(&dimen, "-%d-%dR%d", (int)isoarray[0], (int)isoarray[1], (int)isoarray[2]);
2032 
2033  mk_id(gedp->ged_wdbp, "Tire");
2034 
2035  bu_vls_printf(gedp->ged_result_str, "width = %f\n", isoarray[0]);
2036  bu_vls_printf(gedp->ged_result_str, "ratio = %f\n", isoarray[1]);
2037  bu_vls_printf(gedp->ged_result_str, "radius = %f\n", isoarray[2]);
2038 
2039  /* Automatic conversion from std dimension info to geometry */
2040  width = isoarray[0];
2041  ratio = isoarray[1];
2042  wheeldiam = isoarray[2]*bu_units_conversion("in");
2043  dyside1 = width;
2044  ztire = ((width*ratio/100)*2+wheeldiam)/2;
2045  zhub = ztire-width*ratio/100;
2046  dytred = .8 * width;
2047  d1 = (ztire-zhub)/2.5;
2048 
2049  if (ZERO(hub_width))
2050  dyhub = dytred;
2051  else
2052  dyhub = hub_width*bu_units_conversion("in");
2053 
2054  if (ZERO(zside1))
2055  zside1 = 0.6*zhub + 0.4*ztire;
2056 /* The above is simplified from: */
2057 /* zside1 = ztire-((ztire-zhub)/2*1.2); */
2058 
2059  dztred = .001*ratio*zside1;
2060 
2061  if (ZERO(tire_thickness))
2062  tire_thickness = dztred;
2063 
2064  bu_vls_printf(gedp->ged_result_str, "radius of sidewall max: %f\n", zside1);
2065 
2066  if (tread_type == 1 && pattern_type == 0) pattern_type = 1;
2067  if (tread_type == 2 && pattern_type == 0) pattern_type = 2;
2068  if (pattern_type == 1 && tread_type == 0) tread_type = 1;
2069  if (pattern_type == 2 && tread_type == 0) tread_type = 2;
2070 
2071  /* Make the tire region */
2072  MakeTire(gedp->ged_wdbp, bu_vls_addr(&dimen), dytred, dztred,
2073  d1, dyside1, zside1, ztire, dyhub, zhub, tire_thickness,
2074  tread_type, number_of_tread_patterns, tread_depth_float, pattern_type);
2075 
2076 
2077  bolts = 5;
2078  bolt_diam = 10;
2079  bolt_circ_diam = 75;
2080  spigot_diam = 40;
2081  fixing_offset = 15;
2082  bead_height = 8;
2083  bead_width = 8;
2084  rim_thickness = tire_thickness/2.0;
2085 
2086  /* Make the wheel region*/
2087  if (usewheel != 0)
2088  MakeWheelRims(gedp->ged_wdbp, bu_vls_addr(&dimen),
2089  dyhub, zhub, bolts, bolt_diam, bolt_circ_diam,
2090  spigot_diam, fixing_offset, bead_height, bead_width, rim_thickness);
2091 
2092  /* Make the air region*/
2093  MakeAirRegion(gedp->ged_wdbp, bu_vls_addr(&dimen), dyhub, zhub, usewheel);
2094 
2095  /* Final top level providing a single name for tire+wheel */
2096  BU_LIST_INIT(&wheel_and_tire.l);
2097  bu_vls_sprintf(&str, "tire%s.r", bu_vls_addr(&dimen));
2098  (void)mk_addmember(bu_vls_addr(&str), &wheel_and_tire.l, NULL, WMOP_UNION);
2099  bu_vls_sprintf(&str, "air%s.r", bu_vls_addr(&dimen));
2100  (void)mk_addmember(bu_vls_addr(&str), &wheel_and_tire.l, NULL, WMOP_UNION);
2101  if (usewheel != 0)
2102  bu_vls_sprintf(&str, "wheel%s.r", bu_vls_addr(&dimen));
2103  (void)mk_addmember(bu_vls_addr(&str), &wheel_and_tire.l, NULL, WMOP_UNION);
2104 
2105  mk_lcomb(gedp->ged_wdbp, bu_vls_addr(&name), &wheel_and_tire, 0, NULL, NULL, NULL, 0);
2106 
2107  bu_vls_free(&str);
2108  bu_vls_free(&name);
2109  bu_vls_free(&dimen);
2110 
2111  return GED_OK;
2112 }
2113 
2114 
2115 /*
2116  * Local Variables:
2117  * mode: C
2118  * tab-width: 8
2119  * indent-tabs-mode: t
2120  * c-file-style: "stroustrup"
2121  * End:
2122  * ex: shiftwidth=4 tabstop=8
2123  */
#define GED_OK
Definition: ged.h:55
void(* MakeTreadProfile)(struct rt_wdb(*file), char *suffix, fastf_t *ell2coefficients, fastf_t ztire, fastf_t dztred, fastf_t d1, fastf_t dytred, fastf_t dyhub, fastf_t zhub, fastf_t dyside1, int number_of_tread_patterns, int patterntype)
Definition: tire.c:1576
int mk_rcc(struct rt_wdb *fp, const char *name, const point_t base, const vect_t height, fastf_t radius)
void bu_vls_strncat(struct bu_vls *vp, const char *s, size_t n)
Definition: vls.c:390
fastf_t C[2 *MAX_CNT+1][2 *MAX_CNT+1]
Definition: dsp_brep.cpp:38
Definition: list.h:118
Definition: ged.h:338
Definition: clone.c:90
#define VSET(a, b, c, d)
Definition: color.c:53
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define M_PI
Definition: fft.h:35
int mk_ell(struct rt_wdb *fp, const char *name, const point_t center, const vect_t a, const vect_t b, const vect_t c)
HIDDEN void show_help(const char *name, const char *optstr)
Definition: human.c:1514
int ReadArgs(struct ged *gedp, int argc, const char *argv[], struct bu_vls *name, struct bu_list *sections, fastf_t *mean_outer_diameter, fastf_t *wire_diameter, fastf_t *helix_angle, fastf_t *pitch, int *nt, int *start_cap_type, int *end_cap_type, fastf_t *overall_length, int *lhf)
Definition: coil.c:326
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Definition: wdb.h:64
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
#define WMOP_SUBTRACT
Definition: wdb.h:886
int mk_cone(struct rt_wdb *fp, const char *name, const point_t base, const vect_t dirv, fastf_t height, fastf_t rad1, fastf_t rad2)
#define WMOP_UNION
Definition: wdb.h:887
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
ustring width
void rt_curve_free(struct rt_curve *crv)
Definition: sketch.c:2092
struct bu_list l
Definition: wdb.h:65
#define GED_ERROR
Definition: ged.h:61
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
#define mk_lcomb(_fp, _name, _headp, _rf, _shadername, _shaderargs, _rgb, _inh)
Definition: wdb.h:820
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
#define SKETCHNUM1
Definition: tire.c:988
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
#define WMOP_INTERSECT
Definition: wdb.h:885
int bu_optopt
Definition: globals.c:90
double bu_units_conversion(const char *str)
Definition: units.c:234
#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
void bu_vls_sprintf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:707
#define LOOKUP_QUIET
Definition: raytrace.h:893
char * options
Definition: gqa.c:56
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
#define UNUSED(parameter)
Definition: common.h:239
struct wmember * mk_addmember(const char *name, struct bu_list *headp, mat_t mat, int op)
Definition: reg.c:181
#define GED_CHECK_EXISTS(_gedp, _name, _noisy, _flags)
Definition: ged.h:171
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
#define SKETCHNUM2
Definition: tire.c:890
int mk_comb(struct rt_wdb *wdbp, const char *combname, struct bu_list *headp, int region_kind, const char *shadername, const char *shaderargs, const unsigned char *rgb, int id, int air, int material, int los, int inherit, int append_ok, int gift_semantics)
Definition: reg.c:230
#define ZERO(val)
Definition: units.c:38
#define BU_LIST_INIT(_hp)
Definition: list.h:148
#define BU_LIST_POP_T(hp, type)
Definition: list.h:259
#define D2R(x)
Definition: tire.c:42
int bu_opterr
Definition: globals.c:88
int mk_id(struct rt_wdb *fp, const char *title)
Definition: id.c:43
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
int mk_extrusion(struct rt_wdb *fp, const char *name, const char *sketch_name, const point_t V, const vect_t h, const vect_t u_vec, const vect_t v_vec, int keypoint)
Definition: extrude.c:41
#define RT_SKETCH_INTERNAL_MAGIC
Definition: magic.h:108
#define GED_HELP
Definition: ged.h:62
#define A
Definition: msr.c:51
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int mk_sketch(struct rt_wdb *fp, const char *name, const struct rt_sketch_internal *skt)
Definition: sketch.c:35
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
int ged_tire(struct ged *gedp, int argc, const char *argv[])
Definition: tire.c:1952
#define CURVE_LSEG_MAGIC
Definition: magic.h:199
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
Definition: vls.h:56
double fastf_t
Definition: defines.h:300
int mk_eto(struct rt_wdb *wdbp, const char *name, const point_t vert, const vect_t norm, const vect_t smajor, fastf_t rrot, fastf_t sminor)
Definition: wdb.c:571