Skip to content

Commit

Permalink
Add complex maps, part I
Browse files Browse the repository at this point in the history
  • Loading branch information
kzmath committed Jan 18, 2024
1 parent 4521c08 commit d875941
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
49 changes: 49 additions & 0 deletions complex-map-2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

<!DOCTYPE html>
<html>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400&family=Vollkorn:ital@0;1&display=swap" rel="stylesheet">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" crossorigin="anonymous">

<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js" integrity="sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8" crossorigin="anonymous"></script>

<script src="lib/C5.js"> </script>
<script src="complex-mapping-polar-poly.js"> </script>
<style>
:root { --serif: 'Vollkorn', serif;
--sanserif: 'Roboto', sans-serif;
}
#main {
font-family: var(--serif);
font-size: calc(1em + 0.5vw);
width: max(600px, 70vw);
margin: 20px auto;
}
#nav {
display: flex;
font-family: var(--sanserif);
}
#nav a {
margin: 5px 20px;
text-decoration: none;
font-variant: small-caps;
color: black;
}
a {
color: blue;
}
h2 {
font-size: 120%;
font-weight: normal;
}
</style>
</head>
<body>
<div id="main">
<div id="nav"> <span><a href="/interactive-math/">home</a></span> </div>
</div>
</body>
</html>
146 changes: 146 additions & 0 deletions complex-mapping-polar-poly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
function complexMappingApp() {
// Calulate dimensions for two panel layout
const width = 900;
const margin = 15;
const axSize = (width - 4 * margin) / 2;

const app = new C5({width: width, height: axSize + 2 * margin});

const ax1 = app.addAxis();
ax1.setCrop(margin, margin, margin + axSize, margin + axSize);
const ax2 = app.addAxis();
ax2.setCrop(app.width / 2 + margin, margin, app.width - margin, margin + axSize)

app.setAxes = function(R1, R2) {
ax1.setLimits(-R1, R1, -R1, R1);
ax2.setLimits(-R2, R2, -R2, R2);
}

app.setAxes(1.5, 1.5);
app.R = 3;
app.gN = 15;
app.N = 201;

// Use colors from the Tableaux palette
const [b1, b2] = [C5.C[0], C5.C[1]];
const [c3, c4] = [C5.CS[2], C5.CS[3]];

// Add control dots
const A = ax1.addControlDot(0, 0.5, "A", { fillStyle: c3 });
const B = ax1.addControlDot(0.5, 0, "B", { fillStyle: c4 });
const C = ax2.addControlDot(1, 0, "λ", {fillStyle: "blue"});

const polarToCart = (R, th) => [R * Math.cos(th), R*Math.sin(th)];

// Functions to be applied
const lbz = (x, y) => complexMult([C.x, C.y], [x, y]);
const z2 = (x, y) => [x ** 2 - y ** 2, 2 * x * y];
const z3 = (x, y) => complexIntPower([x, y], 3);
const zinv = (x, y) => complexDiv([1, 0], [x, y]);
const z2inv = (x, y) => complexDiv([1, 0], complexIntPower([x, y], 2));
const mobius = (x, y) => complexDiv([0.5 - x, - y], [1 - 0.5 * x, - 0.5 * y]);

app.functionName = "z2";

app.funcs = {
"lbz": {func: lbz, latex: "\\lambda z"},
"z2": {func: z2, latex: "z^2"},
"z3": {func: z3, latex: "z^3"},
"zinv": {func: zinv, latex: "\\dfrac{1}{z}"},
"z2inv": {func: z2inv, latex: "\\dfrac{1}{z^2}"},
"mobius": {func: mobius, latex: "\\dfrac{\\frac12 - z}{1 - \\frac{z}{2}}"}
}

app.buttonClicked = function() {
app.setCaption("Mapping: " + app.katexM("f(z) = " + app.funcs[app.functionName].latex));
}
app.setCaption("Mapping: " + app.katexM("f(z) = " + app.funcs[app.functionName].latex));

app.addHTMLButton(app.katexM("\\lambda z"), () => {app.functionName = "lbz"});
app.addHTMLButton(app.katexM("z^2"), () => { app.functionName = "z2" });
app.addHTMLButton(app.katexM("z^3"), () => (app.functionName = "z3"));
app.addHTMLButton(app.katexM("\\dfrac{1}{z}"), () => (app.functionName = "zinv"));
app.addHTMLButton(app.katexM("\\dfrac{1}{z^2}"), () => (app.functionName = "z2inv"));
app.addHTMLButton(app.katexM("\\dfrac{\\frac12 - z}{1 - \\frac{z}{2}}"), () => (app.functionName = "mobius"));
// app.addButton("exp(z)", (app) => (app.fText = "exp"));

// app.addHTMLButton("Toggle Debug", (app) => { app.toggleDebug() });
app.addHTMLButton("Toggle Resolution", (app) => {
if (app.gN == 15) { app.gN = 31; } else { app.gN = 15; }
});

app.draw = function() {
let R = app.R


switch (app.functionName) {
case "lbz": app.f = lbz; break;
case "z2": app.f = z2; break;
case "z3": app.f = z3; break;
case "zinv": app.f = zinv; break;
case "z2inv": app.f = z2inv; break;
case "mobius": app.f = mobius; break;
// case "exp": app.f = exp; break;
}
if (app.f == lbz) { C.visible = true } else { C.visible = false };

ax1.beginClip();

const RMesh = genApply(
(arr) => complexApply(polarToCart, arr),
meshGrid2d([0, 0], [0, 2 * Math.PI], [app.R, 0], app.gN, app.N)
);
const thMesh = genApply(
(arr) => complexApply(polarToCart, arr),
meshGrid2d([0, 0], [app.R, 0], [0, 2 * Math.PI], app.gN, app.N)
);

const A_th = Math.atan2(A.y, A.x);
// let A_R = norm2d([A.x, A.y]);
// let B_th = Math.atan2(B.y, B.x);
const B_R = norm2d([B.x, B.y]);

const RLine = complexApply(
polarToCart, linRange2d([0, A_th], [R, A_th], app.N)
);
const thLine = complexApply(
polarToCart, linRange2d([B_R, 0], [B_R, 2*Math.PI], app.N)
);

ax1.axisGrid({ grid: false, tick: false });

ax1.strokePathArr(RMesh, { strokeStyle: b1 });
ax1.strokePathArr(thMesh, { strokeStyle: b2 });
ax1.strokePath(RLine, { strokeStyle: c3, lineWidth: 3 });
ax1.strokePath(thLine, { strokeStyle: c4, lineWidth: 3 });

ax1.endClip();

ax2.beginClip();

const xMapped = genApply((zarr) => complexApply(app.f, zarr), RMesh);
const yMapped = genApply((zarr) => complexApply(app.f, zarr), thMesh);
const hMapped = complexApply(app.f, RLine);
const vMapped = complexApply(app.f, thLine);

ax2.axisGrid({ grid: false });

if (app.f == lbz) {
ax2.strokePath([0, 0, C.x, C.y], {lineWidth: 3})
ax2.drawText("λ = " + C.x.toPrecision(2) + " + " + C.y.toPrecision(2) + "i", -2, -2, {xOffset: 20, font: "20px sans-serif"});
};


ax2.strokePathArr(xMapped, { strokeStyle: b1 });
ax2.strokePathArr(yMapped, { strokeStyle: b2 });
ax2.strokePath(hMapped, { strokeStyle: c3, lineWidth: 3 });
ax2.strokePath(vMapped, { strokeStyle: c4, lineWidth: 3 });
ax2.drawDot(...app.f(A.x, A.y), 6, { label: "f(A)", fillStyle: c3 });
ax2.drawDot(...app.f(B.x, B.y), 6, { label: "f(B)", fillStyle: c4 });


ax2.endClip();
}
return app;
}
complexMappingApp();
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ <h2> Interactive js apps for math </h2>
<li> <a href="complex-roots.html">Complex roots.</a> </li>
<li> <a href="circle-prop.html">Circle of proportional distance.</a> </li>
<li> <a href="appolonian.html">Appolonian circles.</a> </li>
<li> <a href="complex-map-1.html">Complex mapping in Cartesean coordinates, I</a> </li>
<li> <a href="complex-map-2.html">Complex mapping in polar coordinates, I</a> </li>
</ul>
</div>
</body>
Expand Down

0 comments on commit d875941

Please sign in to comment.