JSFiddle - React, Tailwind, and code Playground

by malikzh

HTML

<div class="cnv">
   <canvas width="300" id="cmap" height="300"></canvas>
   <canvas width="300" id="hmap" height="300" style="display: none;"></canvas>
   <canvas width="300" id="qmap" height="300" style="display: block;"></canvas>
</div>
<div class="params">
  <div class="param">
    <div>
      alpha
    </div>
    <div>
      <input type="number" id="v-alpha" value="0.45" step="0.01">
    </div>
  </div>
  <div class="param">
    <div>
      epsilon
    </div>
    <div>
      <input type="number" id="v-epsilon" value="0.15" step="0.01">
    </div>
  </div>
  <div class="param">
    <div>
      gamma
    </div>
    <div>
      <input type="number" id="v-gamma" value="0.94" step="0.01">
    </div>
  </div>
  <div class="param">
    <button id="b-start">
       Начать обучение
    </button>
    <button id="b-reset">
       Сброс
    </button>
  </div>
</div>

<div style="margin-top: 10px;">
   Типа консоль :)
</div>

<div id="our-console"></div>

CSS

canvas {
  border: 1px solid #ccc;
}

.param {
  margin-top: 20px;
}

#our-console {
  width: 500px;
  height: 250px;
  overflow: scroll;
  border: 1px solid #ccc;
  font-family: monospace;
}

#our-console > div {
  padding: 5px 0;
  border-bottom: 1px solid #ccc;
}

JavaScript

// Теорема пифагора, только без корня, чтобы быстрее было
function norm(a, b) {
	return a ** 2 + b ** 2;
}

class Vector {
	constructor(x, y) {
  	this.x = x;
    this.y = y;
  }
  
  scale(n) {
  	this.x *= n;
    this.y *= n;
    return this;
  }
  
  clamp(x0, y0, x1, y1) {
  	this.x = Math.min(x1, Math.max(x0, this.x));
    this.y = Math.min(y1, Math.max(y0, this.y));
  	return this;
  }
  
  move(x, y) {
  	this.x += x;
    this.y += y;
    return this;
  }
}

//  Алгоритм поиска ближайшего расстояния маршрута в заданной точке заданной дистанции
function findNearest(map, x, y, d) {
	const THRESHOLD = 0xFF;
  const avg = (color) => Math.round((color[0] + color[1] + color[2]) / 3);
  
  let dist = +Infinity;
  
  // проверяем саму точку
  if (avg(map.getColor(x, y)) >= THRESHOLD) {
  	return 0;
  }
  
  const TR = new Vector(1, -1).scale(d).move(x, y).clamp(0, 0, map.width(), map.height()); // top-right
  const TL = new Vector(-1, -1).scale(d).move(x, y).clamp(0, 0, map.width(), map.height()); // top-left
  const BR = new Vector(1, 1).scale(d).move(x, y).clamp(0, 0, map.width(), map.height()); // bottom-right
  const BL = new Vector(-1, 1).scale(d).move(x, y).clamp(0, 0, map.width(), map.height()); // bottom-left
  
  
  // TL -> TR : H
  for (let i=TL.x; i<=TR.x; ++i) {
  	const color = map.getColor(i, TL.y);
    
    if (avg(color) >= THRESHOLD) {
    	dist = Math.min(dist, norm(x - i, y - TL.y));
    }
  }
  
  // BL -> BR : H
  for (let i=BL.x; i<=BR.x; ++i) {
  	const color = map.getColor(i, BL.y);
    
    if (avg(color) >= THRESHOLD) {
    	dist = Math.min(dist, norm(x - i, y - BL.y));
    }
  }
  
  
  // TL -> BL : V
  for (let i=TL.y; i<=BL.y; ++i) {
  	const color = map.getColor(TL.x, i);
    
    if (avg(color) >= THRESHOLD) {
    	dist = Math.min(dist, norm(x - TL.x, y - i));
    }
  }
  
  // TR -> BR : V
  for (let i=TR.y; i<=BR.y; ++i) {
  	const color = map.getColor(TR.x, i);
    
    if (avg(color) >= THRESHOLD) {
    	dist = Math.min(dist,...