Skip to content

Instantly share code, notes, and snippets.

@praeclarum
Created November 9, 2011 11:44
Show Gist options
  • Save praeclarum/1351205 to your computer and use it in GitHub Desktop.
Save praeclarum/1351205 to your computer and use it in GitHub Desktop.
App to perform CNC cuts using interval arithmetic and voxels in an adaptive octree
using System;
using System.IO;
namespace Cutter
{
class MainClass
{
const float Precision = 0.02f;
const float CutterStep = 0.1f;
public static void Main (string[] args)
{
DateTime start = DateTime.Now;
var cutter = new Cutter {
Radius = 1,
X = 2.0f,
Y = -3.0f,
Z = 0,
};
var workpiece = new Node {
X = -5,
Y = -5,
Z = -5,
Size = 10,
};
for (var x = cutter.X; x >= -1.5f; x -= CutterStep) {
cutter.X = x;
Step (cutter, workpiece);
}
for (var y = cutter.Y; y <= 2.5f; y += CutterStep) {
cutter.Y = y;
Step (cutter, workpiece);
}
cutter.X = 0;
cutter.Y = 0.0f;
for (var x = cutter.X; x >= -1.5f; x -= CutterStep) {
cutter.X = x;
Step (cutter, workpiece);
}
var dt = DateTime.Now - start;
Console.WriteLine ("{0} s, {1} FPS", dt.TotalSeconds, 1.0/dt.TotalSeconds);
using (var w = new StreamWriter ("/Users/fak/Desktop/cut.svg")) {
w.WriteLine(@"<?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 viewBox=""-6 -6 12 12""
xmlns=""http://www.w3.org/2000/svg"" version=""1.1"">");
workpiece.Draw (w);
w.WriteLine ("</svg>");
}
}
static void Step (Cutter cutter, Node node)
{
if (node.Removed) return;
var i = cutter.GetIntersection (node);
if (i == Intersection.CompletelyInside) {
node.Removed = true;
}
else if (i == Intersection.CompletelyOutside) {
// Nothing to do
}
else {
if (node.Size > Precision) {
node.Split ();
foreach (var c in node.Children) {
Step (cutter, c);
}
}
}
}
}
class Node
{
public float X, Y, Z;
public float Size;
public bool Removed;
public Node[] Children;
public void Draw(TextWriter w)
{
if (Removed) return;
if (Children == null) {
if (Z > (-5 + 0.00001f)) return;
w.WriteLine ("<rect x=\"{0}\" y=\"{1}\" width=\"{2}\" height=\"{2}\" fill=\"none\" stroke=\"black\" stroke-width=\"0.01\" />",
X, Y, Size);
}
else {
foreach (var c in Children) {
c.Draw (w);
}
}
}
public void Split ()
{
if (Children != null) return;
var sz = Size / 2;
Children = new Node[8];
Children [0] = new Node () {
X = X,
Y = Y,
Z = Z,
Size = sz,
};
Children [1] = new Node () {
X = X + sz,
Y = Y,
Z = Z,
Size = sz,
};
Children [2] = new Node () {
X = X + sz,
Y = Y + sz,
Z = Z,
Size = sz,
};
Children [3] = new Node () {
X = X,
Y = Y + sz,
Z = Z,
Size = sz,
};
Children [4] = new Node () {
X = X,
Y = Y,
Z = Z + sz,
Size = sz,
};
Children [5] = new Node () {
X = X + sz,
Y = Y,
Z = Z + sz,
Size = sz,
};
Children [6] = new Node () {
X = X + sz,
Y = Y + sz,
Z = Z + sz,
Size = sz,
};
Children [7] = new Node () {
X = X,
Y = Y + sz,
Z = Z + sz,
Size = sz,
};
}
}
enum Intersection
{
CompletelyInside,
Mixed,
CompletelyOutside,
}
class Cutter
{
public float Radius;
public float X, Y, Z;
public Intersection GetIntersection (Node n)
{
var rr = Radius * Radius;
var x = n.X - X;
var y = n.Y - Y;
var nxx = x * x;
var nyy = y * y;
var xxMin = Math.Min (
Math.Min (nxx, nxx + x*n.Size),
nxx + n.Size*n.Size + 2*x*n.Size);
var yyMin = Math.Min (
Math.Min (nyy, nyy + y*n.Size),
nyy + n.Size*n.Size + 2*y*n.Size);
var min = xxMin + yyMin - rr;
if (min > 0) {
return Intersection.CompletelyOutside;
}
var xxMax = Math.Max (
Math.Max (nxx, nxx + x*n.Size),
nxx + n.Size*n.Size + 2*x*n.Size);
var yyMax = Math.Max (
Math.Max (nyy, nyy + y*n.Size),
nyy + n.Size*n.Size + 2*y*n.Size);
var max = xxMax + yyMax - rr;
if (max < 0) {
return Intersection.CompletelyInside;
}
else {
return Intersection.Mixed;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment