{"spec_id":"scatter-complex-plane","library":"muix","language":"javascript","code":"// anyplot.ai\n// scatter-complex-plane: Complex Plane Visualization (Argand Diagram)\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 88/100 | Created: 2026-08-26\n//# anyplot-orientation: square\n// anyplot.ai\n// scatter-complex-plane: Complex Plane Visualization (Argand Diagram)\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-08-26\nimport { ChartContainer } from \"@mui/x-charts/ChartContainer\";\nimport { useXScale, useYScale } from \"@mui/x-charts/hooks\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// The cube roots of unity — the three solutions to z^3 = 1 — sit evenly\n// spaced on the unit circle, alongside a few arbitrary complex numbers for\n// contrast (Applications: \"roots of polynomials\", \"nth roots of unity\").\nconst ROOTS_OF_UNITY = [\n  { name: \"z1\", re: 1, im: 0 },\n  { name: \"z2\", re: -0.5, im: Math.sqrt(3) / 2 },\n  { name: \"z3\", re: -0.5, im: -Math.sqrt(3) / 2 },\n];\n\nconst ARBITRARY_POINTS = [\n  { name: \"w1\", re: 1.7, im: 1.0 },\n  { name: \"w2\", re: -1.4, im: 1.8 },\n  { name: \"w3\", re: 0.9, im: -1.9 },\n];\n\nconst CATEGORIES = [\n  { key: \"roots\", label: \"Cube roots of unity\", color: t.palette[0], points: ROOTS_OF_UNITY },\n  { key: \"arbitrary\", label: \"Arbitrary points\", color: t.palette[1], points: ARBITRARY_POINTS },\n];\n\n// Rectangular (\"a+bi\") and polar (\"r ∠ θ°\") annotation text for a point.\nfunction rectForm(re, im) {\n  const sign = im < 0 ? \"-\" : \"+\";\n  return `${re.toFixed(2)}${sign}${Math.abs(im).toFixed(2)}i`;\n}\nfunction polarForm(re, im) {\n  const r = Math.hypot(re, im);\n  const theta = (Math.atan2(im, re) * 180) / Math.PI;\n  return `${r.toFixed(2)} ∠ ${theta.toFixed(0)}°`;\n}\n\n// Hand-tuned per-point label offsets (px) so the two annotation lines clear\n// the vector arrows, the origin axes, and each other. `dy` places the first\n// (rectangular-form) line; the second (polar-form) line always sits 20px\n// below it.\nconst LABEL_LAYOUT = {\n  z1: { dx: 18, dy: -40, anchor: \"start\" }, // sits on the real axis — push well above it\n  z2: { dx: -20, dy: -18, anchor: \"end\" },\n  z3: { dx: -20, dy: 32, anchor: \"end\" },\n  w1: { dx: 20, dy: -18, anchor: \"start\" },\n  w2: { dx: -20, dy: -18, anchor: \"end\" },\n  w3: { dx: 20, dy: 32, anchor: \"start\" },\n};\n\nconst DOMAIN = 2.7;\nconst TICKS = [-2, -1, 1, 2];\n\n// --- Argand diagram — axes, unit circle, vectors, markers, and annotations,\n// all composed on the ChartContainer's cartesian scales (community\n// @mui/x-charts surface only, no Pro/Premium). -------------------------------\nfunction ArgandDiagram() {\n  const xScale = useXScale();\n  const yScale = useYScale();\n  const zeroX = xScale(0);\n  const zeroY = yScale(0);\n  const unitRadius = Math.abs(xScale(1) - xScale(0));\n  const axisStart = xScale(-DOMAIN);\n  const axisEnd = xScale(DOMAIN);\n  const axisTop = yScale(DOMAIN);\n  const axisBottom = yScale(-DOMAIN);\n\n  return (\n    <g>\n      <defs>\n        {CATEGORIES.map((cat) => (\n          <marker key={cat.key} id={`arrowhead-${cat.key}`} markerWidth={10} markerHeight={10} refX={8} refY={5} orient=\"auto\">\n            <path d=\"M0,0 L10,5 L0,10 Z\" fill={cat.color} />\n          </marker>\n        ))}\n      </defs>\n\n      {/* Subtle unit-spaced reference grid */}\n      {TICKS.map((v) => (\n        <line key={`grid-v-${v}`} x1={xScale(v)} y1={axisTop} x2={xScale(v)} y2={axisBottom} stroke={t.grid} strokeWidth={1} />\n      ))}\n      {TICKS.map((v) => (\n        <line key={`grid-h-${v}`} x1={axisStart} y1={yScale(v)} x2={axisEnd} y2={yScale(v)} stroke={t.grid} strokeWidth={1} />\n      ))}\n\n      {/* Unit circle — dashed geometric reference for magnitude 1 */}\n      <circle cx={zeroX} cy={zeroY} r={unitRadius} fill=\"none\" stroke={t.inkSoft} strokeWidth={2} strokeDasharray=\"9 9\" opacity={0.8} />\n\n      {/* Real + imaginary axes drawn through the origin */}\n      <line x1={axisStart} y1={zeroY} x2={axisEnd} y2={zeroY} stroke={t.ink} strokeWidth={2.5} />\n      <line x1={zeroX} y1={axisTop} x2={zeroX} y2={axisBottom} stroke={t.ink} strokeWidth={2.5} />\n      <text x={axisEnd - 6} y={zeroY - 16} fontSize={20} fontWeight={600} fill={t.ink} textAnchor=\"end\">\n        Re\n      </text>\n      <text x={zeroX + 16} y={axisTop + 26} fontSize={20} fontWeight={600} fill={t.ink} textAnchor=\"start\">\n        Im\n      </text>\n\n      {/* Tick marks + labels along both axes */}\n      {TICKS.map((v) => (\n        <g key={`tick-re-${v}`}>\n          <line x1={xScale(v)} y1={zeroY - 9} x2={xScale(v)} y2={zeroY + 9} stroke={t.ink} strokeWidth={1.5} />\n          <text x={xScale(v)} y={zeroY + 34} fontSize={17} fill={t.inkSoft} textAnchor=\"middle\">\n            {v}\n          </text>\n        </g>\n      ))}\n      {TICKS.map((v) => (\n        <g key={`tick-im-${v}`}>\n          <line x1={zeroX - 9} y1={yScale(v)} x2={zeroX + 9} y2={yScale(v)} stroke={t.ink} strokeWidth={1.5} />\n          <text x={zeroX - 16} y={yScale(v) + 6} fontSize={17} fill={t.inkSoft} textAnchor=\"end\">\n            {`${v}i`}\n          </text>\n        </g>\n      ))}\n      <text x={zeroX - 14} y={zeroY + 30} fontSize={17} fill={t.inkSoft} textAnchor=\"end\">\n        0\n      </text>\n\n      {/* Vectors from the origin, point markers, and rectangular/polar labels */}\n      {CATEGORIES.map((cat) =>\n        cat.points.map((p) => {\n          const px = xScale(p.re);\n          const py = yScale(p.im);\n          const layout = LABEL_LAYOUT[p.name];\n          return (\n            <g key={p.name}>\n              <line x1={zeroX} y1={zeroY} x2={px} y2={py} stroke={cat.color} strokeWidth={2.5} markerEnd={`url(#arrowhead-${cat.key})`} />\n              <circle cx={px} cy={py} r={12} fill={cat.color} stroke={t.pageBg} strokeWidth={3} />\n              <text x={px + layout.dx} y={py + layout.dy} fontSize={16} fontWeight={600} fill={t.ink} textAnchor={layout.anchor}>\n                {`${p.name} = ${rectForm(p.re, p.im)}`}\n              </text>\n              <text x={px + layout.dx} y={py + layout.dy + 20} fontSize={15} fill={t.inkSoft} textAnchor={layout.anchor}>\n                {polarForm(p.re, p.im)}\n              </text>\n            </g>\n          );\n        })\n      )}\n\n      {/* Category legend */}\n      {CATEGORIES.map((cat, i) => {\n        const legendX = axisStart + 24;\n        const legendY = axisTop + 28 + i * 32;\n        return (\n          <g key={`legend-${cat.key}`}>\n            <circle cx={legendX} cy={legendY} r={9} fill={cat.color} stroke={t.pageBg} strokeWidth={2} />\n            <text x={legendX + 18} y={legendY + 5} fontSize={16} fill={t.ink} textAnchor=\"start\">\n              {cat.label}\n            </text>\n          </g>\n        );\n      })}\n    </g>\n  );\n}\n\n// --- Chart (default-exported component — the harness mounts it) -------------\nexport default function Chart() {\n  const size = window.ANYPLOT_SIZE;\n  const titleHeight = 70;\n  const chartSize = Math.min(size.width, size.height - titleHeight);\n\n  return (\n    <Box sx={{ width: size.width, height: size.height, display: \"flex\", flexDirection: \"column\", alignItems: \"center\", justifyContent: \"center\" }}>\n      <Box sx={{ height: titleHeight, display: \"flex\", alignItems: \"center\" }}>\n        <Typography sx={{ fontSize: 22, fontWeight: 600, color: t.ink }}>scatter-complex-plane · javascript · muix · anyplot.ai</Typography>\n      </Box>\n      <ChartContainer\n        width={chartSize}\n        height={chartSize}\n        series={[]}\n        xAxis={[{ min: -DOMAIN, max: DOMAIN, scaleType: \"linear\", domainLimit: \"strict\" }]}\n        yAxis={[{ min: -DOMAIN, max: DOMAIN, scaleType: \"linear\", domainLimit: \"strict\" }]}\n        margin={{ top: 20, bottom: 20, left: 20, right: 20 }}\n        skipAnimation\n      >\n        <ArgandDiagram />\n      </ChartContainer>\n    </Box>\n  );\n}\n"}