c2.js with ascii

A combination of ideas from here, and here.


<script src="/scripts/c2.min.js"></script>

<canvas id="c2"></canvas>
<div id="ascii_div"></div>

<script>
   const renderer = new c2.Renderer (document.getElementById ('c2'));
   resize ()

   renderer.background ('turquoise')
   let random = new c2.Random ()

   class Agent extends c2.Point {
      constructor () {
         let x = random.next (renderer.width)
         let y = random.next (renderer.height)
         super (x, y)

         this.vx = random.next (-2, 2)
         this.vy = random.next (-2, 2)
      }

      update() {
         this.x += this.vx
         this.y += this.vy

         if (this.x < 0) {
               this.x = 0
               this.vx *= -1
         } else if (this.x > renderer.width) {
               this.x = renderer.width
               this.vx *= -1
         }
         if (this.y < 0) {
               this.y = 0
               this.vy *= -1
         } else if (this.y > renderer.height) {
               this.y = renderer.height
               this.vy *= -1
         }
      }
   }

   let agents = new Array (20)
   for (let i = 0; i < agents.length; i++) agents[i] = new Agent ()

   const chars = "¶Ñ@%&∆∑∫#Wߥ$£√?!†§ºªµ¢çø∂æåπ*™≤≥≈∞~,.…_¬“‘˚`˙"

   const div = document.getElementById (`ascii_div`)
   div.style.fontFamily = `monospace`
   div.style.textAlign = `center`

   renderer.draw (() => {
      renderer.clear ()

      let delaunay = new c2.Delaunay ()
      delaunay.compute (agents)
      let vertices = delaunay.vertices
      let edges = delaunay.edges
      let triangles = delaunay.triangles

      let maxArea = 0
      let minArea = Number.POSITIVE_INFINITY;
      for (let i = 0; i < triangles.length; i++) {
         let area = triangles[i].area ()
         if (area < minArea) minArea = area
         if (area > maxArea) maxArea = area
      }

      renderer.stroke (false)
      for (let i = 0; i < triangles.length; i++) {
         let t = c2.norm (triangles[i].area(), minArea, maxArea)
         let color = c2.Color.hsl (315+30*t, 30+30*t, 20+80*t)
         renderer.fill (color)
         renderer.triangle (triangles[i])
      }

      for (let i = 0; i < agents.length; i++) {
         agents[i].update ()
      }
      
      const w = renderer.canvas.width
      const h = renderer.canvas.height
      const pixels = renderer.context.getImageData (0, 0, w, h).data

      let ascii_img = ``

      for (let y = 0; y < renderer.canvas.height; y += 22) {
         for (let x = 0; x < renderer.canvas.width; x += 10) {
            const i = (y * renderer.canvas.width + x) * 4
            const r = pixels[i]
            const g = pixels[i + 1]
            const b = pixels[i + 2]
            const br = (r * g * b / 16581376) ** 0.1
            const char_i = Math.floor (br * chars.length)
            ascii_img += chars[char_i]
         }
         ascii_img += `\n`
      }

      div.innerText = ascii_img

   })

   function resize () {
      let parent = renderer.canvas.parentElement
      renderer.size (parent.clientWidth, parent.clientWidth / 16 * 9)
   }
</script>