#include <stdio.h> #include <math.h> #include <time.h> #include <stdlib.h> #include "gpc.h" #include "svg.h" // outside dimensions of tray - eventually these may be command-line parameters... float wood = 4.65; //mm float KERF = 0.57; //mm really tight fit, but comes loose after a few removals and reinsertions float HALF_KERF; #define W 30 /* left-right */ //#define H 380 /* top-bottom */ #define H 30 /* top-bottom */ #define D 30 /* front-back */ // -------------------------------------------------------- int mm(int m) { return m*100; } int in(int m) { return m*2540; } int ft(int m) { return in(m*12); } int mm_f(float m) { return (int)roundf(m*100.0); } int in_f(float m) { return (int)roundf(m*2540.0); } int ft_f(float m) { return in_f(m*12.0); } #define RED "#FF0000" #define GREEN "#00FF00" #define BLUE "#0000FF" #define PINK "#FFAAAA" #define WHITE "#FFFFFF" #define BLACK "#000000" #define BACKGROUND "#DDDDFF" #define ENGRAVE_TEXT BLACK #define COMMENT_TEXT BLUE #define HAIRLINE_f 0.01 #define VISIBLE_LINE_f 0.2 #define LIVE_FILL WHITE #define PREVIEW_FILL PINK static svg* psvg; int PREVIEW; // value of these depends on PREVIEW float linewidth_f; char *fill; float stage_width = 0.0, stage_height = 0.0; void hole_mm_f(float w, float h, float x, float y) { if (x+w > stage_width) stage_width = x+w; if (y+h > stage_height) stage_height = y+h; if (PREVIEW) { svg_rectangle(psvg, /* size */ mm_f(w), mm_f(h), /* at */ mm_f(x), mm_f(y), BACKGROUND, /* outline */ BACKGROUND, /* border-width */mm_f(linewidth_f), /* radius x,y */ 0,0); } else { svg_rectangle(psvg, /* size */ mm_f(w), mm_f(h), /* at */ mm_f(x), mm_f(y), WHITE, /* outline */ RED, /* border-width */mm_f(linewidth_f), /* radius x,y */ 0,0); } } void face(int w, int h, int x, int y) { if (x+w > stage_width) stage_width = x+w; if (y+h > stage_height) stage_height = y+h; svg_rectangle(psvg, /* size */ mm(w), mm(h), /* at */ mm(x), mm(y), fill, /* outline */ RED, /* border-width */mm_f(linewidth_f), /* radius x,y */ 0,0); } #ifdef NEVER svg_text(psvg, /* at */ mm(x+10), mm(y+25+1), "sans-serif", mm(3), /* fill colour */ COMMENT_TEXT, /* stroke colour */ COMMENT_TEXT, "5cm x 5cm square", ""); #endif void toothcomb(float center_x, float center_y, int cuts, float spacing, int cut_depth) { int i; float start_x; if ((cuts & 1) == 0) { // even number of cuts start_x = center_x - spacing/2 - ((cuts-1)>>1)*spacing; } else { // odd number of cuts start_x = center_x - (cuts>>1)*spacing; } for (i = 0; i < cuts; i++) { svg_line(psvg, RED, /* width */ mm_f(linewidth_f), /* from */ mm_f(start_x), mm_f(center_y), /* to */ mm_f(start_x), mm_f(center_y+cut_depth)); start_x += spacing; } } void front_face(int x, int y) { int order; int steps = (W - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides for (order = 0; order <= 1; order++) { // preview actions then live actions // cut before the face falls out if (order == (PREVIEW&1)) { hole_mm_f(wood, H/3.0 - 2.0*KERF, /* at */ x+5 /*+ wood*/, y+5 + H/2.0 - H/6.0 + KERF); hole_mm_f(wood, H/3.0 - 2.0*KERF, /* at */ x+5 + W-wood/*-wood*/, y+5 + H/2.0 - H/6.0 + KERF); } if (order == 0) face(W, H, x+5, y+5); } } void back_face(int x, int y) { int order; int steps = (W - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides for (order = 0; order <= 1; order++) { // preview actions then live actions if (order == (PREVIEW&1)) { hole_mm_f(wood, H/3.0 - 2.0*KERF, /* at */ x+5+W+5 /*+ wood*/, y+5 + H/2.0 - H/6.0 + KERF); hole_mm_f(wood, H/3.0 - 2.0*KERF, /* at */ x+5+W+5 + W-wood/*-wood*/, y+5 + H/2.0 - H/6.0 + KERF); } if (order == 0) face(W, H, x+5+W+5, y+5); } } void left_face(int x, int y) { int order; int steps = (D - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides for (order = 0; order <= 1; order++) { // preview actions then live actions if (order == (PREVIEW&1)) { hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5 /*+ wood*/, y+5); hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5 + D-wood/*-wood*/, y+5); hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5 /*+ wood*/, y+5 - H/3.0 + H); hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5 + D-wood/*-wood*/, y+5 - H/3.0 + H); } if (order == 0) face(D, H, x+5+W+5+W+5, y+5); } } void right_face(int x, int y) { int order; int steps = (D - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides for (order = 0; order <= 1; order++) { // preview actions then live actions if (order == (PREVIEW&1)) { hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5+D+5 /*+ wood*/, y+5); hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5+D+5 + D-wood/*-wood*/, y+5); hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5+D+5 /*+ wood*/, y+5 - H/3.0 + H); hole_mm_f(wood, H/3.0, /* at */ x+5+W+5+W+5+D+5 + D-wood/*-wood*/, y+5 - H/3.0 + H); } if (order == 0) face(D, H, x+5+W+5+W+5+D+5, y+5); } } void base(int x, int y) { face(D, W, x+5+W+5+W+5+D+5+D+5, y+5); } void ruler(int x, int y) { svg_line(psvg, RED, /* width */ mm_f(linewidth_f), /* from */ mm(x), mm(y), /* to */ mm(x+50), mm(y)); svg_line(psvg, RED, /* width */ mm_f(linewidth_f), /* from */ mm(x), mm(y), /* to */ mm(x), mm(y-5)); svg_line(psvg, RED, /* width */ mm_f(linewidth_f), /* from */ mm(x+50), mm(y), /* to */ mm(x+50), mm(y-5)); svg_text(psvg, /* at */ mm(x+10), mm(y-1), "sans-serif", mm(3), /* fill colour */ BLACK, /* stroke colour */ BLACK, "5cm line", ""); } void tray(int x, int y) { // base(x,y); skip base for threading test... front_face(x,y); back_face(x,y); left_face(x,y); right_face(x,y); } int main(void) { HALF_KERF = KERF/2.0; stage_width = 3600.0-5.0; stage_height = 2400.0-5.0; for (PREVIEW = 1; PREVIEW >= -1; PREVIEW--) { // do preview first to get size linewidth_f = PREVIEW ? VISIBLE_LINE_f : HAIRLINE_f; fill = PREVIEW ? PREVIEW_FILL : LIVE_FILL; psvg = svg_create(mm_f(stage_width+5), mm_f(stage_height+5)); // size of laser cutter bed stage_width = 0.0; stage_height = 0.0; if (psvg == NULL) { puts("psvg is NULL"); exit(EXIT_FAILURE); } else { if (PREVIEW) svg_fill(psvg, BACKGROUND); } tray(0,0); if (PREVIEW) svg_text(psvg, /* at */ mm(2), mm(4), "sans-serif", mm(3), /* fill colour */ COMMENT_TEXT, /* stroke colour */ COMMENT_TEXT, "THIS IS A PREVIEW-OPTIMISED VERSION. CUT THE OTHER FILE.", ""); svg_finalize(psvg); svg_save(psvg, PREVIEW ? "box-preview.svg" : "box.svg"); svg_free(psvg); } exit(EXIT_SUCCESS); return EXIT_FAILURE; }