/* Generator for the HPG 2022 Cornell Box conference gift laser cut outlines. */
/* This file can be modified to allow for different sizes or manufacturing process. */
/* Output is an SVG file, written to standard output. */
/* Created by Andrew Garrard and in the public domain to do with as you will,
   with no warranty provided. */

#include <stdio.h>

/* All measurements are in mm. */

/* This is the edge length of the interior cube.
   12cm chosen to make the box a size for golf/squash/table tennis balls and a reasonable desk tidy. */
float inner_diameter = 120;

/* The versions mass produced for HPG 2022 were in 6mm birch plywood. */
float wood_thickness = 6;

/* The thickness of the sections outside the slots. */
float arm_thickness = 10;

/* The amount by which the base sits above the surface in desk tidy mode. */
float base_inset = 10;

/* This is the gap around sections that fit together, hopefully masked by the thickness of paint.
   1mm was tried and is far too loose; 0.1mm is quite tight, but that's good once constructed. */
float tolerance = 0.1;

/* Amount by which the outer end of the slot is wider than the inner end (-ve for narrower).
 Note that the front of the slot is narrower, which means the arms flex out slightly and grip. */
float edge_extra_tolerance = -0.1666667;

/* Extra wiggle room at the end of a slot if needed (particularly if corners are rounded). */
float beam_slot_end_tolerance = 0;

/* Additional thickness for paint where there is overlap. Highly variable in practice. */
float paint_thickness = 0.5;

/* Nominal laser beam width from "Bespoke Laser UK" who cut the mass-produced boxes.
   Other reports have been 0.076mm and 0.1666667mm depending on the cutter.
   The outlines are offset such that the shape is defined by the edge, not center, of the beam. */
float laser_width = 0.2;

/* The width of the slots holding the (desk tidy) base/(Box mode) back face. */
float slot_width = 60.0;

/* Size of the hole for the light; 1" chosen to fit suitable object such as furniture tube end caps. */
float light_edge = 25.4;

/* Laser cutting shows paths where the laser should travel, with thickness of the laser width.
   Not laser cutting shows filled shapes that correspond to the cut pieces.
   Note: laser path sections are generated separately in SVG for compatibility. */
int lasercut = 1;

/* Laser Cut UK encoding: all full-depth cuts in red.
   Other manuacturer encoding: external edges in green, interior edges in blue, ruler in red.
   In both cases, solid engraved regions are black. */
int one_cut_colour = 1;

/* Manually set the proof size (this was the proof size returned by Bespoke Laser UK). */
/* Set to 0 to calculate a tight fit from scratch. */
float outWidth = 500;
float outHeight = 290;

/* Calculated value to simplify calculations. */ 
float painted_wood_thickness;

void prefix()
{
  float ruler_line_width = laser_width;
  if (!lasercut) { laser_width = 0; }
  /* N.B. SVG coordinates are from top left. */
  float calculatedWidth = 3*(2*arm_thickness + 2*painted_wood_thickness + 2*tolerance + inner_diameter + 2*laser_width) + 20;
  float calculatedHeight = 2*(base_inset + painted_wood_thickness + tolerance + inner_diameter + 2*laser_width) + 10;
  float xOffset = 0.0f;
  float yOffset = 0.0f;
  if (outWidth) xOffset = (outWidth - calculatedWidth)/2; else outWidth = calculatedWidth;
  if (outHeight) yOffset = (outHeight - calculatedHeight)/2; else outHeight = calculatedHeight;
  printf("<?xml version=\"1.0\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \n  \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg width=\"%.3fmm\" height=\"%.3fmm\" viewBox=\"%.3f %.3f %.3f %.3f\" version=\"1.1\"\n     xmlns=\"http://www.w3.org/2000/svg\">\n",
	 outWidth, outHeight,
	 -xOffset, -yOffset,
	 outWidth, outHeight);
  printf("<style type=\"text/css\">\n");
  printf(".ruler { fill:none; stroke: #FF0000; stroke-width: %.3f; stroke-linecap: round; }\n", ruler_line_width);
  if (lasercut) {
    if (one_cut_colour) {
      /* Laser Cut UK colour coding (external cuts and interior cuts in red) */
      printf("path { fill: none; stroke: #FF0000; stroke-width: %.3f; stroke-linecap: round; }\n", laser_width);
      printf(".H, .P, .G, .year { fill: black; stroke: none; }\n");
      printf(".cutout { stroke: #FF0000; }\n");
    } else {
      /* Alternate encoding (exterior cuts in green, interior cuts in blue) */
      printf("path { fill: none; stroke: #00FF00; stroke-width: %.3f; stroke-linecap: round; }\n", laser_width);
      printf(".H, .P, .G, .year { fill: black; stroke: none; }\n");
      printf(".cutout { stroke: #0000FF; }\n");
    }
  } else {
    printf("path { fill: #F0D890; stroke: none; }\n");
    printf(".H, .P, .G, .year { fill: #A06000; stroke: none; }\n");
  }
  printf("</style>\n");
}

float logosvgwide = 502.1f;
float logosvghigh = 292.7f;

const char *hpglogo =
"<path class=\"G\" d=\"M390.9,151.7h-29c-24.9,0-25.9-24-20.4-40.9l15-46.3c3.1-9.6,1.5-19.6-1.2-28.5h10.5l1.9-5.9H353 "
"c-1.7-4-4-7.9-6.7-11.4h25l1.8-5.7h-32.3c-5.5-5.5-12.4-9.9-20.6-12.4h56.9h62.7v0c37.2,0,70,28.7,59.9,60l-2.3,7.2h-62.7 "
"l12.9-39.9c2.1-6.4-4.9-15.6-11.5-15.7l-18,55.6H374c13.7,0,38.3,18,32.2,36.8l-11.4,35.1c8.2,0,16.9-1,18.9-7.1l8.4-25.8 "
"c4.2-12.9-9.8-26.3-21.7-33.2h18.8h28.3c24,0,38.9,28.2,32.4,48.3l-29.1,90C460.9,180.4,428.1,151.7,390.9,151.7z\"/> "
"<path class=\"P\" d=\"M281.2,0.5H161.9c7.9,2.5,14.9,6.9,20.3,12.4h32.3l-1.8,5.7h-25c2.7,3.5,5,7.4,6.7,11.4H209l-1.9,6h-10.5 "
"c2.7,8.9,4.2,19.2,1.2,28.5l-28.2,87.3h62.7l13.4-41.4H294c17.9,0,32.7-5.5,38.1-22.2l8.9-27.6C351.2,29.2,318.5,0.5,281.2,0.5z "
" M289,27.8l-19.6,60.5c-2,6.1-10.8,7.1-18.9,7.1l27-83.4C284.1,12.1,291.1,21.3,289,27.8z\"/> "
"<path class=\"H\" d=\"M138.6,2.3l-27.8,86c-2,6.1-10.8,7.1-18.9,7.1l30.7-94.9H59.9H3.3C11.2,3,18.1,7.4,23.8,12.9h32L54,18.6H29.3 "
"C32,22.1,34.3,26,36,30h14.4l-1.9,5.9H38.2c2.7,8.9,4.1,19,1,28.5l0,0L11,151.7h62.7l13.4-41.4h16.6l-13.4,41.4H153l29.5-91.2 "
"C191.1,33.8,168.6,9,138.6,2.3z\"/> "
"<path class=\"year\" d=\"M66.3,268.8h50.8l-7.1,21.9H30.2l2.9-9c2-6.1,4.8-11.6,8.4-16.5c3.6-4.9,7.6-9.3,12-13.1 "
"c4.4-3.9,8.9-7.3,13.6-10.3c4.7-3,9.1-5.7,13.2-8.1c4.3-2.5,8.2-4.9,11.6-7.2c3.4-2.3,6.4-4.6,8.9-6.8c2.5-2.3,4.6-4.5,6.3-6.9 "
"c1.6-2.3,2.9-4.8,3.7-7.4c1.7-5.1,1.5-9-0.6-11.6c-2.1-2.6-6.1-3.9-12-3.9c-10.3,0-21.5,4.1-33.6,12.3l7.5-23.2 "
"c12.6-6.7,25.5-10.1,38.6-10.1c6.1,0,11.3,0.8,15.6,2.4c4.3,1.6,7.7,3.9,10,6.8c2.4,3,3.8,6.5,4.2,10.7c0.4,4.2-0.2,8.9-1.9,14.1 "
"c-1.8,5.5-4.2,10.4-7.3,14.7c-3.1,4.3-6.6,8.2-10.6,11.7c-4,3.5-8.2,6.7-12.9,9.7c-4.6,2.9-9.4,5.8-14.2,8.5 "
"c-3.3,1.9-6.5,3.8-9.6,5.6c-3.1,1.9-5.9,3.7-8.3,5.5c-2.5,1.8-4.6,3.6-6.2,5.3C67.9,265.6,66.8,267.2,66.3,268.8z\"/> "
"<path class=\"year\" d=\"M161.3,292.8c-28.5,0-36.3-20-23.4-60.1c6.7-20.8,15.7-36.6,26.9-47.5c11.2-10.9,24.2-16.4,38.9-16.4 "
"c27.9,0,35.2,20.4,22.1,61.1c-6.6,20.3-15.4,35.9-26.5,46.7C188.1,287.4,175.5,292.8,161.3,292.8z M196,188.9 "
"c-11.4,0-21.8,14.4-31.1,43.1c-8.7,27-7.5,40.6,3.7,40.6c10.9,0,20.9-13.9,29.9-41.8C207.5,202.9,206.7,188.9,196,188.9z\"/> "
"<path class=\"year\" d=\"M246.2,268.8H297l-7.1,21.9h-79.8l2.9-9c2-6.1,4.8-11.6,8.4-16.5c3.6-4.9,7.6-9.3,12-13.1 "
"c4.4-3.9,8.9-7.3,13.6-10.3c4.7-3,9.1-5.7,13.2-8.1c4.3-2.5,8.2-4.9,11.6-7.2c3.4-2.3,6.4-4.6,8.9-6.8c2.5-2.3,4.6-4.5,6.3-6.9 "
"c1.6-2.3,2.9-4.8,3.7-7.4c1.7-5.1,1.5-9-0.6-11.6c-2.1-2.6-6.1-3.9-12-3.9c-10.3,0-21.5,4.1-33.6,12.3l7.5-23.2 "
"c12.6-6.7,25.5-10.1,38.6-10.1c6.1,0,11.3,0.8,15.6,2.4c4.3,1.6,7.7,3.9,10,6.8c2.4,3,3.8,6.5,4.2,10.7c0.4,4.2-0.2,8.9-1.9,14.1 "
"c-1.8,5.5-4.2,10.4-7.3,14.7c-3.1,4.3-6.6,8.2-10.6,11.7c-4,3.5-8.2,6.7-12.9,9.7c-4.6,2.9-9.4,5.8-14.2,8.5 "
"c-3.3,1.9-6.5,3.8-9.6,5.6c-3.1,1.9-5.9,3.7-8.3,5.5c-2.5,1.8-4.6,3.6-6.2,5.3C247.8,265.6,246.7,267.2,246.2,268.8z\"/> "
"<path class=\"year\" d=\"M336.1,268.8H387l-7.1,21.9h-79.8l2.9-9c2-6.1,4.8-11.6,8.4-16.5c3.6-4.9,7.6-9.3,12-13.1 "
"c4.4-3.9,8.9-7.3,13.6-10.3c4.7-3,9.1-5.7,13.2-8.1c4.3-2.5,8.2-4.9,11.6-7.2c3.4-2.3,6.4-4.6,8.9-6.8c2.5-2.3,4.6-4.5,6.3-6.9 "
"c1.6-2.3,2.9-4.8,3.7-7.4c1.7-5.1,1.5-9-0.6-11.6c-2.1-2.6-6.1-3.9-12-3.9c-10.3,0-21.5,4.1-33.6,12.3l7.5-23.2 "
"c12.6-6.7,25.5-10.1,38.6-10.1c6.1,0,11.3,0.8,15.6,2.4c4.3,1.6,7.7,3.9,10,6.8c2.4,3,3.8,6.5,4.2,10.7c0.4,4.2-0.2,8.9-1.9,14.1 "
"c-1.8,5.5-4.2,10.4-7.3,14.7c-3.1,4.3-6.6,8.2-10.6,11.7c-4,3.5-8.2,6.7-12.9,9.7c-4.6,2.9-9.4,5.8-14.2,8.5 "
"c-3.3,1.9-6.5,3.8-9.6,5.6c-3.1,1.9-5.9,3.7-8.3,5.5s-4.6,3.6-6.2,5.3C337.7,265.6,336.6,267.2,336.1,268.8z\"/>";

