Quilting Circle Template: Why I Loves Me My 3D Printer(s)

Mary just started an ambitious pieced quilt that requires 50-some-odd precisely sized 1-1/2 inch circles, with marks to locate a 1 inch circle in the middle. She started using a drafting template to mark the smaller circle on freezer paper (don’t ask, it’s complicated), but we couldn’t find the template I know I have with the larger circles.

[Update: It’s a Bittersweet Briar traditional quilt. See all those little dots-for-berries?]

So I says to my wife, I sez, “Hey, we have the technology. What would really simplify what you’re doing?” After a bit of doodling, we came up with a ring having the proper ID and OD, plus a flat handle of some sort.

Half an hour later, I had a solid model:

Quilting circle template - solid model
Quilting circle template – solid model

An hour after that I handed her a warm piece of plastic:

Quilting circle template
Quilting circle template

The bottom ring is exactly 1-1/2 inch OD, 1 inch ID, and thin enough to draw around. The handle keeps her fingers out of the way and even has grips and a hole for a string.

The print quality near the hole isn’t as good as I’d like, because the slicer turned that entire volume into a solid slab of plastic. I can fix that in the second version, but right now she has something to work with, evaluate, and figure out what would improve it.

3D printing isn’t for everybody, but it’s a vital part of my shop!

The OpenSCAD source code has parameters for everything, so we can crank out more templates without fuss:

// Quilting - Circle Template
// Ed Nisley KE4ZNU - July 2013

Layout = "Show";                    // Show Build Circle Handle

//-------
//- Extrusion parameters must match reality!
//  Print with 2 shells

ThreadThick = 0.25;
ThreadWidth = 0.40;

HoleFinagle = 0.2;
HoleFudge = 1.00;

function HoleAdjust(Diameter) = HoleFudge*Diameter + HoleFinagle;

Protrusion = 0.1;           // make holes end cleanly

function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
function IntegerMultipleMin(Size,Unit) = Unit * floor(Size / Unit);

inch = 25.4;

//-------
// Dimensions

CircleID = (1) * inch;

SeamAllowance = (1/4) * inch;

CircleOD = CircleID + 2*SeamAllowance;

CircleThick = 6*ThreadThick;

CircleSides = 12*4;

HandleHeight = (2) * inch;
HandleThick = IntegerMultiple(5.0,ThreadWidth);
HandleSides = 12*4;

StringDia = 4.0;
StringSides = 8;
StringHeight = 0.75*HandleHeight;

DentDepth = HandleThick/4;
DentDia = 15.0;
DentSphereRadius = (pow(DentDepth,2) + pow(DentDia,2)/4)/(2*DentDepth);

//-------

module PolyCyl(Dia,Height,ForceSides=0) {           // based on nophead's polyholes
  Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
  FixDia = Dia / cos(180/Sides);
  cylinder(r=HoleAdjust(FixDia)/2,h=Height,$fn=Sides);
}

module ShowPegGrid(Space = 10.0,Size = 1.0) {

  RangeX = floor(100 / Space);
  RangeY = floor(125 / Space);

	for (x=[-RangeX:RangeX])
	  for (y=[-RangeY:RangeY])
		translate([x*Space,y*Space,Size/2])
		  %cube(Size,center=true);

}

//-------
// Circle ring plate

module CircleRing() {

	rotate(180/CircleSides)
		difference() {
			cylinder(r=CircleOD/2,h=CircleThick,$fn=CircleSides);
			translate([0,0,-Protrusion])
				cylinder(r=CircleID/2,h=(CircleThick + 2*Protrusion),$fn=CircleSides);
		}
}

//-------
// Handle

module Handle() {

	difference() {
		rotate([0,90,0])
			scale([HandleHeight/(CircleOD/2),0.9,1])
				rotate(180/HandleSides)
					cylinder(r=CircleOD/2,h=HandleThick,center=true,$fn=HandleSides);
		translate([0,0,-HandleHeight])
			cube([2*CircleOD,2*CircleOD,2*HandleHeight],center=true);
		translate([-HandleThick,0,StringHeight])
			rotate([0,90,0])
				rotate(180/StringSides)
					PolyCyl(StringDia,2*HandleThick,StringSides);
#		for (i=[-1,1]) {
			translate([i*(DentSphereRadius + HandleThick/2 - DentDepth),0,StringHeight])
				sphere(r=DentSphereRadius);
		}
	}

}

module Template() {
	CircleRing();
	Handle();
}

//-------
// Build it!

ShowPegGrid();

if (Layout == "Circle")
	CircleRing();

if (Layout == "Handle")
	Handle();

if (Layout == "Show")
	Template();