Skip to content

Instantly share code, notes, and snippets.

@thomasvst
Last active December 7, 2023 14:58
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 thomasvst/64379578a83e09a170f9607bf2d07c94 to your computer and use it in GitHub Desktop.
Save thomasvst/64379578a83e09a170f9607bf2d07c94 to your computer and use it in GitHub Desktop.
Collection of utility funtions around spoke length calculation in Javascript. Written by Thomas @ LH WHEELS (https://www.lhwheels.be/)
/**
* Compute the spoke length for one side of the wheel, based on the standard spoke length formula.
*
* Sample : spokeLength(593, 110, 2.5, 57.9, 26.8, 32, 3);
*
* @param erd the Effective Rim Diameter (ERD)
* @param spokeHoleDiameter the hub spoke hole dimater, in mm (usually 2.6)
* @param hubFlangeDiameter the diameter of the hub flange (from hole to hole) in mm
* @param hubFlangeToCenter the distante between the hub flange and the wheel center, taking the rim offset into account, in mm
* @param numberOfSpokes the total number of spoke used to buid the wheel (24, 28, 32)
* @param crossPattern the cross pattern (0, 1, 2, 3)
*
* @return the computed spoke length, rounded to 1 decimal place
*
* @author thomas@lhwheels.be
* @see https://www.wheelpro.co.uk/support/spoke-length-calculators/
* @depreacted use spokeLengthV2
*/
function spokeLength(erd, spokeHoleDiameter, hubFlangeDiameter, hubFlangeToCenter, numberOfSpokes, crossPattern) {
var R = erd / 2; // Rim radius (half the ERD)
var H = hubFlangeDiameter / 2; // Hub flange radius
var F = hubFlangeToCenter; // Hub flange offset
var X = crossPattern; // Cross pattern
var h = numberOfSpokes; // Number of spokes in the wheel
var Ø = spokeHoleDiameter; // Diameter of the spoke hole in the hub
// var spokeLength = Math.sqrt((R * R) + (H * H) + (F * F) - 2 * R * H * Math.cos((4.0 * Math.PI * X) / h)) - (d / 2);
var spokeLength = Math.sqrt((R ** 2) + (H ** 2) + (F ** 2) - 2 * R * H * Math.cos((4.0 * Math.PI * X) / h)) - (Ø / 2);
return Math.round(spokeLength * 10) / 10;
}
/**
* Compute the spoke length for one side of a the wheel, based on the standard spoke length formula.
*
* Sample for straight pull spokes : spokeLengthV2('SP', 593, 2.5, 57.9, 26.8, 32, 3, 1.1);
* Sample for straight j-bend spokes : spokeLengthV2('JB', 593, 2.5, 57.9, 26.8, 32, 3, null);
*
* @param spokeType the spoke type : 'SP' for straight pull / 'JB' for J-Bend
* @param erd the Effective Rim Diameter in mm (ERD)
* @param spokeHoleDiameter the hub spoke hole dimater in mm (usually 2.6)
* @param hubFlangeDiameter the diameter of the hub flange (from hole to hole) in mm
* @param hubFlangeToCenter the distante between the hub flange and the wheel center, taking the rim offset into account, in mm
* @param numberOfSpokes the total number of spoke used to build the wheel (20, 24, 28, 32, 36 ...)
* @param crossPattern the cross pattern (0, 1, 2, 3)
* @param spokeHoleOffset the spoke hole offset (only apply when spoke type = 'SP' )
*
* @return the computed spoke length, rounded to 1 decimal place
*
* @author thomas@lhwheels.be
* @see https://www.wheelpro.co.uk/support/spoke-length-calculators/
* @see https://www.wheelpro.co.uk/wheelbuilding/book.php
* @depreacted use spokeLengthV3
*/
function spokeLengthV2(spokeType, erd, spokeHoleDiameter, hubFlangeDiameter, hubFlangeToCenter, numberOfSpokes, crossPattern, spokeHoleOffset) {
var R = erd / 2; // Rim radius (half the ERD)
var H = hubFlangeDiameter / 2; // Hub flange radius to spoke holes
var F = hubFlangeToCenter; // Hub flange offset
var X = crossPattern; // Cross pattern
if (spokeType == 'SP') {
X += 0.5;
}
var h = numberOfSpokes; // Number of spokes in the wheel
var Ø = spokeHoleDiameter; // Diameter of the spoke hole in the hub
spokeHoleOffset = crossPattern == 0 ? 0 : spokeHoleOffset; // always 0 for radial wheels
var spokeLength = Math.sqrt((R ** 2) + (H ** 2) + (F ** 2) - 2 * R * H * Math.cos((4.0 * Math.PI * X) / h));
if (spokeType == 'JB') {
spokeLength -= (Ø / 2);
} else if (spokeType == 'SP') {
spokeLength += spokeHoleOffset;
}
return Math.round(spokeLength * 10) / 10;
}
function test_spokeLengthV2() {
console.log(spokeLengthV2('JB', 593, 2.5, 57.9, 26.8, 32, 3, null), "Spoke length should be 286.7");
console.log(spokeLengthV2('SP', 593, 2.5, 57.9, 26.8, 32, 3, 1.1), "Spoke length should be 294.6");
console.log(spokeLengthV2('JB', 603, 2.6, 42, 34.5, 24, 2, null), "Spoke length should be 292.3");
}
/**
* Compute the elongation of a spoke.
* Based on the following formula : elongation in mm = (Spoketension in N / (pi * r^2)) / (GPa in N-mm2 / spoke length in mm)
*
* @param spokeTensionInKg the spoke tension in kg. Use 100kg as a midpoint tension if you don't kown what to use.
* @param spokeDiameter the spoke diameter in mm
*
* @see https://www.mtbr.com/threads/spoke-elongation-formula.1182122/
*/
function spokeElongation(spokeTensionInKg, spokeDiameter, spokeLength) {
let gpa = 205000; // based on the Young's modulus of 205000 N / mm2 (typical value for high strength stainless steel)
let spokeTensionInN = spokeTensionInKg * 9.81;
let spokeRadius = spokeDiameter / 2
return (spokeTensionInN / (Math.PI * spokeRadius * spokeRadius)) / (gpa / spokeLength);
}
function test_spokeElongation() {
console.log(spokeElongation(79, 2, 290), "Elongation should be 0.3489");
console.log(spokeElongation(100, 1.5, 292.3018), "Elongation should be 0.7915");
}
/**
* Compute the spoke length for one side of a the wheel, based on the standard spoke length formula and taking spoke elongation into account.
*
* Sample for straight pull spokes : spokeLengthV3('SP', 593, 2.5, 57.9, 26.8, 32, 3, 1.1, 1.5);
* Sample for straight j-bend spokes : spokeLengthV3('JB', 593, 2.5, 57.9, 26.8, 32, 3, null, 1.5);
*
* @param spokeType the spoke type : 'SP' for straight pull / 'JB' for J-Bend
* @param erd the Effective Rim Diameter in mm (ERD)
* @param spokeHoleDiameter the hub spoke hole dimater in mm (usually 2.6)
* @param hubFlangeDiameter the diameter of the hub flange (from hole to hole) in mm
* @param hubFlangeToCenter the distante between the hub flange and the wheel center, taking the rim offset into account, in mm
* @param numberOfSpokes the total number of spoke used to build the wheel (20, 24, 28, 32, 36 ...)
* @param crossPattern the cross pattern (0 (radial), 1, 2, 3)
* @param spokeHoleOffset the spoke hole offset (only apply when spoke type = 'SP' )
* @param spokeDia the spoke diameter in mm (1.5 for Sapim CX-Ray, 1.65 for Sapim D-Light, 1.8 for Sapim Race, etc...)
* @spokeTensionRatio the spoke tension ratio in percent (100 for 100%)
*
* @return the computed spoke length, rounded to 1 decimal place
*
* @author thomas@lhwheels.be
* @see https://www.wheelpro.co.uk/support/spoke-length-calculators/
* @see https://www.wheelpro.co.uk/wheelbuilding/book.php
*/
function spokeLengthV3(spokeType, erd, spokeHoleDiameter, hubFlangeDiameter, hubFlangeToCenter, numberOfSpokes, crossPattern, spokeHoleOffset, spokeDia, spokeTensionRatio) {
var R = erd / 2; // Rim radius (half the ERD)
var H = hubFlangeDiameter / 2; // Hub flange radius to spoke holes
var F = hubFlangeToCenter; // Hub flange offset
var X = crossPattern; // Cross pattern
if (spokeType == 'SP') {
X += 0.5;
}
var h = numberOfSpokes; // Number of spokes in the wheel
var Ø = spokeHoleDiameter; // Diameter of the spoke hole in the hub
spokeHoleOffset = crossPattern == 0 ? 0 : spokeHoleOffset; // always 0 for radial wheels
var spokeLength = Math.sqrt((R ** 2) + (H ** 2) + (F ** 2) - 2 * R * H * Math.cos((4.0 * Math.PI * X) / h));
if (spokeType == 'JB') {
spokeLength -= (Ø / 2);
} else if (spokeType == 'SP') {
spokeLength += spokeHoleOffset;
}
let spokeTension = 120 * spokeTensionRatio / 100;
let elongation = spokeElongation(spokeTension, spokeDia, spokeLength);
spokeLength = spokeLength - elongation;
return Math.round(spokeLength * 10) / 10;
}
function test_spokeLengthV3() {
console.log(spokeLengthV3('JB', 593, 2.5, 57.9, 26.8, 32, 3, null, 1.5, 100), "Spoke length should be 285.9");
}
/**
* Round a spoke length to a multiple of 2 value. The value is rounded to a lower value, between 1 et 3 mm.
* This kind of rounding is ideal when using Sapim double square (DS) nipple.
* ERD must be measured with DS nipples and the spoke must be engaged to 1mm before the end of the nipple.
*
* @param value the spoke length to round
* @return the rounded spoke length
*
* @author thomas@lhwheels.be
*/
function roundSpokeLength(value) {
var rounded = Math.floor(value);
if (rounded % 2 == 1) {
rounded = rounded - 1;
}
if (value - rounded <= 1) {
rounded = rounded - 2;
}
return rounded;
}
function test_roundSpokeLength() {
console.log(roundSpokeLength(291.9), "Rounded spoke length should be 290");
console.log(roundSpokeLength(292), "Rounded spoke length should be 290");
console.log(roundSpokeLength(292.2), "Rounded spoke length should be 290");
console.log(roundSpokeLength(293), "Rounded spoke length should be 290");
console.log(roundSpokeLength(293.1), "Rounded spoke length should be 292");
}
/**
* Compute the spoke tension ratio between the 2 side based on the flanges offsets (this is not a precise method).
* The flange offset is the distance from the hub centre line to the centre of the flange.
* The spoke tension ration will alway be 100 (%) on the side havi the shortest flange offset.
*
* @param thisFlangeOffset the offset of this flange (the one we are computing the spoke tension ratio)
* @param otherFlangeOffset the offset of the other flange
* @return an the spoke ration in % (integer value). Ex : 100 for 100%, 60 for 60%.
*
* @author thomas@lhwheels.be
*/
function computeSpokeTensionRatio(thisFlangeOffset, otherFlangeOffset) {
if (thisFlangeOffset < otherFlangeOffset) {
return 100;
} else {
let ratio = Math.min(thisFlangeOffset, otherFlangeOffset) / Math.max(thisFlangeOffset, otherFlangeOffset);
return Math.round(ratio * 100);
}
}
function test_computeSpokeTensionRatio() {
console.log(computeSpokeTensionRatio(31, 37), "Spoke tension ration should be 100%");
console.log(computeSpokeTensionRatio(37, 31), "Spoke tension ration should be 84%");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment