Skip to content

Instantly share code, notes, and snippets.

@lealbaugh
Last active March 5, 2023 17:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lealbaugh/57af1f5936072daa9b59689828377679 to your computer and use it in GitHub Desktop.
Save lealbaugh/57af1f5936072daa9b59689828377679 to your computer and use it in GitHub Desktop.
const knitout = require('knitout');
const yarn = "3";
const gauge = "half";
const fingerQuantityMinimum = 5;
const fingerQuantityMaximum = 10;
const fingerWidthMinimum = 6;
const fingerWidthMaximum = 8;
const fingerHeightMinimum = 20;
const fingerHeightMaximum = 100;
const thumbChance = 1/4;
const numFingers = randomBetween(fingerQuantityMinimum, fingerQuantityMaximum);
k = new knitout.Writer({carriers:['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']});
k.addHeader('Machine','SWGXYZ');
k.addHeader('Gauge','15');
k.addHeader('Presser','On');
k.addHeader('X-Presser','On');
k.stitchNumber(85);
let glove = {leftedge: 0, rightedge: 0};
let yarnIsIn = false;
for (let f = 0; f<numFingers; f++) {
let fingerWidth = randomBetween(fingerWidthMinimum, fingerWidthMaximum);
let fingerHeight = randomBetween(fingerHeightMinimum, fingerHeightMaximum);
if (f>0 && Math.random() < thumbChance) { // can't add a thumb to a null palm
glove = addThumb(glove, fingerWidth, fingerHeight, yarn);
}
else {
glove = addFinger(glove, fingerWidth, fingerHeight, yarn);
}
}
glove = addCuff(glove, yarn);
k.write('glotch.k');
// ============================================================================
// ============ High-level ====================================================
// ============================================================================
function addFinger (confines, width, height, carrier) {
// finger adds a finger to a right side of the glove
let leftedge = (confines.rightedge - confines.leftedge > 0) ? confines.rightedge + 1 : confines.rightedge;
let finger = {leftedge: leftedge, rightedge: leftedge+width};
console.log("adding finger: ", finger);
// breaks yarn if necessary
if (yarnIsIn) {
k.outhook(yarn);
yarnIsIn = false;
}
// casts on
caston("allneedle", finger, carrier);
// shortrows for roundedness
fingertip(finger, carrier);
// knits the height of the tube
knitRows(finger, height, carrier);
// transfers by one stitch onto the finger next to it
if (confines.rightedge - confines.leftedge > 0) {
transferChunk(finger, -1);
finger.rightedge = finger.rightedge - 1;
}
confines.rightedge = finger.rightedge;
// (if there is one -- that is, if incoming confines is not zero width)
let palmHeight = randomBetween(1,2);
knitRows(confines, palmHeight, carrier);
// and does a course or two of palm pickup
return confines;
}
function addThumb (confines, width, height, carrier) {
// a thumb rotates the confines for a handful of courses, then knits a new finger, joins, and narrows back the width of the thumb
console.log("thumb!");
confines = rotate(confines, 3, carrier);
let originalRightedge = confines.rightedge;
confines = addFinger(confines, width, height, carrier);
for (let i = 0; i<width; i++) {
knitRows(confines, 1, carrier);
transferChunk({leftedge: originalRightedge + 1, rightedge: confines.rightedge}, -1);
confines.rightedge = confines.rightedge - 1;
}
knitRows(confines, 1, carrier);
return confines;
}
function addCuff (confines, carrier) {
// a cuff adds courses of 2x2 ribbing, then binds off
// height of courses is between 1/3 and 1/2 the width of the confines
let width = confines.rightedge - confines.leftedge;
let height = randomBetween(width/2, width);
knitRows(confines, height, carrier);
knitRibRows(confines, height, carrier);
bindoff("open", confines, carrier);
return {leftedge:0,rightedge:0};
}
function fingertip (confines, carrier) {
function shortRows (bed) {
let setback = 1;
// shortrow a nice round fingertip
for (let s = confines.rightedge; s>confines.leftedge+((((confines.rightedge - confines.leftedge)/(2*setback))-1)*setback); s--) {
knit("-", bed, s, carrier);
}
for (let i = Math.round((confines.rightedge - confines.leftedge)/(2*setback)); i>0; i--) {
for (let s = Math.round(confines.rightedge - (i*setback) - 1); s>confines.leftedge+((i-1)*setback); s--) {
knit("-", bed, s, carrier);
}
tuck("+", bed, Math.round(confines.leftedge+((i-1)*setback)), carrier);
for (let s = Math.round(confines.leftedge+((i-1)*setback) + 1); s <= confines.rightedge - ((i)*setback); s++) {
knit("+", bed, s, carrier);
}
if (i>1) tuck("-", bed, Math.round(confines.rightedge - ((i - 1)*setback)), carrier);
else {
for (let s = Math.round(confines.rightedge - ((i - 1)*setback)); s<=confines.rightedge; s++) {
knit("+", bed, s, carrier);
}
}
}
}
shortRows("f");
shortRows("b");
}
// ============================================================================
// ============ Mid-level =====================================================
// ============================================================================
function knitRows (confines, height, carrier) {
for (let h=0; h<height; h++) {
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
// console.log(h, s);
knit("-", "f", s, carrier);
}
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
// console.log(h, s);
knit("+", "b", s, carrier);
}
}
}
function knitRibRows (confines, height, carrier) {
function ribGen (face, stitch) {
if (face == "f"){
return (stitch%4 <= 1) ? "k" : "p";
}
else {
return (stitch%4 <= 1) ? "p" : "k";
}
}
for (let h=0; h<height; h++) {
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
if (ribGen("f", s) != "k") xfer("f", s, "bs", s);
}
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
let bed = (ribGen("f", s) == "k") ? "f" : "bs";
knit("-", bed, s, carrier);
}
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
if (ribGen("f", s) != "k") xfer("bs", s, "f", s);
if (ribGen("b", s) != "k") xfer("b", s, "fs", s);
}
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
let bed = (ribGen("b", s) == "k") ? "b" : "fs";
knit("+", bed, s, carrier);
}
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
if (ribGen("b", s) != "k") xfer("fs", s, "b", s);
}
}
}
function rotate (confines, height, carrier) {
for (let h=0; h<height; h++) {
// knit to one before the edge
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
// console.log(h, s);
knit("-", "f", s, carrier);
}
for (let s=confines.leftedge; s<confines.rightedge; s++) {
// console.log(h, s);
knit("+", "b", s, carrier);
}
// xfer
xfer("f", confines.leftedge, "b", confines.leftedge - 1);
xfer("b", confines.rightedge, "f", confines.rightedge + 1);
for (let s = confines.leftedge + 1; s<=confines.rightedge + 1; s++) {
xfer("f", s, "bs", s-1);
}
for (let s = confines.leftedge; s<=confines.rightedge; s++) {
xfer("bs", s, "f", s);
}
for (let s = confines.leftedge - 1; s<=confines.rightedge - 1; s++) {
xfer("b", s, "fs", s+1);
}
for (let s = confines.leftedge; s<=confines.rightedge; s++) {
xfer("fs", s, "b", s);
}
align("centered");
}
knitRows(confines, 1, carrier);
return confines;
}
function transferChunk (confines, offset) {
for (let s = confines.leftedge; s<=confines.rightedge; s++) {
xfer("f", s, "bs", s);
}
for (let s = confines.leftedge; s<=confines.rightedge; s++) {
xfer("bs", s, "f", s+offset);
}
for (let s = confines.leftedge; s<=confines.rightedge; s++) {
xfer("b", s, "fs", s+offset);
}
for (let s = confines.leftedge; s<=confines.rightedge; s++) {
xfer("fs", s+offset, "b", s+offset);
}
}
function pickup (confines, yarn) {
k.inhook(yarn);
yarnIsIn = true;
knitRows(confines, 1, yarn);
k.releasehook(yarn);
}
function caston (style, confines, carrier) {
k.inhook(yarn);
yarnIsIn = true;
if (style == "tube") {
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
if (s%2 == confines.rightedge%2) {
knit("-", "f", s, carrier);
}
}
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
if (s%2 != confines.rightedge%2) {
knit("+", "b", s, carrier);
}
}
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
if (s%2 != confines.rightedge%2) {
knit("-", "f", s, carrier);
}
}
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
if (s%2 == confines.rightedge%2) {
knit("+", "b", s, carrier);
}
}
}
else if (style == "allneedle") {
align(-1);
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
knit("-", "f", s, carrier);
knit("-", "b", s, carrier);
}
align("centered");
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
knit("+", "f", s, carrier);
knit("+", "b", s, carrier);
}
}
k.releasehook(yarn);
}
function bindoff (style, confines, carrier) {
if (style == "closed") {
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
knit("-", "b", s, carrier);
xfer("b", s, "f", s);
knit("-", "f", s, carrier);
if (s != confines.leftedge) xfer("f", s, "b", s - 1, "centered");
}
let tag = makeTag(confines.leftedge, carrier);
k.outhook(yarn);
yarnIsIn = false;
dropAll(tag);
}
else if (style == "open") {
for (let s=confines.rightedge; s>confines.leftedge; s--) {
knit("-", "f", s, carrier);
xfer("f", s, "bs", s);
xfer("bs", s, "f", s-1);
}
knit("-", "f", confines.leftedge, carrier);
xfer("f", confines.leftedge, "b", confines.leftedge);
for (let s=confines.leftedge; s<confines.rightedge; s++) {
knit("+", "b", s, carrier);
xfer("b", s, "fs", s);
xfer("fs", s, "b", s+1);
}
knit("+", "b", confines.rightedge, carrier);
xfer("b", confines.rightedge, "f", confines.rightedge);
align("centered");
let tag = makeTag(confines.rightedge, carrier);
k.outhook(yarn);
yarnIsIn = false;
dropAll(tag);
}
else {
k.outhook(carrier);
yarnIsIn = false;
dropAll(confines);
}
}
function makeTag (s, carrier) {
knit("+", "f", s, carrier);
knit("-", "f", s, carrier);
knit("+", "f", s, carrier);
knit("-", "f", s+1, carrier);
knit("-", "f", s, carrier);
knit("+", "f", s, carrier);
knit("+", "f", s+1, carrier);
for (let i=0; i<3; i++) {
knit("-", "f", s+2, carrier);
knit("-", "f", s+1, carrier);
knit("-", "f", s, carrier);
knit("+", "f", s, carrier);
knit("+", "f", s+1, carrier);
knit("+", "f", s+2, carrier);
}
return {leftedge: s, rightedge: s+2};
}
function dropAll (confines) {
for (let s=confines.rightedge; s>=confines.leftedge; s--) {
drop("f", s);
}
for (let s=confines.leftedge; s<=confines.rightedge; s++) {
drop("b", s);
}
}
// ============================================================================
// ============ Low-level =====================================================
// ============================================================================
function randomBetween (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function mapNeedle (bed, needle) {
let mappedBed, mappedNeedle;
if (gauge == "full") {
mappedBed = bed;
mappedNeedle = needle;
}
else if (gauge == "half") {
mappedBed = (bed == "f" || bed == "fs") ? "f" : "b";
mappedNeedle = (bed == "f" || bed == "bs") ? (2*needle) - 1 : 2*needle;
}
// console.log({bed: mappedBed, needle: mappedNeedle});
return {bed: mappedBed, needle: mappedNeedle};
}
function knit (direction, bed, needle, carrier) {
let mappedNeedle = mapNeedle(bed, needle);
k.knit(direction, mappedNeedle.bed + mappedNeedle.needle, carrier);
}
function miss (direction, bed, needle, carrier) {
let mappedNeedle = mapNeedle(bed, needle);
k.miss(direction, mappedNeedle.bed + mappedNeedle.needle, carrier);
}
function tuck (direction, bed, needle, carrier) {
let mappedNeedle = mapNeedle(bed, needle);
k.tuck(direction, mappedNeedle.bed + mappedNeedle.needle, carrier);
}
function drop (bed, needle) {
let mappedNeedle = mapNeedle(bed, needle);
k.drop(mappedNeedle.bed + mappedNeedle.needle);
}
function align (alignment) {
if (alignment == "centered") {
if (gauge == "full") {
k.rack(-0.75);
}
else {
k.rack(0);
}
}
else if (typeof alignment == "number") {
if (gauge == "full") {
k.rack(alignment);
}
else {
k.rack(2*alignment);
}
}
else {
console.log("unrecognized alignment style");
}
}
function xfer (fromBed, fromNeedle, toBed, toNeedle, returnAlignment) {
if (fromBed == toBed || (fromBed == "f" && toBed == "fs")|| (fromBed == "fs" && toBed == "f")|| (fromBed == "b" && toBed == "bs")|| (fromBed == "bs" && toBed == "b")) {
console.log("cannot xfer to same bed! attempted: ", fromBed, fromNeedle, toBed, toNeedle);
}
else {
mappedFrom = mapNeedle(fromBed, fromNeedle);
mappedTo = mapNeedle(toBed, toNeedle);
offset = mappedTo.needle - mappedFrom.needle;
if (fromBed == "f" || fromBed == "fs") offset = 0 - offset;
k.rack(offset);
k.xfer(mappedFrom.bed+mappedFrom.needle, mappedTo.bed+mappedTo.needle);
if (typeof returnAlignment !== 'undefined') align(returnAlignment);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment