WIP: don't go through walls?

This commit is contained in:
2026-02-02 10:27:19 -08:00
parent 965ed86ed6
commit 93157f17dd

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- <svg viewBox="-200 -150 400 300" version="1.1" xmlns="http://www.w3.org/2000/svg"> --> <svg viewBox="-200 -150 400 300" version="1.1" xmlns="http://www.w3.org/2000/svg">
<svg viewBox="-20 -20 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg"> <!-- <svg viewBox="-20 -20 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg"> -->
<style> <style>
foreignObject { foreignObject {
font-size: 4pt; font-size: 4pt;
@@ -131,6 +131,8 @@
<!-- <polygon class="wall" points="-10,-40 10,-40 10,-15 -10,-15" /> --> <!-- <polygon class="wall" points="-10,-40 10,-40 10,-15 -10,-15" /> -->
<polygon class="wall" points="-20,-10 20,10 -10,100 -100,100" /> <polygon class="wall" points="-20,-10 20,10 -10,100 -100,100" />
<!-- <polygon class="wall" points="-10,0 10,0 10,10 -10,10" /> -->
<!-- <polygon class="wall" points="-10,10 10,30 -10,40 -20,20" /> --> <!-- <polygon class="wall" points="-10,10 10,30 -10,40 -20,20" /> -->
<!-- <polygon class="wall" points="-20,-10 0,10 -20,20 -30,0" /> --> <!-- <polygon class="wall" points="-20,-10 0,10 -20,20 -30,0" /> -->
@@ -238,15 +240,24 @@ const Move = (() => {
// Triangle has a clockwise orientation // Triangle has a clockwise orientation
function isClockwise([xa, ya], [xb, yb], [xc, yc]) { function isClockwise([xa, ya], [xb, yb], [xc, yc]) {
console.log("isClockwise", xa, ya, xb, yb, xc, yc); // console.log("isClockwise", xa, ya, xb, yb, xc, yc);
// https://en.wikipedia.org/wiki/Curve_orientation#Practical_considerations // https://en.wikipedia.org/wiki/Curve_orientation#Practical_considerations
// Determinant for a convex polygon // Determinant for a convex polygon
const det = (xb - xa) * (yc - ya) - (xc - xa) * (yb - ya); // const det = (xb - xa) * (yc - ya) - (xc - xa) * (yb - ya);
console.log("det", det);
const subR = (a, b) => Math.round(a * 100 - b * 100) / 100;
const xba = subR(xb, xa);
const yca = subR(yc, ya);
const xca = subR(xc, xa);
const yba = subR(yb, ya);
const det = subR(xba * yca, xca * yba);
console.log("dett", det, "edge", xa, ya, xb, yb, "position", xc, yc);
// console.log("xa, ya, xb, yb, xc, yc", xa, ya, xb, yb, xc, yc); // console.log("xa, ya, xb, yb, xc, yc", xa, ya, xb, yb, xc, yc);
const detEx = (xb*expo - xa*expo) * (yc*expo - ya*expo) - (xc*expo - xa*expo) * (yb*expo - ya*expo); // const detEx = (xb*expo - xa*expo) * (yc*expo - ya*expo) - (xc*expo - xa*expo) * (yb*expo - ya*expo);
// console.log("=----", xb*expo - xa*expo, yc*expo - ya*expo, xc*expo - xa*expo, yb*expo - ya*expo); // console.log("=----", xb*expo - xa*expo, yc*expo - ya*expo, xc*expo - xa*expo, yb*expo - ya*expo);
// console.log("=----", xb*expo, xa*expo, yc*expo, ya*expo, xc*expo, xa*expo, yb*expo, ya*expo); // console.log("=----", xb*expo, xa*expo, yc*expo, ya*expo, xc*expo, xa*expo, yb*expo, ya*expo);
// console.log("=----", xb*expo - xa*expo, yc*expo - ya*expo, xc*expo - xa*expo, yb*expo - ya*expo); // console.log("=----", xb*expo - xa*expo, yc*expo - ya*expo, xc*expo - xa*expo, yb*expo - ya*expo);
@@ -291,18 +302,45 @@ const Move = (() => {
// Solve for angles alpha and beta with inverse cosine (arccosine) // Solve for angles alpha and beta with inverse cosine (arccosine)
const numeratorA = Math.round(db ** 2 + dc ** 2 - da ** 2); const numeratorA = Math.round(db ** 2 + dc ** 2 - da ** 2);
const denomA = Math.round(2 * db * dc); const denomA = Math.round(2 * db * dc);
const alpha = Math.acos(numeratorA / denomA); const alphar = Math.acos(numeratorA / denomA);
const numeratorB = Math.round(da ** 2 + dc ** 2 - db ** 2); const numeratorB = Math.round(da ** 2 + dc ** 2 - db ** 2);
const denomB = Math.round(2 * da * dc); const denomB = Math.round(2 * da * dc);
const beta = Math.acos(numeratorB / denomB); const betar = Math.acos(numeratorB / denomB);
console.log(da, db, dc, alpha, beta);
const numA = db ** 2 + dc ** 2 - da ** 2;
const numAr = Math.round((db ** 2 * 100 + dc ** 2 * 100 - da ** 2 * 100) / 100);
const denA = Math.round(2 * db * dc);
const numB = da ** 2 + dc ** 2 - db ** 2;
const numBr = Math.round((da ** 2 * 100 + dc ** 2 * 100 - db ** 2 * 100) / 100);
const denB = Math.round(2 * da * dc);
const aRad = numAr / denA;
const bRad = numBr / denB;
const thetaA = aRad > 1 ? 1 : aRad;
const thetaB = bRad > 1 ? 1 : bRad;
const alpha = Math.acos(thetaA);
const beta = Math.acos(thetaB);
// const alpha = Math.acos((db ** 2 + dc ** 2 - da ** 2) / (2 * db * dc));
// const beta = Math.acos((da ** 2 + dc ** 2 - db ** 2) / (2 * da * dc));
console.log("2 * db * dc", denA, "dett");
console.log("2 * da * dc", denB, "dett");
console.log("db ** 2 + dc ** 2 - da ** 2", numAr, "dett");
console.log("da ** 2 + dc ** 2 - db ** 2", numBr, "dett");
console.log("(db ** 2 + dc ** 2 - da ** 2) / (2 * db * dc)", thetaA, "dett");
console.log("(da ** 2 + dc ** 2 - db ** 2) / (2 * da * dc)", thetaB, "dett");
// console.log("alpha", +alpha.toFixed(15), "beta", +beta.toFixed(15), "da, db, dc", da, db, dc, "dett");
console.log("alpha", alpha, "beta", beta, "da, db, dc", da, db, dc, "dett");
return alpha < halfPi && beta < halfPi; return alpha < halfPi && beta < halfPi;
} }
function getForwardEdges(edges, { x, y }) { function getForwardEdges(edges, { x, y }) {
return edges.filter(({ edge: { xa, ya, xb, yb } }) => return edges.filter(({ edge: { xa, ya, xb, yb } }) => {
isClockwise([xa, ya], [xb, yb], [x, y]) && isAcute([xa, ya], [xb, yb], [x, y])); return isClockwise([xa, ya], [xb, yb], [x, y]) && isAcute([xa, ya], [xb, yb], [x, y]);
});
} }
function getForwardCorners(corners, position, velocity) { function getForwardCorners(corners, position, velocity) {
@@ -390,6 +428,10 @@ const Move = (() => {
// const { xa: x3, ya: y3, xb: x4, yb: y4 } = edgeSeg; // const { xa: x3, ya: y3, xb: x4, yb: y4 } = edgeSeg;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = edge; const { xa: x3, ya: y3, xb: x4, yb: y4 } = edge;
console.log("x1", x1, "y1", y1, "x2", x2, "y2", y2);
console.log("x3", x3, "y3", y3, "x4", x4, "y4", y4);
// https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments // https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments
// https://en.wikipedia.org/wiki/Cramer%27s_rule#Explicit_formulas_for_small_systems // https://en.wikipedia.org/wiki/Cramer%27s_rule#Explicit_formulas_for_small_systems
// const denom = (x2-x1)*(y4-y3)-(x4-x3)*(y2-y1); // const denom = (x2-x1)*(y4-y3)-(x4-x3)*(y2-y1);
@@ -423,8 +465,8 @@ const Move = (() => {
const denom = x21*y43-x43*y21; const denom = x21*y43-x43*y21;
const denomr = Math.round(x21r*100*y43r-x43r*y21r*100) / 100; const denomr = Math.round(x21r*100*y43r-x43r*y21r*100) / 100;
console.log("denom", denom); // console.log("denom", denom);
console.log("denomr", denomr, x21r, y43r, x43r, y21r); // console.log("denomr", denomr, x21r, y43r, x43r, y21r);
const x31 = x3-x1; const x31 = x3-x1;
const x31r = subR(x3, x1); const x31r = subR(x3, x1);
@@ -449,10 +491,13 @@ const Move = (() => {
// const t = +(-(x21*y31-x31*y21).toPrecision(13) / denom).toPrecision(13); // const t = +(-(x21*y31-x31*y21).toPrecision(13) / denom).toPrecision(13);
const s = (x31*y43-x43*y31) / denom; const s = (x31*y43-x43*y31) / denom;
const t = -(x21*y31-x31*y21) / denom; const t = -(x21*y31-x31*y21) / denom;
const sr = (x31r*y43r-x43r*y31r) / denomr; // const sr = (x31r*y43r-x43r*y31r) / denomr;
const tr = (-(x21r*y31r*100*100-x31r*y21r*100*100) / denomr)/10000; const sr = Math.round((x31r*y43r-x43r*y31r) / denomr * 100) / 100;
console.log(x21r, y31r, x31r, y21r, denomr); // const tr = (-(x21r*y31r*100*100-x31r*y21r*100*100) / denomr)/10000;
const tr = -Math.round((x21r*y31r-x31r*y21r) / denomr * 100) / 100;
// console.log(x21r, y31r, x31r, y21r, denomr);
// console.log("checking edge for collision", edge); // console.log("checking edge for collision", edge);
// console.log("position edge segs", positionSeg, edgeSeg); // console.log("position edge segs", positionSeg, edgeSeg);
@@ -474,8 +519,9 @@ const Move = (() => {
// const xs = x1 + s * (x2 - x1); // const xs = x1 + s * (x2 - x1);
// const ys = y1 + s * (y2 - y1); // const ys = y1 + s * (y2 - y1);
const xs = x1 + sr * (x2 - x1); const xs = x1 + s * (x2 - x1);
const ys = y1 + sr * (y2 - y1); const ys = y1 + s * (y2 - y1);
console.log("xs", xs, "ys", ys);
// Math.round(Math.round(-2.03 * 100) + 0.45000000000000445 * (Math.round(-1.95 * 100) - Math.round(-2.03 * 100))) / 100 // Math.round(Math.round(-2.03 * 100) + 0.45000000000000445 * (Math.round(-1.95 * 100) - Math.round(-2.03 * 100))) / 100
// console.log("xs", xs, "ys", ys); // console.log("xs", xs, "ys", ys);
@@ -486,12 +532,32 @@ const Move = (() => {
const x2r = Math.round(x2 * 100); const x2r = Math.round(x2 * 100);
const y1r = Math.round(y1 * 100); const y1r = Math.round(y1 * 100);
const y2r = Math.round(y2 * 100); const y2r = Math.round(y2 * 100);
const x3r = Math.round(x3 * 100);
const x4r = Math.round(x4 * 100);
const y3r = Math.round(y3 * 100);
const y4r = Math.round(y4 * 100);
const xsr = Math.round(x1r + s * (x2r - x1r)) / 100; const xsr = Math.round(x1r + sr * (x2r - x1r)) / 100;
const ysr = Math.round(y1r + s * (y2r - y1r)) / 100; const ysr = Math.round(y1r + sr * (y2r - y1r)) / 100;
const xtr = Math.round(x3r + tr * (x4r - x3r)) / 100;
const ytr = Math.round(y3r + tr * (y4r - y3r)) / 100;
console.log("xsr", xsr, "ysr", ysr, " ::: xtr", xtr, "ytr", ytr);
const lnD = distance(xtr, ytr, edge.xa, edge.ya);
const ln = document.createElementNS(namespaceURIsvg, 'line');
ln.setAttribute('x1', edge.xa);
ln.setAttribute('y1', edge.ya);
ln.setAttribute('x2', edge.xb);
ln.setAttribute('y2', edge.yb);
const lnP = ln.getPointAtLength(lnD);
// collision.position = { x: xs, y: ys }; // collision.position = { x: xs, y: ys };
collision.position = { x: xsr, y: ysr }; collision.position = { x: xsr, y: ysr };
// collision.position = { x: xtr, y: ytr };
// collision.position = lnP;
// console.log("xs, yx", xs, ys); // console.log("xs, yx", xs, ys);
// console.log("xc, yc", xc, yc); // console.log("xc, yc", xc, yc);
@@ -536,8 +602,8 @@ const Move = (() => {
} }
function distance(x1, y1, x2, y2) { function distance(x1, y1, x2, y2) {
// return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
return Math.round(Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) * 100) / 100; // return Math.round(Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) * 100) / 100;
} }
function detectCornerCollision([xc, yc], [x, y], radius) { function detectCornerCollision([xc, yc], [x, y], radius) {
@@ -678,10 +744,23 @@ const Move = (() => {
// console.log("vx", vx, "vy", vy); // console.log("vx", vx, "vy", vy);
// console.log("ax", ax, "ay", ay); // console.log("ax", ax, "ay", ay);
const v = { const vr = {
x: vx > 0 && vx + ax <= 0 ? 0 : vx + ax, x: Math.round(vx * 100 + ax * 100) / 100,
y: vy > 0 && vy + ay <= 0 ? 0 : vy + ay y: Math.round(vy * 100 + ay * 100) / 100
}; };
const v = {
x: vx > 0 && vr.x <= 0 ? 0 : vr.x,
y: vy > 0 && vr.y <= 0 ? 0 : vr.y
};
// const v = {
// x: vx > 0 && vx + ax <= 0 ? 0 : vx + ax,
// y: vy > 0 && vy + ay <= 0 ? 0 : vy + ay
// };
console.log("v", v, "ax", ax, "ay", ay);
// v.x = +v.x.toPrecision(13); // v.x = +v.x.toPrecision(13);
// v.y = +v.y.toPrecision(13); // v.y = +v.y.toPrecision(13);
@@ -756,10 +835,16 @@ const Move = (() => {
const vDotn = edgeNrmlVect.x * velocityVect.x + edgeNrmlVect.y * velocityVect.y; const vDotn = edgeNrmlVect.x * velocityVect.x + edgeNrmlVect.y * velocityVect.y;
// const aDotn = edgeNrmlVect.x * accVect.x + edgeNrmlVect.y * accVect.y; // const aDotn = edgeNrmlVect.x * accVect.x + edgeNrmlVect.y * accVect.y;
const denom = edgeNrmlVect.x ** 2 + edgeNrmlVect.y ** 2; const denom = edgeNrmlVect.x ** 2 + edgeNrmlVect.y ** 2;
const pVect = { const pVect = {
x: vDotn / denom * edgeNrmlVect.x, x: vDotn / denom * edgeNrmlVect.x,
y: vDotn / denom * edgeNrmlVect.y y: vDotn / denom * edgeNrmlVect.y
}; };
// (-1.2*100 - -14.8*100)/100
console.log("vDotn", vDotn);
console.log("denom", denom);
console.log("pVect", pVect);
// const aVect = { // const aVect = {
// x: aDotn / denom * edgeNrmlVect.x, // x: aDotn / denom * edgeNrmlVect.x,
@@ -770,8 +855,12 @@ const Move = (() => {
// const reverseA = { x: -aVect.x, y: -aVect.y }; // const reverseA = { x: -aVect.x, y: -aVect.y };
// add reverseP and v vectors together and a vector // add reverseP and v vectors together and a vector
const prVonNx = reverseP.x + v.x; const prVonNx = Math.round(reverseP.x*100 + v.x*100)/100;
const prVonNy = reverseP.y + v.y; const prVonNy = Math.round(reverseP.y*100 + v.y*100)/100;
console.log("intended velocity", v);
console.log("counter velocity", prVonNx, prVonNy);
// console.log("velocity vector", velocityVect); // console.log("velocity vector", velocityVect);
// console.log("normal vector", edgeNrmlVect); // console.log("normal vector", edgeNrmlVect);
// console.log("V dot N", vDotn); // console.log("V dot N", vDotn);
@@ -780,10 +869,7 @@ const Move = (() => {
// drawLine(px, py, px + edgeNrmlVect.x, py + edgeNrmlVect.y, "black"); // drawLine(px, py, px + edgeNrmlVect.x, py + edgeNrmlVect.y, "black");
// drawLine(contact.position.x, contact.position.y, contact.position.x + prVonNx, contact.position.y + prVonNy, "teal"); // drawLine(contact.position.x, contact.position.y, contact.position.x + prVonNx, contact.position.y + prVonNy, "teal");
const side = isClockwise([contact.edge.xa, contact.edge.ya], [contact.edge.xb, contact.edge.yb], [px, py]);
// contact.velocity = { x: prVonNx, y: prVonNy }; // contact.velocity = { x: prVonNx, y: prVonNy };
// Velocity[entity_id] = { x: prVonNx, y: prVonNy };
Velocity[entity_id] = { x: prVonNx, y: prVonNy }; Velocity[entity_id] = { x: prVonNx, y: prVonNy };
console.log("v", v); console.log("v", v);
console.log("velocity", Velocity[entity_id]); console.log("velocity", Velocity[entity_id]);
@@ -791,7 +877,7 @@ const Move = (() => {
console.log("current position", px, py); console.log("current position", px, py);
drawCircle(px, py, "pink"); drawCircle(px, py, "pink");
console.log("contact.position", contact.position); console.log("contact.position", contact.position, "dett");
drawCircle(contact.position.x, contact.position.y, "limegreen"); drawCircle(contact.position.x, contact.position.y, "limegreen");
console.log("intended next position", p); console.log("intended next position", p);
@@ -802,14 +888,86 @@ const Move = (() => {
// y: vy > 0 && vy + ay <= 0 ? 0 : vy + ay // y: vy > 0 && vy + ay <= 0 ? 0 : vy + ay
// }; // };
const newP = { let newP = {
// x: contact.position.x + elapsed * prVonNx * metersPerMillisecond, // x: contact.position.x + elapsed * prVonNx * metersPerMillisecond,
// y: contact.position.y + elapsed * prVonNy * metersPerMillisecond // y: contact.position.y + elapsed * prVonNy * metersPerMillisecond
x: Math.round((contact.position.x + elapsed * prVonNx * metersPerMillisecond) * 100) / 100, x: Math.round((contact.position.x + elapsed * prVonNx * metersPerMillisecond) * 100) / 100,
y: Math.round((contact.position.y + elapsed * prVonNy * metersPerMillisecond) * 100) / 100, y: Math.round((contact.position.y + elapsed * prVonNy * metersPerMillisecond) * 100) / 100,
}; };
console.log("calculated next position", newP, "dett");
let isC = isClockwise([contact.edge.xa, contact.edge.ya], [contact.edge.xb, contact.edge.yb], [newP.x, newP.y]);
console.log("is calculated next position clockwise with current contact", isC, "aaa");
let isA = isAcute([contact.edge.xa, contact.edge.ya], [contact.edge.xb, contact.edge.yb], [newP.x, newP.y]);
console.log("is calculated next position acute with current contact", isA, "aaa");
console.log("actual next position", newP); console.log("calculated next", newP, "aaa");
// can I reflect the calculated next position across the edge line?
const m = rise / run;
const c = (contact.edge.xb*contact.edge.ya-contact.edge.xa*contact.edge.yb) / (contact.edge.xb-contact.edge.xa);
const d = (newP.x + (newP.y - c)*m)/(1+m**2);
const refP = {
x: 2*d - newP.x,
y: 2*d*m - newP.y + 2*c
};
console.log("reflection before rounding", refP, "aaa");
refP.x = Math.round(refP.x * 100) / 100;
refP.y = Math.round(refP.y * 100) / 100;
// shouldnt change isClockwise if isAcute isn't also changing
// if we go from clockwise to not clockwise without changing acuteness,
// that means we went through a wall
if (!isC && isA) newP = refP;
console.log("reflection", refP, "aaa");
isC = isClockwise([contact.edge.xa, contact.edge.ya], [contact.edge.xb, contact.edge.yb], [refP.x, refP.y]);
console.log("is reflected position clockwise with current contact", isC, "aaa");
isA = isAcute([contact.edge.xa, contact.edge.ya], [contact.edge.xb, contact.edge.yb], [refP.x, refP.y]);
console.log("is reflected position acute with current contact", isA, "aaa");
const inWall = contact.wall.node.isPointInFill(newP);
console.log("is our calculated next position inside current edge's wall?", inWall, "dett");
// if an edge passes through a point, is that point in the wall's fill? yes
// so touching a wall is technically being in its fill
const lnIntxnFromTwoPts = (ln1, ln2) => {
const { xa: x1, ya: y1, xb: x2, yb: y2 } = ln1;
const { xa: x3, ya: y3, xb: x4, yb: y4 } = ln2;
const denom = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
return {
x: ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4)) / denom,
y: ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4)) / denom
};
}
// const rise = contact.edge.yb - contact.edge.ya;
// const run = constact.edge.xb - contact.edge.xa;
// const p_new = lnIntxnFromTwoPts(contact.edge, { xa: newP.x, ya: newP.y, xb: newP.x + rise, yb: newP.y - run });
// newP = lnIntxnFromTwoPts(contact.edge, { xa: newP.x, ya: newP.y, xb: newP.x + rise, yb: newP.y - run });
// console.log("intersection point with edge", newP, "dett");
// const isCw = isClockwise([contact.edge.xa, contact.edge.ya], [contact.edge.xb, contact.edge.yb], [newP.x, newP.y]);
// console.log("is intersection point clockwise?", isCw, "dett");
// const lnD = distance(contact.position.x, contact.position.y, newP.x, newP.y);
const lnD = distance(contact.edge.xa, contact.edge.ya, newP.x, newP.y);
const ln = document.createElementNS(namespaceURIsvg, 'line');
ln.setAttribute('x1', contact.edge.xa);
ln.setAttribute('y1', contact.edge.ya);
ln.setAttribute('x2', newP.x);
ln.setAttribute('y2', newP.y);
// newP = ln.getPointAtLength(lnD);
// container.appendChild(el);
// console.log("POINT ON EDGE LINE LENGTH", lnD);
// console.log("calculated next position along edge line", newP);
drawCircle(newP.x, newP.y, "black"); drawCircle(newP.x, newP.y, "black");
Position[entity_id] = newP; Position[entity_id] = newP;
@@ -913,7 +1071,8 @@ function init() {
// s. velocity = { x: -5*mult, y: 7*mult }; // s. velocity = { x: -5*mult, y: 7*mult };
// drawCircle(0, 0); // drawCircle(0, 0);
s.acceleration = { x: -1, y: 2 }; // s.acceleration = { x: -1, y: 2 };
s.acceleration = { x: -2, y: 2 };
// s.acceleration = { x: 0, y: 0 }; // s.acceleration = { x: 0, y: 0 };
Ships.forEach(({ entity_id }) => { Ships.forEach(({ entity_id }) => {
@@ -1218,7 +1377,7 @@ function drawLine(xa, ya, xb, yb, color = "black") {
return el; return el;
} }
function drawCircle(cx, cy, color = "black", r = 0.2) { function drawCircle(cx, cy, color = "black", r = 1) {
const el = document.createElementNS(namespaceURIsvg, 'circle'); const el = document.createElementNS(namespaceURIsvg, 'circle');
el.setAttribute('cx', cx); el.setAttribute('cx', cx);
el.setAttribute('cy', cy); el.setAttribute('cy', cy);

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 68 KiB