{"spec_id":"scatter-complex-plane","library":"echarts","language":"javascript","code":"// anyplot.ai\n// scatter-complex-plane: Complex Plane Visualization (Argand Diagram)\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 94/100 | Created: 2026-08-26\n//# anyplot-orientation: square\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// 4th roots of unity: solutions of z^4 = 1, spaced 90° apart on |z| = 1\nconst rootsOfUnity = [\n  { re: 1, im: 0 },\n  { re: 0, im: 1 },\n  { re: -1, im: 0 },\n  { re: 0, im: -1 },\n];\n\n// A few arbitrary complex numbers off the unit circle\nconst arbitraryPoints = [\n  { re: 1.8, im: 1.2 },\n  { re: -1.5, im: 0.9 },\n  { re: 0.7, im: -1.9 },\n  { re: -0.9, im: -2.2 },\n  { re: 2.1, im: -0.4 },\n];\n\nfunction fmtNum(n) {\n  return Number.isInteger(n) ? String(n) : n.toFixed(1);\n}\n\nfunction formatComplex(re, im) {\n  const sign = im < 0 ? \"−\" : \"+\";\n  return `${fmtNum(re)}${sign}${fmtNum(Math.abs(im))}i`;\n}\n\nfunction toVectorData(points) {\n  return points.map((p) => ({\n    coords: [\n      [0, 0],\n      [p.re, p.im],\n    ],\n  }));\n}\n\nfunction toPointData(points) {\n  return points.map((p) => {\n    // Points sitting exactly on the imaginary axis (re === 0) would have their\n    // label centered at x=0, so the vertical axis line cuts through the text;\n    // nudge those labels sideways and left-align them clear of the line.\n    const onImaginaryAxis = p.re === 0;\n    return {\n      value: [p.re, p.im],\n      label: {\n        show: true,\n        position: p.im >= 0 ? \"top\" : \"bottom\",\n        align: onImaginaryAxis ? \"left\" : \"center\",\n        offset: onImaginaryAxis ? [10, 0] : [0, 0],\n        formatter: () => formatComplex(p.re, p.im),\n        color: t.ink,\n        fontSize: 15,\n        fontWeight: 500,\n      },\n    };\n  });\n}\n\n// Unit circle reference (dashed), 144 segments\nconst circlePoints = Array.from({ length: 145 }, (_, i) => {\n  const theta = (i / 144) * 2 * Math.PI;\n  return [Math.cos(theta), Math.sin(theta)];\n});\n\n// --- Series -------------------------------------------------------------\nconst unitCircle = {\n  type: \"line\",\n  data: circlePoints,\n  showSymbol: false,\n  smooth: true,\n  lineStyle: { type: \"dashed\", width: 1.5, color: t.inkSoft, opacity: 0.55 },\n  silent: true,\n  z: 1,\n};\n\nconst unitCircleLabel = {\n  type: \"scatter\",\n  data: [[Math.cos(Math.PI / 4) * 1.1, Math.sin(Math.PI / 4) * 1.1]],\n  symbolSize: 0,\n  silent: true,\n  label: {\n    show: true,\n    formatter: \"|z| = 1\",\n    color: t.inkSoft,\n    fontSize: 14,\n    position: \"top\",\n  },\n  z: 1,\n};\n\nconst rootsVectors = {\n  name: \"Roots of unity\",\n  type: \"lines\",\n  coordinateSystem: \"cartesian2d\",\n  data: toVectorData(rootsOfUnity),\n  lineStyle: { color: t.palette[0], width: 2.5, opacity: 0.85 },\n  symbol: [\"none\", \"arrow\"],\n  symbolSize: [0, 12],\n  silent: true,\n  z: 3,\n};\n\nconst arbitraryVectors = {\n  name: \"Arbitrary points\",\n  type: \"lines\",\n  coordinateSystem: \"cartesian2d\",\n  data: toVectorData(arbitraryPoints),\n  lineStyle: { color: t.palette[1], width: 2.5, opacity: 0.85 },\n  symbol: [\"none\", \"arrow\"],\n  symbolSize: [0, 12],\n  silent: true,\n  z: 3,\n};\n\nconst rootsMarkers = {\n  name: \"Roots of unity\",\n  type: \"scatter\",\n  data: toPointData(rootsOfUnity),\n  symbol: \"circle\",\n  symbolSize: 20,\n  itemStyle: { color: t.palette[0], borderColor: t.pageBg, borderWidth: 2 },\n  z: 5,\n};\n\nconst arbitraryMarkers = {\n  name: \"Arbitrary points\",\n  type: \"scatter\",\n  data: toPointData(arbitraryPoints),\n  symbol: \"diamond\",\n  symbolSize: 22,\n  itemStyle: { color: t.palette[1], borderColor: t.pageBg, borderWidth: 2 },\n  z: 5,\n};\n\n// --- Chart --------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"scatter-complex-plane · javascript · echarts · anyplot.ai\",\n    subtext: \"4th Roots of Unity and Arbitrary Points in the Argand Plane\",\n    left: \"center\",\n    top: 24,\n    itemGap: 10,\n    textStyle: { color: t.ink, fontSize: 22, fontWeight: \"500\" },\n    subtextStyle: { color: t.inkSoft, fontSize: 16 },\n  },\n  legend: {\n    top: 96,\n    left: \"center\",\n    orient: \"horizontal\",\n    textStyle: { color: t.ink, fontSize: 15 },\n    itemGap: 28,\n    itemWidth: 26,\n    itemHeight: 14,\n    icon: \"circle\",\n  },\n  grid: { left: 130, right: 90, top: 160, bottom: 60 },\n  xAxis: {\n    type: \"value\",\n    min: -2.5,\n    max: 2.5,\n    interval: 1,\n    name: \"Real (Re)\",\n    nameLocation: \"end\",\n    nameGap: 16,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 13 },\n    axisLine: { onZero: true, lineStyle: { color: t.inkSoft, width: 1.5 } },\n    axisTick: { show: false },\n    splitLine: { show: true, lineStyle: { color: t.grid } },\n  },\n  yAxis: {\n    type: \"value\",\n    min: -2.5,\n    max: 2.5,\n    interval: 1,\n    name: \"Imaginary (Im)\",\n    nameLocation: \"end\",\n    nameGap: 16,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 13 },\n    axisLine: { onZero: true, lineStyle: { color: t.inkSoft, width: 1.5 } },\n    axisTick: { show: false },\n    splitLine: { show: true, lineStyle: { color: t.grid } },\n  },\n  tooltip: {\n    trigger: \"item\",\n    backgroundColor: t.elevatedBg,\n    borderColor: t.grid,\n    textStyle: { color: t.ink, fontSize: 14 },\n    formatter: (params) => {\n      if (params.seriesType !== \"scatter\") return \"\";\n      const [re, im] = params.value;\n      const r = Math.hypot(re, im);\n      const thetaDeg = (Math.atan2(im, re) * 180) / Math.PI;\n      return `<b>${params.seriesName}</b><br/>${formatComplex(re, im)}<br/>r = ${r.toFixed(2)}, θ = ${thetaDeg.toFixed(1)}°`;\n    },\n  },\n  series: [\n    unitCircle,\n    unitCircleLabel,\n    rootsVectors,\n    arbitraryVectors,\n    rootsMarkers,\n    arbitraryMarkers,\n  ],\n});\n"}