View Single Post
Old 12-01-21, 10:50 PM
  #15  
JohnDThompson 
Old fart
 
JohnDThompson's Avatar
 
Join Date: Nov 2004
Location: Appleton WI
Posts: 24,936

Bikes: Several, mostly not name brands.

Mentioned: 153 Post(s)
Tagged: 0 Thread(s)
Quoted: 3571 Post(s)
Liked 3,367 Times in 1,916 Posts
If you have a C compiler, this open-source code will print a template you can use to miter tubes:

/*----------------------------------------------------------------------------*/
/* Written by Eric Fahlgren efahl@adams.com */
/* November 1994 */
/* */
/* Adapted by Jason Byrne in 2015 to print a miter on each side of tube. */
/* jbyrne27@gmail.com */
/* */
/* Distribute as you see fit. Please retain my name and email address above. */
/* */
/* */
/* If you find any bugs or anomalous behavior, please email me with an */
/* example. */
/*----------------------------------------------------------------------------*/

void fix_libc_(){} /* Subvert stupidity of acc on Sparc */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

/*----------------------------------------------------------------------------*/

#define PI 3.14159265359
#define HALF_PI 1.57079632679489661923132169164E+0
#define TWO_PI 6.28318530717958647692528676656E+0
#define SEGS 36
#define INC (TWO_PI / SEGS)

#define DTOR 1.74532925199432957692369076849E-2 /* PI / 180 */
#define RTOD 5.72957795130823208767981548141E+1 /* 180 / PI */

#define DEG(r) ((r) * RTOD)
#define DEGREES(r) ((r) * RTOD)
#define RAD(d) ((d) * DTOR)
#define RADIANS(d) ((d) * DTOR)

/*----------------------------------------------------------------------------*/

typedef enum { FALSE, TRUE } BOOL;

typedef enum { out_PS, out_VIEW } OutputDest;
OutputDest Output = out_PS;

/*----------------------------------------------------------------------------*/

static double PS_MaxY = 0.0;
static BOOL PS_GuideLines = TRUE;

void PS_Header(double R1, double R2, double R3, double F, double A, double A2, char *Label, double P, double *paperSize)
{
if ( Output != out_PS ) return;

printf("%%!PS-Adobe-2.0\n");
printf("gsave\n");
printf("initgraphics\n");
printf("<</PageSize [%g %g]>>setpagedevice", paperSize[0]*72.0, paperSize[1]*72.0); //Units are inches*72
printf("\n");
printf("72 dup scale\n");
printf("0.5 0.5 translate\n");
printf("0.005 setlinewidth\n");
printf("/tick { lineto 0 0.05 rlineto 0 -0.10 rlineto 0 0.05 rlineto } def\n");
printf("/pnum { 10 string cvs show } def\n");
printf("/Courier findfont 10 72 div scalefont setfont\n");
printf("gsave\n");
printf(" 90 rotate\n");
printf(" 1.0 -1.5 translate\n");
printf(" newpath 0.1 1.25 moveto (%s) show\n", Label);
printf(" newpath 0.1 1.00 moveto (D this tube = ) show %f pnum\n", 2*R1);
printf(" newpath 0.1 0.75 moveto (D butt to R = ) show %f pnum\n", 2*R2);
printf(" newpath 0.1 0.50 moveto (D butt to L = ) show %f pnum\n", 2*R3);
printf(" newpath 0.1 0.25 moveto (Offset = ) show %f pnum\n", F );
printf(" newpath 0.1 0.00 moveto (Angle R = ) show %f pnum\n", 90.0-DEGREES(A) );
printf(" newpath 0.1 -0.25 moveto (Angle L = ) show %f pnum\n", 90.0-DEGREES(A2) );
printf(" newpath 0.1 -0.50 moveto (Phase = ) show %f pnum\n", DEGREES(P) );
printf("grestore\n");
printf("newpath 0 0 moveto\n");
}

/*----------------------------------------------------------------------------*/

void PS_Line(double x, double y)
{
if ( Output != out_PS ) return;
if ( y > PS_MaxY ) PS_MaxY = y;
printf("%f %f tick\n", x, y);
}

