Skip to content

Instantly share code, notes, and snippets.

@GoodNovember
Last active January 8, 2018 22:26
Show Gist options
  • Save GoodNovember/2d8b36b9d70b4fe9f3ace8e6dbc7940f to your computer and use it in GitHub Desktop.
Save GoodNovember/2d8b36b9d70b4fe9f3ace8e6dbc7940f to your computer and use it in GitHub Desktop.
Generic Javascript SmoothStep Algorithm

Inspired by this answer: https://stackoverflow.com/a/41196499

This implementation improves upon the above answer by only running the PascalTriangle functions once during initialization and using the compiled results in all subsequent calls to the function.

// (nthOrder should be a positive integer, not a float.)
// values higher than 15 show some strange behavior.

function SmoothMaker(nthOrder){

	var preCalculatedValues = []
	
	for(var n = 0; n <= nthOrder - 1; n++){
		var precalculatedValue = PascalTriangle(-nthOrder, n) * PascalTriangle(2 * nthOrder - 1, nthOrder - n - 1)
		preCalculatedValues.push(precalculatedValue)
	}

	function PascalTriangle(a, b){
		var result = 1 
		for(var i = 1; i <= b; i++){
			result *= ((a - (i - 1)) / i)
		}
		return result
	}

	return function(x){
		var order = preCalculatedValues.length
		return preCalculatedValues.reduce(function(result, precalcValue, index, array){
			var power = order + index
			result += Math.pow(x, power) * precalcValue
			return result
		}, 0)
	}

}

Example usage:

const ctx = document.createElement("canvas").getContext("2d")

document.body.appendChild(ctx.canvas)
ctx.canvas.width = 300
ctx.canvas.height = 300

ctx.beginPath()

const ChosenOrder = 4

const Smooth = SmoothMaker(ChosenOrder)

for(var i = 0; i < ctx.canvas.width; i++){
	var part = i / ctx.canvas.width
	var value = Smooth(part) * ctx.canvas.height
	ctx.lineTo(i, value)
}

ctx.stroke()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment