#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;
#define W 142 /* left-right */
//#define H 380 /* top-bottom */
#define H 10 /* top-bottom */
#define D 52 /* 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;
}
}
int xpos, ypos;
void front_face(int x, int y) {
int order;
int steps = (W - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides
xpos = x+5; ypos = y+5;
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/2, /* at */ x+5 /*+ wood*/, y+5 + H/2);
//hole_mm_f(wood, H/2, /* at */ x+5 + W-wood/*-wood*/, y+5 + H/2);
hole_mm_f(wood, H/3.0, /* at */ xpos /*+ wood*/, ypos + H/2.0 - H/6.0);
hole_mm_f(wood, H/3.0, /* at */ xpos + W-wood/*-wood*/, ypos + H/2.0 - H/6.0);
//hole_mm_f(W - 20, H - 10, x+5+10, y+5+10);
toothcomb(xpos + W/2.0, ypos, steps, 2.0, 2);
}
if (order == 0) face(W, H, xpos, ypos);
}
}
void back_face(int x, int y) {
int order;
int steps = (W - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides
xpos = x+5/*+W+5*/; ypos = y+5+H+5;
for (order = 0; order <= 1; order++) { // preview actions then live actions
if (order == (PREVIEW&1)) {
hole_mm_f(wood, H/3.0, /* at */ xpos /*+ wood*/, ypos + H/2.0 - H/6.0);
hole_mm_f(wood, H/3.0, /* at */ xpos + W-wood/*-wood*/, ypos + H/2.0 - H/6.0);
//hole_mm_f(W - 20, H - 10, x+5+W+5+10, y+5+10);
toothcomb(xpos + W/2.0, ypos, steps, 2.0, 2);
}
if (order == 0) face(W, H, xpos, ypos);
}
}
void left_face(int x, int y) {
int order;
int steps = (D - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides
xpos = x+5/*+W+5+W+5*/; ypos = y+5+H+5+H+5;
for (order = 0; order <= 1; order++) { // preview actions then live actions
if (order == (PREVIEW&1)) {
hole_mm_f(wood, H/3.0, /* at */ xpos /*+ wood*/, ypos);
hole_mm_f(wood, H/3.0, /* at */ xpos + D-wood/*-wood*/, ypos);
hole_mm_f(wood, H/3.0, /* at */ xpos /*+ wood*/, ypos - H/3.0 + H);
hole_mm_f(wood, H/3.0, /* at */ xpos + D-wood/*-wood*/, ypos - H/3.0 + H);
//toothcomb(x+5+W+5+W+5 + D/2.0, y+5, steps, 2, 3);
}
if (order == 0) face(D, H/*+10*/, xpos, ypos);
}
}
void right_face(int x, int y) {
int order;
int steps = (D - (wood + /* 10 + 10 +*/ wood))/2 ; // NO /*1 cm*/ gap from internal sides
xpos = x+5 /*+W+5+W+5*/ +D+5; ypos = y+5+H+5+H+5;
for (order = 0; order <= 1; order++) { // preview actions then live actions
if (order == (PREVIEW&1)) {
hole_mm_f(wood, H/3.0, /* at */ xpos /*+ wood*/, ypos);
hole_mm_f(wood, H/3.0, /* at */ xpos + D-wood/*-wood*/, ypos);
hole_mm_f(wood, H/3.0, /* at */ xpos /*+ wood*/, ypos - H/3.0 + H);
hole_mm_f(wood, H/3.0, /* at */ xpos + D-wood/*-wood*/, ypos - H/3.0 + H);
//toothcomb(x+5+W+5+W+5+D+5 + D/2.0, y+5, steps, 2, 3);
}
if (order == 0) face(D, H/*+10*/, xpos, ypos);
}
}
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) {
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 ? "tray-preview.svg" : "tray.svg");
svg_free(psvg);
}
exit(EXIT_SUCCESS);
return EXIT_FAILURE;
}