void bottom_face(float xoff, float yoff, float *width, float *height)
{
  printf("<path d=\"");
  printf("M %.3f %.3f ", xoff, yoff);
  printf("v %.3f ",
	 base_inset + painted_wood_thickness + tolerance +
	 inner_diameter + laser_width);
  printf("h %.3f ", arm_thickness - edge_extra_tolerance + laser_width);
  printf("l %.3f %.3f ",
	 edge_extra_tolerance - beam_slot_end_tolerance,
	 -(base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2));
  printf("h %.3f ",
	 beam_slot_end_tolerance + painted_wood_thickness + tolerance - laser_width);
  printf("v %.3f ",
	 base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2);
  printf("h %.3f ",
	 inner_diameter + laser_width);
  printf("v %.3f ",
	 -(base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2));
  printf("h %.3f ",
	 beam_slot_end_tolerance + painted_wood_thickness + tolerance - laser_width);
  printf("l %.3f %.3f ",
	 edge_extra_tolerance - beam_slot_end_tolerance,
	 base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2);
  printf("h %.3f ", arm_thickness - edge_extra_tolerance + laser_width);
  printf("v %.3f ",
	 -(base_inset + painted_wood_thickness + tolerance +
	   inner_diameter + laser_width));
  printf("h %.3f Z ",
	 -(2*arm_thickness + 2*painted_wood_thickness + 2*tolerance + laser_width + inner_diameter));
  if (lasercut) {
    printf("\" /><path class=\"cutout\" d=\"");
  }
  printf("m %3f %3f ",
	 arm_thickness + painted_wood_thickness + inner_diameter/2 - slot_width/2 + laser_width,
	 inner_diameter + laser_width);
  printf("h %3f ",
	 slot_width - laser_width + 2*tolerance);
  printf("v %3f ",
	 painted_wood_thickness + tolerance - laser_width);
  printf("h %3f ",
	 -(slot_width - laser_width + 2*tolerance));
  printf("v %3f ",
	 -(painted_wood_thickness + tolerance - laser_width));
  printf("Z\" />\n");
  printf("<g transform=\"translate(%3f, %3f) scale(%.3f)\">\n",
	 arm_thickness + painted_wood_thickness + tolerance + inner_diameter/6.0f + laser_width,
	 inner_diameter/2.0f + laser_width - logosvghigh * inner_diameter /3.0f / logosvgwide,
	 inner_diameter * 2.0f/3.0f / logosvgwide);
  printf("%s", hpglogo);
  printf("</g>\n");
  *width = 2*arm_thickness + 2*painted_wood_thickness + 2*tolerance + inner_diameter + 2*laser_width;
  *height = base_inset + painted_wood_thickness + tolerance + inner_diameter + 2*laser_width;
}

void top_face(float xoff, float yoff, float *width, float *height)
{
  printf("<path d=\"");
  printf("M %.3f %.3f ", xoff, yoff);
  printf("v %.3f ",
	 base_inset + painted_wood_thickness + tolerance +
	 inner_diameter + laser_width);
  printf("h %.3f ", arm_thickness - edge_extra_tolerance + laser_width);
  printf("l %.3f %.3f ",
	 edge_extra_tolerance - beam_slot_end_tolerance,
	 -(base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2));
  printf("h %.3f ",
	 beam_slot_end_tolerance + painted_wood_thickness + tolerance - laser_width);
  printf("v %.3f ",
	 base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2);
  printf("h %.3f ",
	 inner_diameter + laser_width);
  printf("v %.3f ",
	 -(base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2));
  printf("h %.3f ",
	 beam_slot_end_tolerance + painted_wood_thickness + tolerance - laser_width);
  printf("l %.3f %.3f ",
	 edge_extra_tolerance - beam_slot_end_tolerance,
	 base_inset + painted_wood_thickness + tolerance*1.5f + inner_diameter/2);
  printf("h %.3f ", arm_thickness - edge_extra_tolerance + laser_width);
  printf("v %.3f ",
	 -(base_inset + painted_wood_thickness + tolerance +
	   inner_diameter + laser_width));
  printf("h %.3f Z ",
	 -(2*arm_thickness + 2*painted_wood_thickness + 2*tolerance + laser_width + inner_diameter));
  if (lasercut) {
    printf("\" /><path class=\"cutout\" d=\"M %3f %3f ",
	   arm_thickness + painted_wood_thickness + inner_diameter/2 - slot_width/2 + laser_width + xoff,
	   inner_diameter + laser_width + yoff);
  } else {
    printf("m %3f %3f ",
	   arm_thickness + painted_wood_thickness + inner_diameter/2 - slot_width/2 + laser_width,
	   inner_diameter + laser_width);
  }
  printf("h %3f ",
	 slot_width - laser_width + 2*tolerance);
  printf("v %3f ",
	 painted_wood_thickness + tolerance - laser_width);
  printf("h %3f ",
	 -(slot_width - laser_width + 2*tolerance));
  printf("v %3f Z ",
	 -(painted_wood_thickness + tolerance - laser_width));
  if (lasercut) {
    printf("\" /><path class=\"cutout\" d=\"");
  }
  printf("M %3f %3f ",
	 arm_thickness + painted_wood_thickness + tolerance + inner_diameter/2 - light_edge/2 + laser_width + xoff,
	 inner_diameter/2 - light_edge/2 + laser_width + yoff);
  printf("h %3f ",
	 light_edge - laser_width);
  printf("v %3f ",
	 light_edge - laser_width);
  printf("h %3f ",
	 -(light_edge - laser_width));
  printf("v %3f ",
	 -(light_edge - laser_width));
  printf("Z\" />\n");
  *width = 2*arm_thickness + 2*painted_wood_thickness + 2*tolerance + inner_diameter + 2*laser_width;
  *height = base_inset + painted_wood_thickness + tolerance + inner_diameter + 2*laser_width;
}

void side_face(float xoff, float yoff, float *width, float *height)
{
  printf("<path d=\"");
  printf("M %.3f %.3f ", xoff, yoff);
  printf("v %.3f ",
	 base_inset + painted_wood_thickness + tolerance +
	 inner_diameter + laser_width);
  printf("h %.3f ",
	 2*arm_thickness + 2*painted_wood_thickness + 2*tolerance + laser_width + inner_diameter);
  printf("v %.3f ",
	 -(base_inset + painted_wood_thickness + tolerance +
	   inner_diameter + laser_width));
  printf("h %.3f ", -(arm_thickness - edge_extra_tolerance + laser_width));
  printf("l %.3f %.3f ",
	 beam_slot_end_tolerance - edge_extra_tolerance,
	 tolerance/2 + inner_diameter/2);
  printf("h %.3f ",
	 -(beam_slot_end_tolerance + painted_wood_thickness + tolerance - laser_width));
  printf("v %.3f ",
	 -(tolerance/2 + inner_diameter/2));
  printf("h %.3f ",
	 -(inner_diameter + laser_width));
  printf("v %.3f ",
	 tolerance/2 + inner_diameter/2);
  printf("h %.3f ",
	 -(beam_slot_end_tolerance + painted_wood_thickness + tolerance - laser_width));
  printf("l %.3f %.3f ",
	 beam_slot_end_tolerance - edge_extra_tolerance,
	 -(tolerance/2 + inner_diameter/2));
  printf("h %.3f Z ", -(arm_thickness - edge_extra_tolerance + laser_width));
  if (lasercut) {
    printf("\" /><path class=\"cutout\" d=\"");
    printf("M %3f %3f ",
	   arm_thickness + painted_wood_thickness + inner_diameter/2 - slot_width/2 + laser_width + xoff,
	   inner_diameter + laser_width + yoff);
  } else {
    printf("m %3f %3f ",
	   arm_thickness + painted_wood_thickness + inner_diameter/2 - slot_width/2 + laser_width,
	   inner_diameter + laser_width);
  }
  printf("h %3f ",
	 slot_width - laser_width + 2*tolerance);
  printf("v %3f ",
	 painted_wood_thickness + tolerance - laser_width);
  printf("h %3f ",
	 -(slot_width - laser_width + 2*tolerance));
  printf("v %3f ",
	 -(painted_wood_thickness + tolerance - laser_width));
  printf("Z\" />\n");
  *width = 2*arm_thickness + 2*painted_wood_thickness + 2*tolerance + inner_diameter + 2*laser_width;
  *height = base_inset + painted_wood_thickness + tolerance + inner_diameter + 2*laser_width;
}

