Skip to content

Instantly share code, notes, and snippets.

@lukem512
Last active May 15, 2021 17:23
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 lukem512/a7fe4c16c7fa0c7a6c53cb2d94ead663 to your computer and use it in GitHub Desktop.
Save lukem512/a7fe4c16c7fa0c7a6c53cb2d94ead663 to your computer and use it in GitHub Desktop.
Calculator for yurt component dimensions and count. Specify a diameter and a wall height (or use the defaults) and you'll be shown how many poles, and of what lengths, are needed.
const defaults = {
units: 'ft', // units to use, could be 'ft' or 'm'
diameter: 14, // units
wallHeight: 6, // units, at outer edge
khanaHoleSpacing: 1, // units, spacing between crossing rods
roofAngle: 25, // degrees from horizontal
tonoDiameter: 1, // units
}
function deg2rad(deg) {
return deg * (Math.PI / 180);
}
function calculateCircumference({diameter}) {
return Math.PI * diameter;
}
function calculateUniRadius({diameter, tonoDiameter}) {
return (diameter - tonoDiameter) / 2;
}
function calculateUniLength({roofAngle, ...options}) {
return calculateUniRadius(options) / Math.cos(deg2rad(roofAngle));
}
function calculateRoofHeight({roofAngle, ...options}) {
return Math.sin(deg2rad(roofAngle)) * calculateUniLength({roofAngle, ...options});
}
function calculateKhanaRodLength({wallHeight}) {
// Assuming 45 degrees, length is the hypotenuse
// of a right-angled triangle with sides of the desired wall height.
return Math.sqrt((wallHeight*wallHeight) * 2);
}
function calculateKhanaRodCount({khanaHoleSpacing, wallHeight, ...options}) {
// A minimal lattice has just two holes - one at either end
// Thus, for each length of the khana rod around the circumference, there are 2 rods
const wholeRodsInCircumference = calculateCircumference(options) / wallHeight;
// A denser (thus stronger) lattice has more holes and one rod per hole.
// The rod length divided by the hole spacing gives the number of holes.
const holesPerKhanaRod = calculateKhanaRodLength({wallHeight}) / khanaHoleSpacing;
return wholeRodsInCircumference * holesPerKhanaRod;
}
function buildYurt(options = {}) {
// Find any missing options and their default values
const missingOpts = Object.keys(defaults)
.filter(key => !(key in options))
.reduce((obj, key) => {
obj[key] = defaults[key];
return obj;
}, {});
// Then mutate the options object to include defaults
options = Object.assign(options, missingOpts);
// Compute some re-usable values
const roofHeight = calculateRoofHeight(options);
const khanaRodCount = Math.ceil(calculateKhanaRodCount(options));
const uniRodCount = Math.ceil(khanaRodCount / 2);
// Build up an object specifying the yurt
return {
units: options.units,
diameter: options.diameter,
height: options.wallHeight + roofHeight,
roof: {
height: roofHeight,
angle: options.roofAngle,
uni: {
length: calculateUniLength(options),
count: uniRodCount,
},
tono: {
diameter: options.tonoDiameter,
holeSpacing: options.tonoDiameter / uniRodCount,
}
},
walls: {
circumference: calculateCircumference(options),
height: options.wallHeight,
khana: {
length: calculateKhanaRodLength(options),
holeSpacing: options.khanaHoleSpacing,
count: khanaRodCount,
}
}
};
}
const yurt = buildYurt();
console.log(yurt);
console.log();
console.log(`YURT`);
console.log(`----`);
console.log();
console.log(`Diameter: ${yurt.diameter.toFixed(2)} ${yurt.units}`);
console.log(`Height: ${yurt.height.toFixed(2)} ${yurt.units}`);
console.log();
console.log(`To build this yurt you will need:`);
console.log();
console.log(`- ${yurt.walls.khana.count}x ${yurt.walls.khana.length.toFixed(2)} ${yurt.units} khana (lattice) poles`);
console.log(`- ${yurt.roof.uni.count}x ${yurt.roof.uni.length.toFixed(2)} ${yurt.units} uni (roof) poles`);
console.log(`- 1x ${yurt.roof.tono.diameter.toFixed(2)} ${yurt.units} diameter tono (crown) with ${yurt.roof.uni.count} holes spaced every ${yurt.roof.tono.holeSpacing.toFixed(2)} ${yurt.units}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment