Source

boxer / boxer

Trammell Hudson 6c95181 





Trammell Hudson 68c64aa 




Trammell Hudson 6c95181 


Trammell Hudson 6bc457e 
Trammell Hudson 6c95181 

Trammell Hudson d00596b 
Trammell Hudson 55a98b2 
Trammell Hudson d00596b 



Trammell Hudson 55a98b2 
Trammell Hudson 68c64aa 
Trammell Hudson 6c95181 
Trammell Hudson 6bc457e 



Trammell Hudson f2bd903 
Trammell Hudson 6bc457e 

Trammell Hudson d00596b 


Trammell Hudson 68c64aa 
Trammell Hudson 6bc457e 





Trammell Hudson d00596b 


Trammell Hudson f2bd903 
Trammell Hudson 68c64aa 
Trammell Hudson 6bc457e 

Trammell Hudson d00596b 












Trammell Hudson 68c64aa 
Trammell Hudson 6c95181 

Trammell Hudson d00596b 


Trammell Hudson 6c95181 




Trammell Hudson 13af312 
Trammell Hudson 6c95181 

Trammell Hudson d00596b 





























































Trammell Hudson f2bd903 
Trammell Hudson d00596b 












Trammell Hudson f2bd903 
Trammell Hudson d00596b 












Trammell Hudson f2bd903 
Trammell Hudson d00596b 












Trammell Hudson f2bd903 
Trammell Hudson d00596b 
























Trammell Hudson f2bd903 
Trammell Hudson d00596b 












Trammell Hudson f2bd903 
Trammell Hudson d00596b 












Trammell Hudson f2bd903 
Trammell Hudson d00596b 












Trammell Hudson f2bd903 
Trammell Hudson d00596b 

















Trammell Hudson 68c64aa 
Trammell Hudson d00596b 





















#!/usr/bin/perl
# Generate SVG files with a specified number of sides and tabs
# to make a self-locking acrylic or wooden laser cut box.
#
# (c) 2012 Trammell Hudson <hudson@osresearch.net>
#
# 5mm bamboo needs a larger kerf -- 0.2?  power 100, speed 4
# 3mm acrylic works well with 6mm fingers
# 6mm acrylic kerf = 0.1 is ok, 0.2 shatters, power 100 speed 4
# Be sure to measure the acrylic -- some of them vary.
#
use warnings;
use strict;
use Math::Trig;
use Getopt::Long;

my $units = "mm"; # mm = 1, inches = 1000 / 25.4
my $thickness = 3;
my $sides = 4;
my $length = 50;
my $width = 30;
my $height = 20;
my $tab_width = 6;
my $kerf = 0.1;
my $spacing;

my $usage = <<"";
Usage: boxer [options] > box.svg
Options:
	-h | -? | --help	This help
	-T | --tab-width N	Tab width in mm
	-t | --thickness N	Material thickness in mm
	-H | --height N		Height of the box, in mm
	-w | --width N		Outside edge length, in mm
	-l | --length N		Outside edge length, in mm for rectangles
	-k | --kerf N		Kerf in mm (typically 0.1)
	-s | --spacing N	Spacing between pieces in mm


GetOptions(
	'h|?|help'		=> sub { print $usage; exit 0 },
	't|thickness=f'		=> \$thickness,
	'H|height=f'		=> \$height,
	'w|width=f'		=> \$width,
	'l|length=f'		=> \$length,
	'k|kerf=f'		=> \$kerf,
	'T|tab-width=f'		=> \$tab_width,
	's|spacing=f'		=> \$spacing,
) or die $usage;

die "tab should be wider than the material thickness\n"
	if $thickness > $tab_width;

my $num_x_tabs = int(($width - $thickness*2) / ($tab_width * 2));
my $num_y_tabs = int(($length - $thickness*2) / ($tab_width * 2));
my $num_z_tabs = int(($height - $thickness*2) / ($tab_width * 2));
die "tab width $tab_width too large for width $width\n"
	if $num_x_tabs == 0;
die "tab width $tab_width too large for length $length\n"
	if $num_y_tabs == 0;
die "tab width $tab_width too large for height $height\n"
	if $num_z_tabs == 0;

$spacing ||= $kerf * 10;

# Compute the height of the interior triangle
#my $interior_angle = 360.0 / $sides;
#my $interior_len = $edge - $thickness * 2;
#my $interior_radius = ($interior_len/2) / tan(deg2rad($interior_angle/2));


print <<"";
<!-- Created with boxer (http://trmm.net/) -->
<svg xmlns="http://www.w3.org/2000/svg">
<g transform="scale(3.543307)"><!-- scale to mm -->


sub make_translate
{
	my ($x,$y) = @_;
	return "translate($x,$y)";
}


sub make_path
{
	my $rc = <<"";
	<path
		stroke		= "#ff0000"
		fill		= "none"
		stroke-width	= "0.1px"
		d		= "M

	for my $pt (@_)
	{
		my ($x,$y) = @$pt;
		$rc .= "$x,$y\n";
	}

	$rc .= <<"";
	"/>

	return $rc;
}


#
# Applies a transform to a list of SVG objects (paths or other groups)
# Returns a SVG group
#
sub make_group
{
	my $transform = shift;

	my $rc = <<"";
	<g
		transform	= "$transform"
	>

	$rc .= join '\n', @_;
	$rc .= <<"";
	</g>

	return $rc;
}


#
# Generate the flat top and bottom pieces.
# Returns a SVG path
#
sub make_top
{
	my $rc;

	my @points;

	# Bottom edge
	push @points, [$thickness, $thickness];
	my $x = $width/2 - $tab_width * ($num_x_tabs - 0.5);
	for my $n (1..$num_x_tabs)
	{
		push @points,
			[$x - $kerf, $thickness],
			[$x - $kerf, 0],
			[$x + $tab_width + $kerf, 0],
			[$x + $tab_width + $kerf, $thickness],
			;
		$x += $tab_width * 2;
	}

	# Right edge
	push @points, [$width - $thickness, $thickness];
	my $y = $length/2 - $tab_width * ($num_y_tabs - 0.5);
	for my $n (1..$num_y_tabs)
	{
		push @points,
			[$width - $thickness, $y - $kerf],
			[$width, $y - $kerf],
			[$width, $y + $tab_width + $kerf],
			[$width - $thickness, $y + $tab_width + $kerf],
			;
		$y += $tab_width * 2;
	}

	# Top edge
	push @points, [$width - $thickness, $length - $thickness];
	$x = $width/2 + $tab_width * ($num_x_tabs - 0.5);
	for my $n (1..$num_x_tabs)
	{
		push @points,
			[$x + $kerf, $length - $thickness],
			[$x + $kerf, $length],
			[$x - $tab_width - $kerf, $length],
			[$x - $tab_width - $kerf, $length - $thickness],
			;
		$x -= $tab_width * 2;
	}

	# Left edge
	push @points, [$thickness, $length - $thickness];
	$y = $length/2 + $tab_width * ($num_y_tabs - 0.5);
	for my $n (1..$num_y_tabs)
	{
		push @points,
			[$thickness, $y + $kerf],
			[0, $y + $kerf],
			[0, $y - $tab_width - $kerf],
			[$thickness, $y - $tab_width - $kerf],
			;
		$y -= $tab_width * 2;
	}

	# Close the path
	push @points, [$thickness, $thickness];

	return make_path(@points);
}


sub make_side
{
	my ($x_dim, $num_x_tabs) = @_;
	my @points;

	# Bottom edge
	push @points, [0,0];
	my $x = $x_dim / 2 - $tab_width * ($num_x_tabs - 0.5);
	for my $n (1..$num_x_tabs)
	{
		push @points,
			[$x - $kerf, 0],
			[$x + $kerf, $thickness],
			[$x - $kerf + $tab_width, $thickness],
			[$x + $kerf + $tab_width, 0],
			;
		$x += $tab_width * 2;
	}

	# Height edge
	push @points, [$x_dim - $thickness, 0];
	my $z = $height/2 - $tab_width * ($num_z_tabs - 0.5);
	for my $n (1..$num_z_tabs)
	{
		push @points,
			[$x_dim - $thickness, $z - $kerf],
			[$x_dim, $z - $kerf],
			[$x_dim, $z + $tab_width + $kerf],
			[$x_dim - $thickness, $z + $tab_width + $kerf],
			;
		$z += $tab_width * 2;
	}

	# Top eddge
	push @points, [$x_dim - $thickness, $height];
	$x = $x_dim / 2 + $tab_width * ($num_x_tabs - 0.5);
	for my $n (1..$num_x_tabs)
	{
		push @points,
			[$x + $kerf, $height],
			[$x - $kerf, $height - $thickness],
			[$x + $kerf - $tab_width, $height - $thickness],
			[$x - $kerf - $tab_width, $height],
			;
		$x -= $tab_width * 2;
	}

	# Height edge
	push @points, [0, $height];
	$z = $height/2 + $tab_width * ($num_z_tabs - 0.5);
	for my $n (1..$num_z_tabs)
	{
		push @points,
			[0, $z + $kerf],
			[$thickness, $z - $kerf],
			[$thickness, $z + $kerf - $tab_width],
			[0, $z - $kerf - $tab_width],
			;
		$z -= $tab_width * 2;
	}

	# Close it back to the bottom
	push @points, [0,0];

	return make_path(@points);
}

print make_group("translate(0,0)", make_top());
print make_group("translate(" . ($width+$spacing) .",0)", make_top());
print make_group(
	make_translate(0, $length + $spacing),
	make_side($width, $num_x_tabs)
);
print make_group(
	make_translate($width + $spacing, $length + $spacing),
	make_side($width, $num_x_tabs)
);

print make_group(
	make_translate(0, $length + $height + $spacing * 2),
	make_side($length, $num_y_tabs)
);
print make_group(
	make_translate($length + $spacing, $length + $height + $spacing * 2),
	make_side($length, $num_y_tabs)
);

print <<"";
</g>
</svg>

__END__