#!/usr/bin/perl

use POSIX;


$PI = atan2(1, 1)*4;
$epsilon = 0.02;

$d = 25.4/8;	# 1/8"
$r = $d/2;


sub orig
{
    $x0 = $_[0];
    $y0 = $_[1];
}


sub mil
{
    return $_[0]/1000*25.4;
}


sub cut
{
    if (defined $x) {
	if ($x == $_[0]+$x0 && $y == $_[1]+$y0) {
	    shift @_;
	    shift @_;
	} else {
	    print "\n";
	}
    }
    while (@_) {
	$x = shift @_;
	$y = shift @_;
	$x += $x0;
	$y += $y0;
	print "$x $y $z\n";
    }
}


sub mm
{
	local ($x, $y, @m) = @_;

	return ($x*$m[0]+$y*$m[1], $x*$m[2]+$y*$m[3]);
}


sub a2m
{
	local ($a) = $_[0]/180*$PI;

	return (cos($a), sin($a), -sin($a), cos($a));
}


sub yarc
{
	local ($x, $y, $dx, $dy0, $dy1, $r, @m) = @_;
	local ($dy);

	$dx = ($dx > 0 ? 1 : -1)*sqrt($r*$r-$dy0*$dy0+$epsilon);
	$dy = $dy0;

	while (1) {
		if ($dy0 < $dy1) {
			last if $dy >= $dy1-$epsilon;
		} else {
			last if $dy <= $dy1+$epsilon;
		}
		print $x+$dx, " ", $y+$dy, " ", $z, "\n";
		($dx, $dy) = &mm($dx, $dy, @m);
	}
}


sub circ
{
	local ($x, $y, $r, $n) = @_;
	local ($a, $dx, $dy);

	for ($a = 0; $a <= 2*$PI+$epsilon; $a += 2*$PI/$n) {
		$dx = $r*sin($a);
		$dy = $r*cos($a);
		print $x+$dx, " ", $y+$dy, " ", $z, "\n";
	}
}


#
# general shape:
#
#  <------ 150 ------>
# +-------------------+
# |                   | ^
# | () () () () () () | |
# | () () () () () () | | 93
# | () () () () () () | |
# | () () () () () () | |
# |                   | v
# +-------------------+
#


# start depth
$z0 = -0.5;

# floor depth
$zf = -18;

# maximum depth step
$zs = 2.5;

# distance between columns
$xs = 24;

# distance between vial centers within columns
$ys = 20;

# vial diameter
$vd = 18.7;

# minimum wall thickness
$mw = 2.5;

$nc = 6;
$nr = 4;


@m_cw = &a2m(1);
@m_ccw = &a2m(-1);

# vial hole radius
$vr = $vd/2;

# circle radii: first, last, increment
$r0 = $r/2;
$r1 = $vr-$r*1.5;
$rs = $r*0.75;

#
# x offset at which the vial bay stops
#

$t = $ys/2-$mw/2;
$xo = sqrt($vr*$vr-$t*$t);

#
# radius of the arcs connecting vial bays
#
$br = $vr*($mw/2)/$t;

# x offset of the center of the arcs connecting vial bays
#
#$bx = $xo+sqrt($br*$br-($mw/2)*($mw/2));
$bx = $xo+$xo*($mw/2)/$vr;

print STDERR "t = $t\n";
print STDERR "xo = $xo\n";
print STDERR "br = $br\n";
print STDERR "bx = $bx\n";

# adjust the z step

$nz = POSIX::ceil(($z0-$zf)/$zs);
$zs = ($z0-$zf)/$nz;

print STDERR "nz = $nz\n";
print STDERR "zs = $zs\n";

print STDERR "r0 = $r0\n";
print STDERR "r1 = $r1\n";
print STDERR "rs = $rs\n";


sub do_col
{
	local ($x0) = @_;
	local ($rw, $end);

	for ($rw = 0; $rw != $nr; $rw++) {
		if ($rw) {
			$end = $rw == $nr-1 ? $vr : ($ys-$mw)/2;
			&yarc($x0-$bx, $y0-$ys/2,
			    1, -$mw/2-$r, $mw/2+$r, $br+$r, @m_ccw);
			&yarc($x0, $y0,
			    -1, -($ys-$mw)/2+$r, $end-$r, $vr-$r, @m_cw);
		} else {
			&yarc($x0, $y0,
			    1, -$vr+$r, ($ys-$mw)/2-$r, $vr-$r, @m_cw);
		}
		$y0 += $ys;
	}
	for ($rw = 0; $rw != $nr; $rw++) {
		$y0 -= $ys;
		if ($rw) {
			$end = $rw == $nr-1 ? $vr : ($ys-$mw)/2;
			&yarc($x0+$bx, $y0+$ys/2,
			    -1, $mw/2+$r, -$mw/2-$r, $br+$r, @m_ccw);
			&yarc($x0, $y0,
			    1, ($ys-$mw)/2-$r, -$end+$r, $vr-$r, @m_cw);
		} else {
			&yarc($x0, $y0,
			    1, $vr-$r, -($ys-$mw)/2+$r, $vr-$r, @m_cw);
		}
	}
}


sub do_cols
{
	local ($c, $x);

	$x = $x0;
	for ($c = 0; $c != $nc; $c++) {
		&do_col($x);
		$x += $xs;
		print "\n";
	}
}


sub do_circles
{
	local ($c, $rw, $x, $y);
	local ($rr);

	$x = $x0;
	for ($c = 0; $c != $nc; $c++) {
		$y = $y0;
		for ($rw = 0; $rw != $nr; $rw++) {
			for ($rr = $r0; $rr <= $r1; $rr += $rs) {
				&circ($x, $y, $rr, 180);
			}
			print "\n";
			$y += $ys;
		}
		$x += $xs;
	}
}


($x0, $y0) = (5+$ys/2, 6.5+$ys/2);

$z = $z0;
for ($i = 0; $i != $nz; $i++) {
#	print "#%%r_tool=0\n";
	&do_circles;

#	print "#%%r_tool=", $r, "\n";
	&do_cols;

	$z -= $zs;
}