/*----------------------------------------------------------------------------*/

void PS_Trailer(double x, double y)
{
if ( Output != out_PS ) return;
// printf("0 %f rlineto\n", -y);
printf("closepath stroke\n");
if ( PS_GuideLines ) {
printf("newpath 0 0 moveto 0 %f lineto stroke\n", PS_MaxY);
printf("newpath %f 0 moveto %f %f lineto stroke\n", x/4.0, x/4.0, PS_MaxY);
printf("newpath %f 0 moveto %f %f lineto stroke\n", x/2.0, x/2.0, PS_MaxY);
printf("newpath %f 0 moveto %f %f lineto stroke\n", 3*x/4.0, 3*x/4.0, PS_MaxY);
printf("newpath %f 0 moveto %f %f lineto stroke\n", x, x, PS_MaxY);
printf("newpath 0 %f moveto %f %f lineto stroke\n", PS_MaxY, x, PS_MaxY);
}
printf("showpage\n");
printf("grestore\n");
}

/*----------------------------------------------------------------------------*/

void VIEW_Header(double R1, double R2, double F, double A, char *Label)
{
if ( Output != out_VIEW ) return;
printf("var cre var=xxR1 rea=%f uni=length\n", R1);
printf("var cre var=xxR2 rea=%f uni=length\n", R2);
printf("var cre var=xxF rea=%f uni=length\n", F);
printf("var cre var=xxA rea=%f uni=angle\n", DEGREES(A));
printf("geo cre cur pol pol=.mod1.ground.pol1 loc= &\n");
}

/*----------------------------------------------------------------------------*/

void VIEW_Line(double x, double y, double z)
{
if ( Output != out_VIEW ) return;
printf("%f, %f, %f, &\n", x, y, z);
}

/*----------------------------------------------------------------------------*/

void VIEW_Trailer(double x, double y, double z)
{
if ( Output != out_VIEW ) return;
printf("%f,%f,%f\n", x, y, z);
}

/*----------------------------------------------------------------------------*/

void Header(double R1, double R2, double R3, double F, double A, double A2, char *Label, double P, double *paperSize)
{
switch ( Output ) {
case out_PS : PS_Header (R1, R2, R3, F, A, A2, Label, P, paperSize); break;
case out_VIEW: VIEW_Header(R1, R2, F, A, Label); break;
}
}

/*----------------------------------------------------------------------------*/

void Line(double x, double y, double z, double l)
{
switch ( Output ) {
case out_PS : PS_Line (l, z); break;
case out_VIEW: VIEW_Line(x, y, z); break;
}
}

/*----------------------------------------------------------------------------*/

void Trailer(double x, double y, double z, double l)
{
switch ( Output ) {
case out_PS : PS_Trailer(l, z); break;
case out_VIEW: VIEW_Trailer(x, y, z); break;
}
}

/*----------------------------------------------------------------------------*/
double DrawMiter(double R1, double R2, double F, double A, double L, double Z, double P)
{
int i;
double x, y, z;
double theta;
double R2sqr = R2 * R2;
double m = tan(A); /* Slope of line */
double m2 = tan(A / 2.0); /* To compute intercept */
double b, d;
double points [SEGS+1];
double zmax;
double zmin;

zmax = -1000;
zmin = 1000;
for ( i = 0; i <= SEGS; i++ ) {
theta = -HALF_PI + i * INC + P;
x = R1 * cos(theta) - F; /* x with offset */
y = R1 * sin(theta); /* y */
if ( R2 == 0.0 ) {
z = 0.0; /* z against a flat plate */
b = 0.0;
}
else {
d = R2sqr - x*x; /* z against tube */
z = d < 0.0 ? 0.0 : sqrt(d); /* z without tilt */
b = m * m2 * z; /* Compute intercept of tilted line */
}
z += y * m + b; /* Compute z increment from tilted line */
x += F; /* Move x back where it should be */
if (z > zmax)
zmax = z;
if (z < zmin)
zmin = z;
points[i] = z;
}

for ( i = 0; i <= SEGS; i++ ) {
if ( Output == out_PS ) {
Line(x, y, points[i]+L+Z-zmin, i * INC * R1);
}
}
return zmax-zmin;
}


/*----------------------------------------------------------------------------*/

void WritePoints(double R1, double R2, double R3, double F, double A, double A2, double L, double P, char *Label, double *paperSize)
{
double x, y;
double Z;

Header(R1, R2, R3, F, A, A2, Label, P, paperSize);
Z=DrawMiter(R1, R3, F, A2, 0, 0, 0);
Line(x, y, 0, SEGS * INC * R1);
Line(x, y, 0, 0);
DrawMiter(R1, R2, F, PI-A, L, Z, P);
Line(x, y, 0, SEGS * INC * R1);
Line(x, y, 0, 0);
Trailer(x, y, 0, (SEGS) * INC * R1);
}

/*----------------------------------------------------------------------------*/

void Usage(void)
{
fprintf(stderr, "miter [-dnumber] [-Dnumber] [-p] [-anumber] [-onumber] [-lstring] [-v]\n");
fprintf(stderr, " Example:\n");
fprintf(stderr, " miter -d1.0 -D1.25 -a27 -l"Top tube to head tube"\n");
fprintf(stderr, "\n");
fprintf(stderr, " -d - diameter of mitered tube; default 1.0\n");
fprintf(stderr, " -D - diameter of right tube butting against; default 1.0\n");
fprintf(stderr, " -E - diameter of left tube butting against; default 1.0\n");
fprintf(stderr, " -L - length between deepest point (facing towards middle of tube) of each miter; default 4.0\n");
fprintf(stderr, " -p - butt against flat plate\n");
fprintf(stderr, " -o - offset of d centerline from D centerline; default 0.0\n");
fprintf(stderr, " -a - included angle between centerlines on right side; default 90\n");
fprintf(stderr, " -b - included angle between centerlines on left side; default 90\n");
fprintf(stderr, " -P - phase angle between centerlines of each miter; default 0\n");
fprintf(stderr, " -l - label to print on output\n");
fprintf(stderr, " -v - print output for ADAMS/View\n");
fprintf(stderr, " -g - suppress guidelines on PostScript\n");
fprintf(stderr, " -Z - paper size:\n");
fprintf(stderr, " 0: ANSI A (8.5x11)\n");
fprintf(stderr, " 1: ANSI B (11x17)\n");
fprintf(stderr, " 2: ANSI C (17x22)\n");
fprintf(stderr, " 3: ANSI D (22x34)\n");
fprintf(stderr, " 4: ANSI E (34x44)\n");
fprintf(stderr, " 5: A0 (33.1x46.8)\n");
fprintf(stderr, " 6: A1 (23.4x33.1)\n");
fprintf(stderr, " 7: A2 (16.5x23.4)\n");
fprintf(stderr, " 8: A3 (11.7x16.5)\n");
fprintf(stderr, " 9: A4 (8.3x11.7)\n");
fprintf(stderr, " 10: A5 (5.8x8.3)\n");
fprintf(stderr, " 11: B0 (39.4x55.7)\n");
fprintf(stderr, " 12: B1 (27.8x39.4)\n");
fprintf(stderr, " 13: B2 (19.7x27.8)\n");
fprintf(stderr, " 14: B3 (13.9x19.7)\n");
fprintf(stderr, " 15: B4 (9.8x13.9)\n");
fprintf(stderr, " 16: B5 (6.9x9.8)\n");
exit(1);
}

/*----------------------------------------------------------------------------*/

int main(int ArgC, char *ArgV[])
{
int iArg;
double R1 = 0.5; /* Radius of tube for which we are cutting the miter */
double R2 = 0.5; /* Radius of tube against which we are butting on right*/
double R3 = 0.5; /* Radius of tube against which we are butting on left*/
double L = 4.0; /* Length of mitered tube between deepest point of each miter */
double F = 0.0; /* Offset of R1 centerline from R2 centerline */
double A = 0.0; /* Angle between R1 centerline and R2 centerline */
double P = 0.0; /* Angle between centerline of each miter */
double A2 = 0.0; /* Angle between R1 centerline and R2 centerline on other end*/
char *Label = ""; /* Any comment you wish to provide */
int Z = 0;
double paperSize[2]; /*Paper size in postscript units (inches*72) */

for ( iArg = 1; iArg < ArgC; iArg++ ) {
if ( ArgV[iArg][0] != '-' ) Usage();

switch ( ArgV[iArg][1] ) {
case 'l':
Label = &ArgV[iArg][2];
break;

case 'd':
sscanf(&ArgV[iArg][2], "%lf", &R1);
R1 /= 2.0;
break;

case 'D':
sscanf(&ArgV[iArg][2], "%lf", &R2);
R2 /= 2.0;
break;

case 'E':
sscanf(&ArgV[iArg][2], "%lf", &R3);
R3 /= 2.0;
break;

case 'L':
sscanf(&ArgV[iArg][2], "%lf", &L);
break;

case 'p':
R2 = 0.0;
break;

case 'a':
sscanf(&ArgV[iArg][2], "%lf", &A);
A = RADIANS(90.0 - A);
break;

case 'b':
sscanf(&ArgV[iArg][2], "%lf", &A2);
A2 = RADIANS(90.0 - A2);
break;

case 'P':
sscanf(&ArgV[iArg][2], "%lf", &P);
P = RADIANS(P);
break;

case 'o':
sscanf(&ArgV[iArg][2], "%lf", &F);
break;

case 'v':
Output = out_VIEW;
break;

case 'g':
PS_GuideLines = FALSE;
break;

case 'Z':
sscanf(&ArgV[iArg][2], "%d", &Z);
break;

default:
Usage();
break;
}
}


switch (Z) {
case 0:
paperSize[0] = 8.5; paperSize[1] = 11; break;
case 1:
paperSize[0] = 11; paperSize[1] = 17; break;
case 2:
paperSize[0] = 17; paperSize[1] = 22; break;
case 3:
paperSize[0] = 22; paperSize[1] = 34; break;
case 4:
paperSize[0] = 34; paperSize[1] = 44; break;
case 5:
paperSize[0] = 33.1; paperSize[1] = 46.8; break;
case 6:
paperSize[0] = 23.4; paperSize[1] = 33.1; break;
case 7:
paperSize[0] = 16.5; paperSize[1] = 23.4; break;
case 8:
paperSize[0] = 11.7; paperSize[1] = 16.5; break;
case 9:
paperSize[0] = 8.3; paperSize[1] = 11.7; break;
case 10:
paperSize[0] = 5.8; paperSize[1] = 8.3; break;
case 11:
paperSize[0] = 39.4; paperSize[1] = 55.7; break;
case 12:
paperSize[0] = 27.8; paperSize[1] = 39.4; break;
case 13:
paperSize[0] = 19.7; paperSize[1] = 27.8; break;
case 14:
paperSize[0] = 13.9; paperSize[1] = 19.7; break;
case 15:
paperSize[0] = 9.8; paperSize[1] = 13.9; break;
case 16:
paperSize[0] = 6.9; paperSize[1] = 9.8; break;
default:
paperSize[0] = 8.5; paperSize[1] = 11; break;
}

WritePoints(R1, R2, R3, F, A, A2, L, P, Label, paperSize);

#ifdef TESTING
WritePoints(0.75, 1.625, 0.0, RADIANS(atan(1.7/16.0)));
WritePoints(0.75 / 2.0, 1.625 / 2.0, 0.0, atan(1.7/16.0), "Chain stay to BB");
WritePoints(0.5 / 2.0, 1.125 / 2.0, 0.25, RADIANS(45.0), "Right seat stay to seat tube");
WritePoints(0.5 / 2.0, 1.125 / 2.0, -0.25, RADIANS(45.0), "Left seat stay to seat tube");
WritePoints(1.00/2, 1.25/2, 0.0, RADIANS(90.0 - 72.0), "Top tube to head tube");
WritePoints(1.00/2, 1.125/2, 0.0, RADIANS(90.0 - 75.0), "Top tube to seat tube");
#endif

exit(0);
}
JohnDThompson is offline