JSFiddle - React, Tailwind, and code Playground

by Stanislav Doronin

HTML

<canvas id='myCanvas'> </canvas>

JavaScript

// n - показатель преломления
function trace_rays(n) {
	var points = [];
	for (var i=-0.95; i<1; i=i+0.05) {
		var a = Math.acos(i);
		var b = Math.PI / 2.0 - a;
		var b1 = Math.asin(Math.sin(b)/n);
		
		var x0 = i;
		var y0 = 2;
		
		var x1 = i;
		var y1 = Math.sin(a);
		
		var b1_ = b1 - b;
		
		var l = 2 * Math.sin(Math.PI/2.0 - b1);
		
		var x2 = x1 + Math.sin(b1_) * l;
		var y2 = y1 - Math.cos(b1_) * l;
		
		var b3 = Math.PI/2 + Math.acos(x2);
		var b3_ = Math.PI + b3 + b;
		
		var x3 = x2 - Math.sin(b3_) * 2;
		var y3 = y2 - Math.cos(b3_) * 2;
		
		var ray = [[x0,y0],[x1,y1],[x2,y2],[x3,y3]];
		
		var ortl = 0.1;
		var ort1 = [[x1 + Math.sin(b)*ortl, y1 + Math.cos(b)*ortl], [x1 - Math.sin(b)*ortl, y1 - Math.cos(b)*ortl]];
		
		var ort2 = [[x2 + Math.sin(b3)*ortl, y2 + Math.cos(b3)*ortl], [x2 - Math.sin(b3)*ortl, y2 - Math.cos(b3)*ortl]];
		
		points.push(ray,ort1,ort2);
	}
	return points;
}

function draw_glass(ctx,sx,sy,k) {
	ctx.beginPath();
    ctx.arc(sx*k, sy*k, k, 0, 2 * Math.PI, false);
	ctx.stroke();
}

function draw_rays(ctx,sx,sy,k,rays) {
	while (rays.length>0) {
		var ray = rays.shift();
		var p = ray.shift();
		ctx.beginPath();
		ctx.moveTo((p[0]+sx)*k, (p[1]+sy)*k);
		while (ray.length>0) {
			p = ray.shift();
			ctx.lineTo((p[0]+sx)*k, (p[1]+sy)*k);
		}
		ctx.stroke();
	}
}

	var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext('2d');
    canvas.width  = 1000;
	canvas.height = 800;
	
	var rays1 = trace_rays(1.33);
	var rays2 = trace_rays(1);
	
	var k = 100;
	var sx = 2;
	var sy = 3;
	draw_rays(ctx,sx,sy,k,rays2);
	draw_glass(ctx,sx,sy,k);
	sx = 4.2;
	draw_rays(ctx,sx,sy,k,rays1);
	draw_glass(ctx,sx,sy,k);