Public
Edited
Oct 23, 2023
Insert cell
Insert cell
Insert cell
Insert cell
{
var markCircleR, markCircleZ, markDataInv;

// Draw the fixed circle
{
const polygon = mkCirclePolygon(circleR);

markCircleR = Plot.link(polygon, {
x1: "x1",
x2: "x2",
y1: "y1",
y2: "y2"
});
}

// Draw the circle1
{
const { polygon } = circleZ;

markCircleZ = Plot.dot(polygon, {
x: "x",
y: "y",
fill: "idx",
r: 2,
tip: true
});
}

// Draw the data-inversed
{
markDataInv = Plot.dot(dataInv, {
x: "x",
y: "y",
stroke: "idx",
strokeWidth: 1.0,
tip: true
});
}

return Plot.plot({
grid: true,
aspectRatio: 1.0,
x: { nice: true, domain: [-1, 3] },
y: { nice: true, domain: [-1, 1] },
color: { nice: true, legend: true },
marks: [markCircleR, markCircleZ, markDataInv]
});
}
Insert cell
Insert cell
Insert cell
{
var markCircleR, markGridPnts, markInvGridPnts;

// Draw the fixed circle
{
const polygon = mkCirclePolygon(circleR);

markCircleR = Plot.link(polygon, {
x1: "x1",
x2: "x2",
y1: "y1",
y2: "y2"
});
}

// Draw the grid pnts
{
markGridPnts = Plot.dot(gridPnts, {
x: "x",
y: "y",
r: 2,
fill: "color",
interpolate: "none"
// tip: true
});
}

// Draw the inversed grid pnts
{
markInvGridPnts = Plot.dot(invGridPnts, {
x: "x",
y: "y",
r: 1,
strokeWidth: 1.0,
fill: "color"
// tip: true
});
}

return Plot.plot({
grid: true,
aspectRatio: 1.0,
x: { nice: true, domain: [-1, 3] },
y: { nice: true, domain: [-2, 2] },
color: { nice: true, legend: true },
marks: [markCircleR, markGridPnts, markInvGridPnts]
});
}
Insert cell
Insert cell
Plot.raster({
fill: mandelbrot,
x1: -2,
x2: 1,
y1: -1.164,
y2: 1.164
}).plot({
color: { legend: true },
aspectRatio: 1
})
Insert cell
function mandelbrot(x, y) {
for (let n = 0, zr = 0, zi = 0; n < 80; ++n) {
[zr, zi] = [zr * zr - zi * zi + x, k * zr * zi + y];
if (zr * zr + zi * zi > 4) return n;
}
}
Insert cell
invGridPnts = {
const pnts = gridPnts.map((pnt) =>
Object.assign({ color: pnt.color }, invert(pnt, circleR))
);
return pnts;
}
Insert cell
gridPnts = {
const pnts = [],
n1 = 100,
n2 = 100,
scaleX = d3
.scaleLinear()
.domain([0, n1])
.range([1, 1 + 2 * xScale]),
scaleY = d3
.scaleLinear()
.domain([0, n2])
.range([-1 - yOffset, 2 - yOffset]);

var x, y, color;

for (let i = 0; i < n1; ++i) {
for (let j = 0; j < n2; ++j) {
x = scaleX(i);
y = scaleY(j);
color = x + y
pnts.push({ x, y, color });
}
}

return pnts;
}
Insert cell
d3.color
Insert cell
c = d3.color("white")
Insert cell
dataInv = {
var idx;

const { polygon } = circleZ,
dataInv = polygon.map((pnt) => {
idx = pnt.idx;
return Object.assign({ idx }, invert(pnt, circleR));
});

return dataInv;
}
Insert cell
circleZ = {
const { a, r } = relativePosition,
circle = { x: a, y: 0, r: r };

circle.polygon = mkCirclePolygon(circle);

return circle;
}
Insert cell
circleR = {
return { x: 0, y: 0, r: 1 };
}
Insert cell
Insert cell
invert = (pnt, circle) => {
const { x: cx, y: cy, r } = circle,
{ x: px, y: py } = pnt,
[vx, vy] = [px - cx, py - cy],
t = (r * r) / (vx * vx + vy * vy);

return { x: cx + t * vx, y: cy + t * vy };
}
Insert cell
mkCirclePolygon = (circle) => {
const { x, y, r } = circle,
n = 100,
i2rad = d3
.scaleLinear()
.domain([0, n])
.range([0, Math.PI * 2]),
buffer = [];

var rad1, rad2;
for (let i = 0; i < n; ++i) {
rad1 = i2rad(i);
rad2 = i2rad(i + 1);
buffer.push({
x1: x + r * Math.cos(rad1),
x2: x + r * Math.cos(rad2),
y1: y + r * Math.sin(rad1),
y2: y + r * Math.sin(rad2),
idx: i
});
}

buffer.map((d) => Object.assign(d, { x: d.x1, y: d.y1 }));

return buffer;
}
Insert cell
d3 = require("d3")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more