Svg box

From Hamsterworks Wiki!

Jump to: navigation, search

This C coding sample was finished in December 2014.

I'm building a 200mm high digital clock for the local swimming pool - without my glasses I can't read the small analogue clocks on the wall. I picked up the 200mm display segments from Seeed Studio (http://www.seeedstudio.com/depot/7-Segment-Display-8-Inches-Red-p-1194.html) needed to create a high quality enclosure to mount them on and house the electronics.

This is what the design looks like before I paint it and then properly mount the segments:

Svg box 7seg.jpg

I have never performed any laser cutting. On the weekend I dropped into Fab Lab xChc (http://www.fablabxchc.org.nz/) and the kind folk there got me started. A nice format for the laser cutter to work with is SVG, which I have never used before. After a bit of research it turns out to be pretty easy to work with. Soon after I had a program to output a panel with the required drill holes I was inspired by the case of a project featured on Hackaday (http://hackaday.com/2014/12/01/a-z80-computer-with-switches-and-blinkenlights/). Not being sure of the size of enclosure I wanted, and not wanting to spend hours tweaking a CAD design I wrote a small bit of C to generate the box outline. The team at Fab Lab xChc were very impressed that it was a success first time.

Here's what design looks like:

Svg box.png

And the SVG file that describes it:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="67cm" height="32cm" viewBox="0 0 6700 3200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<polyline points="50,50 201,50 201,80 470,80 470,50 743,50 743,80 1012,80 1012,50 1285,50 1285,80 1554,80 1554,50 1827,50 1827,80
 2096,80 2096,50 2369,50 2369,80 2638,80 2638,50 2911,50 2911,80 3189,80 3189,50 3462,50 3462,80 3731,80 3731,50 4004,50 4004,80 
 4273,80 4273,50 4546,50 4546,80 4815,80 4815,50 5088,50 5088,80 5357,80 5357,50 5630,50 5630,80 5899,80 5899,50 6050,50 6050,201
 6020,201 6020,399 6050,399 6050,601 6020,601 6020,799 6050,799 6050,1001 6020,1001 6020,1199 6050,1199 6050,1401 6020,1401 6020,1599
 6050,1599 6050,1801 6020,1801 6020,1999 6050,1999 6050,2201 6020,2201 6020,2399 6050,2399 6050,2550 5899,2550 5899,2520 5630,2520
 5630,2550 5357,2550 5357,2520 5088,2520 5088,2550 4815,2550 4815,2520 4546,2520 4546,2550 4273,2550 4273,2520 4004,2520 4004,2550
 3731,2550 3731,2520 3462,2520 3462,2550 3189,2550 3189,2520 2911,2520 2911,2550 2638,2550 2638,2520 2369,2520 2369,2550 2096,2550
 2096,2520 1827,2520 1827,2550 1554,2550 1554,2520 1285,2520 1285,2550 1012,2550 1012,2520 743,2520 743,2550 470,2550 470,2520 
 201,2520 201,2550 50,2550 50,2399 80,2399 80,2201 50,2201 50,1999 80,1999 80,1801 50,1801 50,1599 80,1599 80,1401 50,1401 50,1199
 80,1199 80,1001 50,1001 50,799 80,799 80,601 50,601 50,399 80,399 80,201 50,201 50,50" fill="none" stroke="black" stroke-width="3" />
<polyline points="6130,50 6251,50 6251,80 6449,80 6449,50 6570,50 6570,199 6600,199 6600,401 6570,401 6570,599 6600,599 6600,801 
 6570,801 6570,999 6600,999 6600,1201 6570,1201 6570,1399 6600,1399 6600,1601 6570,1601 6570,1799 6600,1799 6600,2001 6570,2001
 6570,2199 6600,2199 6600,2401 6570,2401 6570,2550 6449,2550 6449,2520 6251,2520 6251,2550 6130,2550 6130,2401 6100,2401 6100,2199
 6130,2199 6130,2001 6100,2001 6100,1799 6130,1799 6130,1601 6100,1601 6100,1399 6130,1399 6130,1201 6100,1201 6100,999 6130,999
 6130,801 6100,801 6100,599 6130,599 6130,401 6100,401 6100,199 6130,199 6130,50" fill="none" stroke="black" stroke-width="3" />
<polyline points="80,2630 199,2630 199,2600 472,2600 472,2630 741,2630 741,2600 1014,2600 1014,2630 1283,2630 1283,2600 1556,2600
 1556,2630 1825,2630 1825,2600 2098,2600 2098,2630 2367,2630 2367,2600 2640,2600 2640,2630 2909,2630 2909,2600 3191,2600 3191,2630
 3460,2630 3460,2600 3733,2600 3733,2630 4002,2630 4002,2600 4275,2600 4275,2630 4544,2630 4544,2600 4817,2600 4817,2630 5086,2630
 5086,2600 5359,2600 5359,2630 5628,2630 5628,2600 5901,2600 5901,2630 6020,2630 6020,2749 6050,2749 6050,2951 6020,2951 6020,3070
 5901,3070 5901,3100 5628,3100 5628,3070 5359,3070 5359,3100 5086,3100 5086,3070 4817,3070 4817,3100 4544,3100 4544,3070 4275,3070
 4275,3100 4002,3100 4002,3070 3733,3070 3733,3100 3460,3100 3460,3070 3191,3070 3191,3100 2909,3100 2909,3070 2640,3070 2640,3100
 2367,3100 2367,3070 2098,3070 2098,3100 1825,3100 1825,3070 1556,3070 1556,3100 1283,3100 1283,3070 1014,3070 1014,3100 741,3100
 741,3070 472,3070 472,3100 199,3100 199,3070 80,3070 80,2951 50,2951 50,2749 80,2749 80,2630" fill="none" stroke="black" stroke-width="3" />
</svg>
 

I've also got the code that adds the drill-holes for the segments, so if anybody wants it just drop me an email.

svg_box.c

If you ever need to quickly generate a box for a project, you are more than welcome to use this to generate your basic box.

 
/*********************************************************
 * svg_box.c
 *
 * Generate an SVG file for a box.
 *
 * Author Mike Field <hamster@snap.net.nz>
 *
 ********************************************************/

#include <stdio.h>

/*******************************************************************
* Settings that control the size of the box - set as static
* values because I can't be bothered with argument parsing
*******************************************************************/
/* Box dimensions (int 1/10ths of a mm, and how many mitres to have, divided by two */
static int w = 6000, div_w = 10;
static int h = 2500, div_h = 5;
static int d =  500, div_d = 0;

/* How big the corner mitres are, in 1/10ths of a mm */
static int corner = 150;
/* Thickness for the material (depth of the mitres) in 1/10ths of a mm */
static int thick = 30;

/* Frame around the sides panels */
static int frame = 50;

/* Fudge Factor for kerf (width of cuts) - must be even as it is divided by two */
static int cut_width = 2;

/*******************************************************************/
/* For getting the correct space characters in the polyline object */
static int polyFirst;
/*******************************************************************/

static void PolyStart(void) {
   printf("<polyline points=\"");
   polyFirst = 1;
}

static void PolyPoint(int x, int y) {
   if(!polyFirst)
     printf(" ");
   polyFirst = 0;
   printf("%i,%i",x,y);
}

static void PolyEnd(void) {
  printf("\" fill=\"none\" stroke=\"black\" stroke-width=\"3\" />\r\n");
}

void MitrePanel(int x, int y, int w, int h, int corner_size,  int div_x, int div_y, int thick, int invertX, int invertY) {
   int a,b,i,d, half_cut;
   x = x-w/2+ (invertX ? thick : 0);
   y = y-h/2+ (invertY ? thick : 0);
   PolyStart();
   /////////////////////////////////
   // Top side
   /////////////////////////////////
   PolyPoint(x,y);
   x += corner_size- (invertX ? thick : 0);
   half_cut = (invertY ? -cut_width/2 : cut_width/2);
   d = (invertY ? -1 : 1);
   PolyPoint(x+half_cut,y);
   y += thick *d; d = -d;
   PolyPoint(x+half_cut,y);
   half_cut = -half_cut;

   // All but the center one
   a = (w-2*corner_size) / (2*div_x+1);
   // the center one
   b = w-2*corner_size-a*(2*div_x);

   for(i = 0; i < div_x; i++)
   {
     x += a;
     PolyPoint(x+half_cut,y);
     y += thick *d; d = -d;
     PolyPoint(x+half_cut,y);
     half_cut = -half_cut;
   }


   x+= b;
   PolyPoint(x+half_cut,y);
   y += thick *d; d = -d;
   PolyPoint(x+half_cut,y);
   half_cut = -half_cut;

   for(i = 0; i < div_x; i++)
   {
     x += a;
     PolyPoint(x+half_cut,y);
     y += thick *d; d = -d;
     PolyPoint(x+half_cut,y);
     half_cut = -half_cut;
   }

   x += corner_size- (invertX ? thick : 0);
   PolyPoint(x,y);

   /////////////////////////////////
   // Right Side
   /////////////////////////////////
   half_cut = (invertX ? -cut_width/2 : cut_width/2);
   y += corner_size - (invertY ? thick : 0);

   d = (invertX ? 1 : -1);
   PolyPoint(x,y+half_cut);
   x += thick *d; d = -d;
   PolyPoint(x,y+half_cut);
   half_cut = -half_cut;

   // All but the center one
   a = (h-2*corner_size) / (2*div_y+1);
   // the center one
   b = h-2*corner_size-a*(2*div_y);

   for(i = 0; i < div_y; i++)
   {
     y += a;
     PolyPoint(x,y+half_cut);
     x += thick *d; d = -d;
     PolyPoint(x,y+half_cut);
     half_cut = -half_cut;
   }


   y += b;
   PolyPoint(x,y+half_cut);
   x += thick *d; d = -d;
   PolyPoint(x,y+half_cut);
   half_cut = -half_cut;

   for(i = 0; i < div_y; i++)
   {
     y += a;
     PolyPoint(x,y+half_cut);
     x += thick *d; d = -d;
     PolyPoint(x,y+half_cut);
     half_cut = -half_cut;
   }

   y += corner_size - (invertY ? thick : 0);
   PolyPoint(x,y);

   /////////////////////////////////////////////////////
   // bottom Side
   /////////////////////////////////////////////////////
   half_cut = (invertY ? cut_width/2 : -cut_width/2);
   x -= corner_size-(invertX ? thick : 0);

   d = (invertY ? 1 : -1);
   PolyPoint(x+half_cut,y);
   y += thick *d; d = -d;
   PolyPoint(x+half_cut,y);
   half_cut = -half_cut;

   // All but the center one
   a = (w-2*corner_size) / (2*div_x+1);
   // the center one
   b = w-2*corner_size-a*(2*div_x);

   for(i = 0; i < div_x; i++)
   {
     x -= a;
     PolyPoint(x+half_cut,y);
     y += thick *d; d = -d;
     PolyPoint(x+half_cut,y);
     half_cut = -half_cut;
   }


   x -= b;
   PolyPoint(x+half_cut,y);
   y += thick *d; d = -d;
   PolyPoint(x+half_cut,y);
   half_cut = -half_cut;

   for(i = 0; i < div_x; i++)
   {
     x -= a;
     PolyPoint(x+half_cut,y);
     y += thick *d; d = -d;
     PolyPoint(x+half_cut,y);
     half_cut = -half_cut;
   }

   x -= corner_size-(invertX ? thick : 0);
   PolyPoint(x,y);

   /////////////////////////////////////////////////////
   // Left side
   /////////////////////////////////////////////////////
   half_cut = (invertX ? cut_width/2 : -cut_width/2);
   y -= corner_size-(invertY ? thick : 0);

   d = (invertX ? -1 : 1);
   PolyPoint(x,y+half_cut);
   x += thick *d; d = -d;
   PolyPoint(x,y+half_cut);
   half_cut = -half_cut;

   // All but the center one
   a = (h-2*corner_size) / (2*div_y+1);
   // the center one
   b = h-2*corner_size-a*(2*div_y);

   for(i = 0; i < div_y; i++)
   {
     y -= a;
     PolyPoint(x,y+half_cut);
     x += thick *d; d = -d;
     PolyPoint(x,y+half_cut);
     half_cut = -half_cut;
   }


   y -= b;
   PolyPoint(x,y+half_cut);
   x += thick *d; d = -d;
   PolyPoint(x,y+half_cut);
   half_cut = -half_cut;

   for(i = 0; i < div_y; i++)
   {
     y -= a;
     PolyPoint(x,y+half_cut);
     x += thick *d; d = -d;
     PolyPoint(x,y+half_cut);
     half_cut = -half_cut;
   }

   y -= corner_size - (invertY ? thick : 0);
   PolyPoint(x,y);
   PolyEnd();
}

void StartDoc(int w, int h) {
  w = (w+99)/100*100;
  h = (h+99)/100*100;
  printf("<?xml version=\"1.0\" standalone=\"no\"?>\r\n");
  printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n");
  printf("<svg width=\"%icm\" height=\"%icm\" viewBox=\"0 0 %i %i\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\r\n", w/100, h/100, w,h);

}

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

int main(int argc, char *argv[])
{
  StartDoc(frame*3+w+d,frame*3+h+d);


  MitrePanel(frame+w/2,        frame+h/2,         w, h, corner, div_w, div_h, thick,0,0);
  MitrePanel(frame+w+frame+d/2,frame+h/2,         d, h, corner, div_d, div_h, thick,1,0);
  MitrePanel(frame+w/2,        frame+h+frame+d/2, w, d, corner, div_w, div_d, thick,1,1);

  EndDoc();
  return 0;
}

Personal tools