// calculate tiles const RADIUS_OPTS = [ "const", "right", "left", "up", "down", "right-up", "right-down", "left-up", "left-down", "in", "out", ]; function distance(dx, dy) { return Math.sqrt(dx ** 2 + dy ** 2); } class DotMaker { constructor(width) { this.width = width; this.cx = 0.5 * width; this.cy = 0.5 * width; } dots(m, n) { if( m - n === 0 ) { return []; } const ps = []; const imin = -this.width; const imax = this.width / m; for( let i = imin; i <= imax; i++ ) { const jmin = m * i + (m - n) * this.width; const jmax = m * i; for( let j = jmin; j <= jmax; j++ ) { const x = (j - m * i) / (m - n); const y = m * (x + i); if( x > 0 && y > 0 && x < this.width && y < this.width ) { ps.push({i:i, j:j, x:x, y:y}); } } } return ps; } radius(d, func, maxr) { switch (func) { case "const": return maxr; case "right": return maxr * d.x / this.width; case "left": return maxr * (this.width - d.x) / this.width; case "down": return maxr * d.y / this.width; case "up": return maxr * (this.width - d.y) / this.width; case "right-up": return 0.5 * maxr * (d.x + this.width - d.y) / this.width; case "left-up": return 0.5 * maxr * (this.width - d.x + this.width - d.y) / this.width; case "right-down": return 0.5 * maxr * (d.x + d.y) / this.width; case "left-down": return 0.5 * maxr * (this.width - d.x + d.y) / this.width; case "out": return 2 * maxr * distance((d.x - this.cx), (d.y - this.cy)) / this.width; case "in": return 2 * maxr * (0.5 * this.width - distance((d.x - this.cx), (d.y - this.cy))) / this.width; default: return maxr; } } } export { RADIUS_OPTS, DotMaker };