I have a certain figure drawn in Canvas. It is necessary to mirror the shape of a given line. Tell me how to implement JavaScript?
1 answer
Something I got into this task))
In general, one way to build a reflection is to drop the perpendicular from each point of the polygon to a line, find the coordinates of these points, and shift them to the vector of this perpendicular, since this value should be the same for both the reflected and the original polygon.
Essentially, it all comes down to finding these points on a line.
Let P0 a certain point of a polygon, denote by P1 , P2 points through which the line passes.
and let A be the point on the line obtained by the method described above.
then, due to the fact that the angle between the vectors (P0, A)(P1, P2) straight line - their scalar product (P0, A)(P1, P2) = 0
but on the other hand, A belongs to the line (P1, P2)
therefore, we get a simple system of two equations with two unknowns (Ax, Ay)
(Ax - P0.x)*(P2.x - P1.x) + (Ay - P0.y)*(P2.y - P1.y) = 0 (Ax - P1.x)*(P2.y - P1.y) - (Ay - P1.y)*(P2.x - P1.x) = 0 denote by B = P2.x - P1.x and C = P2.y - P1.y
after the simplest identity transformations of this system, we obtain an equivalent system
B*Ax + C*Ay = B*P0.x + C*P0.y C*Ax - B*Ay = C*P1.x - B*P1.y trivially solvable, for example, by the cramer method.
|B*P0.x + C*P0.y, C| |C*P1.x - B*P1.y, -B| Ax = --------------------- -B*B - C*C |B, B*P0.x + C*P0.y| |C, C*P1.y - B*P1.y| Ay = --------------------- -B*B - C*C and the final formula of a certain point of the reflected polygon will be
x = Ax + (Ax - P0.x) y = Ay + (Ay - P0.y) (function() { const cnv = document.getElementById("cnv"); const ctx = cnv.getContext("2d"); const reflectbtn = document.getElementById("reflect"); const againbtn = document.getElementById("again"); function initApp() { cnv.width = window.innerWidth; cnv.height = window.innerHeight; } let Vec2 = function(x = 0, y = 0) { this.x = x; this.y = y; } let polygonVertices = [ new Vec2(150, 110), new Vec2(230, 10), new Vec2(300, 110) ]; let reflectionLinePoints = [ new Vec2(200, 310), new Vec2(300, 10) ]; function drawPolygon(vertices) { if (vertices.length == 0) return; vertices.forEach(function(v) { drawPoint(v); }); ctx.beginPath(); vertices.forEach(function(v) { ctx.lineTo(vx, vy); }); ctx.lineTo(vertices[0].x, vertices[0].y); ctx.stroke(); ctx.closePath(); } function drawLine(linePoints) { drawPoint(linePoints[0]); drawPoint(linePoints[1]); ctx.save(); ctx.beginPath(); ctx.setLineDash([5, 5]); ctx.moveTo(linePoints[0].x, linePoints[0].y); ctx.lineTo(linePoints[1].x, linePoints[1].y); ctx.stroke(); ctx.closePath(); ctx.restore(); } function computeA(p0, p1, p2) { let b = p2.x - p1.x; let c = p2.y - p1.y; let denom = b * (-b) - c * c; let ax = -b * (b * p0.x + c * p0.y) - c * (c * p1.x - b * p1.y); let ay = b * (c * p1.x - b * p1.y) - c * (b * p0.x + c * p0.y); return new Vec2( ax / denom, ay / denom ); } function drawPoint(p) { ctx.beginPath(); ctx.arc(px, py, 3, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); } function reflect(linePoints, polygonPoints) { let points = []; polygonPoints.forEach(function(p, i) { let a = computeA(p, linePoints[0], linePoints[1]); ax += ax - px; ay += ay - py; points.push(a); }); return points; } initApp(); drawPolygon(polygonVertices); drawLine(reflectionLinePoints); reflectbtn.onclick = function() { ctx.clearRect(0, 0, cnv.width, cnv.height); drawPolygon(polygonVertices); drawLine(reflectionLinePoints); let reflectedPoints = reflect(reflectionLinePoints, polygonVertices); drawPolygon(reflectedPoints); } againbtn.onclick = function() { ctx.clearRect(0, 0, cnv.width, cnv.height); drawPolygon(polygonVertices); drawLine(reflectionLinePoints); } }()); <button id="reflect">reflect</button> <button id="again">again</button> <canvas id="cnv"></canvas> 
ctx.save //save ctx.draw //draw shape ctx.scale(-1, 1); //rotate shape ctx.restore // restorectx.save //save ctx.draw //draw shape ctx.scale(-1, 1); //rotate shape ctx.restore // restore- TitaN