void base(float xoff, float yoff, float *width, float *height)
{
  printf("<path d=\"");
  printf("M %.3f %.3f ",
	 xoff + painted_wood_thickness + tolerance + arm_thickness,
	 yoff + painted_wood_thickness/2);
  printf("v %.3f ", (inner_diameter - slot_width)/2);
  printf("h %.3f ", -painted_wood_thickness);
  printf("v %.3f ", slot_width + laser_width);
  printf("h %.3f ", painted_wood_thickness);
  printf("v %.3f ", (inner_diameter - slot_width)/2);
  printf("h %.3f ", (inner_diameter - slot_width)/2);
  printf("v %.3f ", painted_wood_thickness/2);
  printf("h %.3f ", slot_width + laser_width);
  printf("v %.3f ", -painted_wood_thickness/2);
  printf("h %.3f ", (inner_diameter - slot_width)/2);
  printf("v %.3f ", -(inner_diameter - slot_width)/2);
  printf("h %.3f ", painted_wood_thickness);
  printf("v %.3f ", -(slot_width + laser_width));
  printf("h %.3f ", -painted_wood_thickness);
  printf("v %.3f ", -(inner_diameter - slot_width)/2);
  printf("h %.3f ", -(inner_diameter - slot_width)/2);
  printf("v %.3f ", -painted_wood_thickness/2);
  printf("h %.3f ", -(slot_width + laser_width));
  printf("v %.3f ", painted_wood_thickness/2);
  printf("h %.3f ", -(inner_diameter - slot_width)/2);
  printf("Z\" />\n");
  printf("<g transform=\"translate(%3f, %3f) scale(%.3f)\">\n",
	 xoff + painted_wood_thickness + arm_thickness + tolerance + inner_diameter/6.0f + laser_width,
	 yoff + painted_wood_thickness/2 + inner_diameter/2.0f + laser_width - logosvghigh * inner_diameter /3.0f / logosvgwide,
	 inner_diameter * 2.0f/3.0f / logosvgwide);
  printf("%s", hpglogo);
  printf("</g>\n");
}

void ruler(float xoff, float yoff)
{
  int i;
  printf("<g transform=\"translate(%.3f, %.3f) rotate(-90)\">\n/",
	 xoff, yoff);
  printf("<path class=\"ruler\" d=\"M 0 0 ");
  for (i = 0; i <= 100; i++) {
    printf("v %.3f m %.3f %.3f ", i%10?3.f:5.f, 1.0f, i%10?-3.f:-5.f);
  }
  printf("Z\" />\n");
  for (i = 0; i <= 10; i++) {
    printf("<text x=\"%.3f\" y=\"%.3f\" fill=\"#FF0000\" text-anchor=\"middle\" font-size=\"5px\">%d</text>\n",
	   10.0f * i, 10.0f, i);
  }
  printf("<text x=\"%.3f\" y=\"%.3f\" fill=\"#FF0000\" text-anchor=\"middle\" font-size=\"5px\">cm</text>\n",
	 110.0f, 10.0f);
  printf("</g>\n");
}

void suffix()
{
  printf("</svg>\n");
}

int main(int argc, char **argv)
{
  float w, h;
  if (argc != 12 && argc != 1) {
    printf("Usage: %s, or %s inner_diameter wood_thickness arm_thickness base_inset tolerance edge_extra_tolerance beam_slot_end_tolerance paint_thickness laser_width slot_width light_edge\n", argv[0], argv[0]);
    return 0;
  } else if (argc == 12) {
    sscanf(argv[1], "%f", &inner_diameter);
    sscanf(argv[2], "%f", &wood_thickness);
    sscanf(argv[3], "%f", &arm_thickness);
    sscanf(argv[4], "%f", &base_inset);
    sscanf(argv[5], "%f", &tolerance);
    sscanf(argv[6], "%f", &edge_extra_tolerance);
    sscanf(argv[7], "%f", &beam_slot_end_tolerance);
    sscanf(argv[8], "%f", &paint_thickness);
    sscanf(argv[9], "%f", &laser_width);
    sscanf(argv[10], "%f", &slot_width);
    sscanf(argv[11], "%f", &light_edge);
  }
  painted_wood_thickness = wood_thickness + paint_thickness;
  prefix();
  bottom_face(laser_width/2,laser_width/2,&w,&h);
  top_face(laser_width/2,h+10.0f+laser_width/2,&w,&h);
  side_face(w+10.0f+laser_width/2,laser_width/2, &w, &h);
  side_face(w+10.0f+laser_width/2,h+10.0f+laser_width/2, &w, &h);
  side_face(2*(w+10.0f)+laser_width/2,laser_width/2, &w, &h);
  base(2*(w+10.0f)+laser_width/2,h+10.0f+laser_width/2, &w, &h);
  ruler(2.0f*w+25.0f - 10.0f + laser_width/2, 2.0f*h + laser_width/2);
  suffix();
  return 0;
}
