Best Fit Rectangle

Calculates point averages to come up with the best fitting rectangle

by wio_dude

HTML

<input id="clear" type="button" value="clear" />
<input id="segments" type="checkbox" checked />
<label for="segments">edge colors</label>
<input id="averages" type="checkbox" checked /> 
<label for="segments">average points</label>
<input id="fitrect" type="checkbox" checked />
<label for="segments">best fit rectangle</label>
<br/>
<canvas id="draw" height="500" width="500"></canvas>

CSS

canvas {
  background-color: yellow
}

JavaScript

const draw = document.getElementById('draw')
const clear = document.getElementById('clear')
const segments = document.getElementById('segments')
const averages = document.getElementById('averages')
const fitrect = document.getElementById('fitrect')

const ctx = draw.getContext('2d')


class DrawingCanvas {
	constructor(opts) {
  	this.canvas = opts.canvas
    this.tool = opts.tool
    this.tools = opts.tools
    this.listeners = [
    	['mousedown', this.drawStart.bind(this)],
    	['mousemove', this.drawContinue.bind(this)],
    	['mouseup', this.drawEnd.bind(this)]
    ]
    this.addListeners()
  }
  
  addListeners() {
  	for (const [type, handler] in liteners) {
    	this.canvas.addEventListener(type, handler)
    }
  }
  
  removeListeners() {
  	for (const [type, handler] in liteners) {
    	this.canvas.removeEventListener(type, handler)
    }
  }
  
  canvasCoords(evt) {
    const rect = this.canvas.getBoundingClientRect()
    return [
      evt.clientX - rect.left,
      evt.clientY - rect.top
    ]
  }
  
  drawStart(evt) {
  	if (this.tool in this.tools) {
    	const tool = this.tools[this.tool]
      tool.drawStart(this.canvasCoords(evt))
    }
  }
  
  drawContinue(evt) {
  	if (this.tool in this.tools) {
    	const tool = this.tools[this.tool]
      tool.drawStart(this.canvasCoords(evt))
    }
  }
  
  drawEnd(evt) {
  	if (this.tool in this.tools) {
    	const tool = this.tools[this.tool]
      tool.drawStart(this.canvasCoords(evt))
    }
  }
}


clear.addEventListener('click', (evt) => {
  drawing.lines = []
  drawing.drawing = false
  drawing.maxDist = 0
})

function last(a) {
  return a[a.length - 1]
}

function pointsIter(points) {
  return {
    points,
    [Symbol.iterator]() {
      return {
        points: this.points,
        index: 1,
        next() {
          if (this.index >= this.points.length) {
            return {
              done: true
            }
          }
          const value = [
            this.points[this.index - 1],
  ...