Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* gen by new.py at 2020-11-28 01:42:48.024758 */
- window.onload = async function onload() {
- // if ('seedrandom' in Math) Math.seedrandom('0');
- const height = 400;
- const width = 400;
- const ctx = document.createElement('canvas').getContext('2d');
- ctx.canvas.height = height;
- ctx.canvas.width = width;
- document.body.appendChild(ctx.canvas);
- ctx.imageSmoothingEnabled = false;
- const COLORS = Array(10).fill().map(() => `rgb(${Array(3).fill().map(() => Math.random()*256)})`);
- ctx.save();
- ctx.fillStyle = 'black';
- ctx.fillRect(0, 0, width, height);
- ctx.translate(200, 200);
- ctx.scale(6, 6);
- const grid = new InfinitGrid();
- const rect_max_w = 20;
- const rect_max_h = 20;
- const rect_min_w = 4;
- const rect_min_h = 4;
- const rect_min_per = 4; // any face of rect must be equal or greater than rect_min_per
- const tries_num = 1000;
- const rects_num = 3;
- const rects = [];
- for (let i = 0; i < rects_num; ++i) {
- for (let t = 0; t < tries_num; ++t) {
- const parent = rects[Math.random() * rects.length | 0] || [0, 0, 0, 0];
- const w = rect_min_w + Math.random() * (rect_max_w - rect_min_w) | 0;
- const h = rect_min_h + Math.random() * (rect_max_h - rect_min_h) | 0;
- const angle = Math.random() * Math.PI * 2;
- const r = (Math.min(parent[2], parent[3]) + Math.min(w, h)) / 2;
- const x = parent[0] + parent[2] / 2 + r * Math.cos(angle) - w / 2 | 0;
- const y = parent[1] + parent[3] / 2 + r * Math.sin(angle) - h / 2 | 0;
- if (grid.fill_back(x, y, w, h, i) === 0) continue; // area == 0
- // TODO: нужно найти все точки, граничащие с void'ом, и посчитать длину стрипа до любого другого индекса (или воида).
- // если длина стрипа меньше rect_min_per -- не ok.
- if (grid.faces(i, null, x, y, x+w, y+h).some((side) => side.some((line) => {
- const w = Math.abs(line[2]-line[0]);
- const h = Math.abs(line[3]-line[1]);
- return w > 0 && w < rect_min_per || h > 0 && h < rect_min_per;
- })))
- { // not ok
- grid.clear_value(i);
- } else { // ok
- rects.push([x, y, w, h]);
- break;
- }
- }
- }
- for (let y = grid.top; y <= grid.bottom; ++y) {
- if (grid.grid[y] instanceof Array) {
- for (let x = grid.left; x <= grid.right; ++x) {
- if (grid.grid[y][x] != null) {
- ctx.fillStyle = COLORS[grid.grid[y][x]];
- ctx.fillRect(x, y, 0.9, 0.9);
- }
- }
- }
- }
- ctx.restore();
- }
- // negative indices will be used, also no boundary checks
- class InfinitGrid {
- constructor() {
- this.grid = [];
- this.top = 0;
- this.left = 0;
- this.right = 0;
- this.bottom = 0;
- }
- get(x, y) {
- if (this.grid[y] instanceof Array) {
- return this.grid[y][x];
- }
- return null;
- }
- // intersection_area(x, y, w, h) {
- // let area = 0;
- // for (let y0 = 0; y0 < h; ++y0) {
- // if (this.grid[y0+y] instanceof Array) {
- // for (let x0 = 0; x0 < w; ++x0) {
- // area += ~~(this.grid[y0+y][x0+x] != null);
- // }
- // }
- // }
- // return area;
- // }
- fill_back(x, y, w, h, value) {
- let area = 0;
- if (x < this.left) this.left = x;
- if (x+w > this.right) this.right = x+w;
- if (y < this.top) this.top = y;
- if (y+h > this.bottom) this.bottom = y+h;
- for (let y0 = 0; y0 < h; ++y0) {
- if (!(this.grid[y0+y] instanceof Array)) {
- this.grid[y0+y] = [];
- }
- for (let x0 = 0; x0 < w; ++x0) {
- if (this.grid[y0+y][x0+x] == null) {
- this.grid[y0+y][x0+x] = value;
- ++area;
- }
- }
- }
- return area;
- }
- /*
- clone() {
- const clone = new this.constructor();
- for (let y = this.top; y <= this.bottom; ++y) {
- if (this.grid[y] instanceof Array) {
- clone.grid[y] = [];
- for (let x = this.left; x <= this.right; ++x) {
- if (this.grid[y][x] != null) {
- clone.grid[y][x] = this.grid[y][x];
- }
- }
- }
- }
- clone.top = this.top;
- clone.left = this.left;
- clone.right = this.right;
- clone.bottom = this.bottom;
- return clone;
- }
- */
- clear_value(value) {
- for (let y = this.top; y <= this.bottom; ++y) {
- if (this.grid[y] instanceof Array) {
- for (let x = this.left; x <= this.right; ++x) {
- if (this.grid[y][x] === value) {
- this.grid[y][x] = null;
- }
- }
- }
- }
- }
- // make_outlines from creature/grid.js~205
- faces(for_index, void_value, left, top, right, bottom) {
- top = top || this.top;
- left = left || this.left;
- right = right || this.right;
- bottom = bottom || this.bottom;
- void_value = void_value || null;
- const FCI = for_index != null; // "for certain index" flag (if not then for all non null)
- const FIV = FCI ? for_index : void_value; // "for_index" value
- const faces_L=[], faces_T=[], faces_R=[], faces_B=[];
- for (let y = top; y <= bottom; ++y) {
- if (!(this.grid[y] instanceof Array)) continue;
- for (let x = left; x <= right; ++x) {
- if (this.grid[y][x] == void_value) continue; // skip void cell.
- if (FCI && this.grid[y][x] != FIV) continue; // skip for certain index.
- if (this.grid[y][x-1] == FIV ^ FCI) {
- const line = faces_L.find((line) => x === line[0] && y === line[3]);
- if (line) line[3] = y+1; else faces_L.push([x, y, x, y+1]);
- }
- if (this.grid[y][x+1] == FIV ^ FCI) {
- const line = faces_R.find((line) => x+1 === line[0] && y === line[3]);
- if (line) line[3] = y+1; else faces_R.push([x+1, y, x+1, y+1]);
- }
- if (!(this.grid[y-1] instanceof Array) || (this.grid[y-1][x] == FIV ^ FCI)) {
- const line = faces_T.find((line) => y === line[1] && x === line[2]);
- if (line) line[2] = x+1; else faces_T.push([x, y, x+1, y]);
- }
- if (!(this.grid[y+1] instanceof Array) || (this.grid[y+1][x] == FIV ^ FCI)) {
- const line = faces_B.find((line) => y+1 === line[1] && x === line[2]);
- if (line) line[2] = x+1; else faces_B.push([x, y+1, x+1, y+1]);
- }
- }
- }
- return [faces_L, faces_T, faces_R, faces_B];
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement