Parse
File Parse origin-shift/origin-shift-main.js
This tree is parsed live from the source file.
Classes
-
{{ item.name }}
- {{ key }}
Not Classes
{{ getTree() }}
Comments
{{ getTreeComments() }}
Source
let radius = 50
let gap = 10 // Math.floor(radius * .25)
let conf = {
/* The size of a single position for a path origin */
positionSize: 10
/* the size of the indicator at the end of a path */
, tipRadius: 1
, tipWidth: 2
, lineWidth: 2
/* Position radius*/
, radius
/* How many items per row within the grid */
/* A NxN grid, e.g. 10 == 100 points */
, rowCount: 10
/* Distance between nodes - not including extended draws*/
, gap// Math.floor(radius * .25)
/* Distance between points */
, pointSpread: radius + gap
/* boolean to render the center position of every point*/
, drawPosition: false
, lineColor: '#006622'
}
radius = 5
gap = 0 // Math.floor(radius * .25)
conf = {
/* The size of a single position for a path origin */
positionSize: 1
/* the size of the indicator at the end of a path */
, tipRadius: 1
, tipWidth: 1
, lineWidth: 1
/* Position radius*/
, radius
/* How many items per row within the grid */
/* A NxN grid, e.g. 10 == 100 points */
, rowCount: 120
/* Distance between nodes - not including extended draws*/
, gap// Math.floor(radius * .25)
/* Distance between points */
, pointSpread: radius + gap
, drawTip: false
/* boolean to render the center position of every point*/
, drawPosition: false
, lineColor: 'white'
}
radius = 4
gap = 0 // Math.floor(radius * .25)
conf = {
/* The size of a single position for a path origin */
positionSize: 1
/* the size of the indicator at the end of a path */
, tipRadius: 1
, tipWidth: 1
, lineWidth: 1
/* Position radius*/
, radius
/* How many items per row within the grid */
/* A NxN grid, e.g. 10 == 100 points */
, rowCount: 215
/* Distance between nodes - not including extended draws*/
, gap// Math.floor(radius * .25)
/* Distance between points */
, pointSpread: radius + gap
, drawTip: false
/* boolean to render the center position of every point*/
, drawPosition: false
, lineColor: 'white'
}
radius = 20
gap = 8 // Math.floor(radius * .25)
conf = {
/* The size of a single position for a path origin */
positionSize: 1
/* the size of the indicator at the end of a path */
, tipRadius: 2
, tipWidth: 2
, lineWidth: 4
/* Position radius*/
, radius
/* How many items per row within the grid */
/* A NxN grid, e.g. 10 == 100 points */
, rowCount: 20
/* Distance between nodes - not including extended draws*/
, gap// Math.floor(radius * .25)
/* Distance between points */
, pointSpread: radius + gap
, drawTip: true
/* boolean to render the center position of every point*/
, drawPosition: true
, lineColor: 'green'
}
radius = 80
gap = 10 // Math.floor(radius * .25)
conf = {
/* The size of a single position for a path origin */
positionSize: 1
/* the size of the indicator at the end of a path */
, tipRadius: 2
, tipWidth: 2
, lineWidth: 20
/* Position radius*/
, radius
/* How many items per row within the grid */
/* A NxN grid, e.g. 10 == 100 points */
, rowCount: 5
/* Distance between nodes - not including extended draws*/
, gap// Math.floor(radius * .25)
/* Distance between points */
, pointSpread: radius + gap
, drawTip: true
/* boolean to render the center position of every point*/
, drawPosition: true
, lineColor: 'green'
}
const pointList = PointList.generate.list(conf.rowCount * conf.rowCount, 0)
/* To set the position of the grid generator, we can just edit the first point. */
pointList[0].set(20, 20)
/* Then reshape internally */
let ss = pointList.shape.grid(conf.pointSpread, conf.rowCount)
const autoMain = function(){
runTests()
stage = MainStage.go({
loop: false
})
}
class OriginShift {
reset(draw=true){
this.origin = pointList.length - 1
pointList.forEach((p,i)=>{
p.radius = conf.radius
let isLastColumn = (i+1) % conf.rowCount == 0;
let dir = isLastColumn? DOWN_DEG: RIGHT_DEG
p.rotation = dir
})
}
move(count=1) {
for (var i = count - 1; i >= 0; i--) {
this.randomMove()
}
}
walk(count=10) {
this.move(count)
}
randomMove() {
let items = this.nextPossible()
var item = items[Math.floor(Math.random()*items.length)];
// The current node points to the new origin,
// the new origin has no pointer
let current = pointList[this.origin]
let next = pointList[item]
current.lookAt(next)
this.origin = item;
}
nextPossible(index=this.origin) {
return getNeighbours(index, conf.rowCount)
}
}
let os = new OriginShift();
class MainStage extends Stage {
// canvas = document.getElementById('playspace');
canvas = 'playspace'
mounted(){
this.reset()
}
// loopDraw(){
// os.move(1)
// super.loopDraw()
// }
draw(ctx){
/* Without _clear_ the view will redraw on-top of the existing content */
os.move(10)
this.clear(ctx)
this.drawPoints(ctx)
}
reset(draw=true){
os.reset()
draw && this.draw(this.ctx)
}
drawPoints(ctx) {
let o = os.origin
let drawPos = conf.drawPosition
let drawTip = conf.drawTip
pointList.forEach((p, i)=>{
let isOrigin = i == o;
let tip = p.project() // to the radius
// quickStrokeWithCtx(ctx, 'red', 1)
this.drawDirectionLine(p, tip, isOrigin, ctx)
drawPos && p.pen.circle(ctx, 2, 'black', 3)
!isOrigin && drawTip && this.drawTip(tip, isOrigin, ctx)
})
this.drawOriginNode(ctx);
}
drawDirectionLine(p, tip, isOrigin, ctx,){
ctx.beginPath()
if(!isOrigin) {
// tip.draw.circle(ctx, tipRadius)
/* stencil a line from the tip, back to _p_; the start position */
tip.draw.lineTo(ctx, p)
}
/* draw render the line */
quickStrokeWithCtx(ctx, conf.lineColor, conf.lineWidth)
}
drawTip(tip, isOrigin, ctx) {
/* Draw the _tip_ of a projection. */
ctx.beginPath()
tip.draw.circle(ctx, conf.tipRadius)
quickStrokeWithCtx(ctx, isOrigin? 'red':'grey', conf.tipWidth)
}
drawOriginNode(ctx) {
let o = os.origin
ctx.beginPath();
pointList[o].draw.circle(ctx, 2)
quickStrokeWithCtx(ctx, 'red', conf.lineWidth)
}
}
/*
// Example usage:
rowCount = 9;
positionIndex = 5;
console.log(getNeighbours(positionIndex, rowCount)); // Output: [1, 7, 3, 5]
*/
function getNeighbours(index, rowWidth) {
const row = Math.floor(index / rowWidth)
, col = index % rowWidth
, size = rowWidth * rowWidth
, up = index - rowWidth
, left = index - 1
, right = index + 1
, down = index + rowWidth
, res = []
;
// console.log(index, 'up', up, 'left', left, 'right', right, 'down', down)
const inBounds = (v) => (v >= 0) && (v < size);
const boundPush = (v) => inBounds(v) && res.push(v);
boundPush(up);
boundPush(down);
// if most left (col 0), left cannot be applied.
(col > 0) && boundPush(left);
// if most right (col == rowWidth), right cannot be applied.
(col != rowWidth-1) && boundPush(right);
return res.sort()
}
const arrayMatch = (a,b) => {
let sb = b.sort()
return (a.length == b.length ) && a.sort().every((e,i)=>sb[i]==e)
}
const runTests = function(){
runOne(0, [1, 3], 'first item')
runOne(1, [0, 2, 4], 'first row center item')
runOne(2, [1, 5], 'first row last item')
runOne(3, [0, 4, 6], 'second row first item')
runOne(4, [1, 3, 5, 7], 'center')
runOne(5, [2, 4, 8], 'second row last item')
runOne(6, [3, 7], 'last row first item')
runOne(7, [4, 6, 8], 'last row center item')
runOne(8, [5, 7], 'last item')
}
const runOne = function(index, expected, extra='') {
res = getNeighbours(index, 3)
exp = expected
extra = extra.length == 0? extra: `${extra}, `
let isMatch = arrayMatch(res, exp)
let f = isMatch? 'log': 'warn'
if(!isMatch) {
console[f](`match=${isMatch} (${index}) result=${res} != expected=${exp}, ${extra}`)
}
}
;autoMain();
copy