Here's a quickly put together generator (haXe)
class SquareSpiral { public static inline var LEFT = 0; public static inline var UP = 1; public static inline var RIGHT = 2; public static inline var DOWN = 3; public static inline var CW = 1; public static inline var CCW = -1; //----------- private var x:Int; private var y:Int; private var dir :Int; private var wind:Int; private var cnt :Int; private var ccnt:Int; private var fst :Bool; //----------- public function new(x, y, ?dir = LEFT, ?wind = CW) { this.x = x; this.y = y; this.dir = dir; this.wind = wind; ccnt = 0; cnt = 1; fst = true; } //----------- public function next() { var ret = { x:x, y:y }; x += [ -1, 0, 1, 0][dir]; y += [ 0, -1, 0, 1][dir]; if(++ccnt==cnt) { dir += wind; if (dir < 0) dir += 4; if (dir > 3) dir -= 4; ccnt = 0; if (fst=!fst) cnt++; } return ret; }}
then for example:
var spiral = new SquareSpiral(10,10,SquareSpiral.RIGHT,SquareSpiral.CW);//^^ matches your example output for direction and winding.for(i in 0...19) trace(i + " " + spiral.next());
output is:
0 { x : 10, y : 10 }1 { x : 11, y : 10 }2 { x : 11, y : 11 }3 { x : 10, y : 11 }4 { x : 9, y : 11 }5 { x : 9, y : 10 }6 { x : 9, y : 9 }7 { x : 10, y : 9 }8 { x : 11, y : 9 }9 { x : 12, y : 9 }10 { x : 12, y : 10 }11 { x : 12, y : 11 }12 { x : 12, y : 12 }13 { x : 11, y : 12 }14 { x : 10, y : 12 }15 { x : 9, y : 12 }16 { x : 8, y : 12 }17 { x : 8, y : 11 }18 { x : 8, y : 10 }