disc-elipse-2.js

total 0
used 0
limit 0
/* title: Egg 2 categories: curve src_dir: ../point_src/ files: head pointlist point ../point_src/math.js ../point_src/point-content.js mouse stage ../point_src/stage-clock.js ../point_src/extras.js ../point_src/random.js dragging ../point_src/setunset.js ../point_src/stroke.js ../point_src/curve-extras.js xybind --- */ class MainStage extends Stage { canvas = 'playspace' live = true mounted() { this.angleX = 0 this.angleY = 0 this.angleZ = 0 this.radius = 100 this.point = this.center.copy().update({radius: this.radius}) this.dragging.add(this.point) } draw(ctx) { this.draw2(ctx) } draw1(ctx) { this.clear(ctx) // this.angleX += 0.1 // this.angleY -= 0.1 // this.angleZ = 0 // this.angleZ += 0.01 this.drawDisc(ctx) this.point.pen.indicator(ctx, {color: '#AA6666'}) } drawDisc(ctx) { const center = this.point const baseRadius = this.point.radius // Simulate 3D disc squash using sin of rotation const rx = baseRadius const ry = baseRadius * Math.cos(this.angleX) * Math.cos(this.angleY) // Draw the ellipse as a disc projection ctx.beginPath() ctx.ellipse(center.x, center.y, rx, Math.abs(ry), this.angleZ, 0, 2 * Math.PI) ctx.strokeStyle = '#AA6666' ctx.lineWidth = 2 ctx.stroke() ctx.fillStyle = 'rgba(200, 100, 100, 0.3)' ctx.fill() } draw2(ctx) { this.clear(ctx) this.angleX += 0.1 // this.angleY += 0.1 // this.angleZ += 0.01 const r = this.radius || 100 const center = this.center // // Define local axes of a unit circle (X and Y axes in 3D) // let xAxis = rotate3D({x: r, y: 0, z: 0}, this.angleX, this.angleY, this.angleZ) // let yAxis = rotate3D({x: 0, y: r, z: 0}, this.angleX, this.angleY, this.angleZ) // // Radii are lengths of the projected axes // const rx = Math.sqrt(xAxis.x**2 + xAxis.y**2) // const ry = Math.sqrt(yAxis.x**2 + yAxis.y**2) // // Rotation angle of the x-axis (for canvas ellipse rotation) // const rotation = Math.atan2(xAxis.y, xAxis.x) let xDir = rotate3D({x: 1, y: 0, z: 0}, this.angleX, this.angleY, this.angleZ) let yDir = rotate3D({x: 0, y: 1, z: 0}, this.angleX, this.angleY, this.angleZ) const rx = r * Math.sqrt(xDir.x**2 + xDir.y**2) const ry = r * Math.sqrt(yDir.x**2 + yDir.y**2) const rotation = Math.atan2(xDir.y, xDir.x) ctx.beginPath() ctx.ellipse(center.x, center.y, rx, ry, rotation, 0, 2 * Math.PI) ctx.strokeStyle = '#AA6666' ctx.lineWidth = 2 ctx.stroke() ctx.fillStyle = 'rgba(200, 100, 100, 0.3)' ctx.fill() this.point.pen.indicator(ctx, {color: '#AA6666'}) } draw3(ctx) { this.clear(ctx) this.angleX += 0.01 // this.angleY += 0.01 this.angleZ += 0.01 const r = this.radius const center = this.point // Rotate 4 points around disc let px = rotate3D({x: r, y: 0, z: 0}, this.angleX, this.angleY, this.angleZ) let nx = rotate3D({x: -r, y: 0, z: 0}, this.angleX, this.angleY, this.angleZ) let py = rotate3D({x: 0, y: r, z: 0}, this.angleX, this.angleY, this.angleZ) let ny = rotate3D({x: 0, y: -r, z: 0}, this.angleX, this.angleY, this.angleZ) // Project all to 2D const proj = (pt) => [center.x + pt.x, center.y + pt.y] let [x1, y1] = proj(px) let [x2, y2] = proj(nx) let [y1x, y1y] = proj(py) let [y2x, y2y] = proj(ny) const rx = 0.5 * Math.hypot(x1 - x2, y1 - y2) const ry = 0.5 * Math.hypot(y1x - y2x, y1y - y2y) const rotation = Math.atan2(y1 - y2, x1 - x2) ctx.beginPath() ctx.ellipse(center.x, center.y, rx, ry, rotation, 0, 2 * Math.PI) ctx.strokeStyle = '#AA6666' ctx.lineWidth = 2 ctx.stroke() ctx.fillStyle = 'rgba(200, 100, 100, 0.3)' ctx.fill() this.point.pen.indicator(ctx, {color: '#AA6666'}) } draw4(ctx) { this.clear(ctx) // this.angleX += 0.01 this.angleY += 0.01 this.angleZ += 0.01 const r = this.radius const center = this.center const steps = 100 const points = [] for (let i = 0; i < steps; i++) { const theta = (i / steps) * 2 * Math.PI const point3D = { x: r * Math.cos(theta), y: r * Math.sin(theta), z: 0 } const rotated = rotate3D(point3D, this.angleX, this.angleY, this.angleZ) points.push([center.x + rotated.x, center.y + rotated.y]) } // Now compute bounding box (approximate ellipse) let minX = Infinity, maxX = -Infinity let minY = Infinity, maxY = -Infinity for (const [x, y] of points) { if (x < minX) minX = x if (x > maxX) maxX = x if (y < minY) minY = y if (y > maxY) maxY = y } const ellipseWidth = maxX - minX const ellipseHeight = maxY - minY const rx = ellipseWidth / 2 const ry = ellipseHeight / 2 const cx = (minX + maxX) / 2 const cy = (minY + maxY) / 2 // Optional: Find orientation const [a1, a2] = points[0] const [b1, b2] = points[Math.floor(steps / 4)] const rotation = Math.atan2(b2 - a2, b1 - a1) ctx.beginPath() ctx.ellipse(cx, cy, rx, ry, rotation, 0, 2 * Math.PI) ctx.strokeStyle = '#AA6666' ctx.lineWidth = 2 ctx.stroke() ctx.fillStyle = 'rgba(200, 100, 100, 0.3)' ctx.fill() this.point.pen.indicator(ctx, {color: '#AA6666'}) } draw5(ctx) { this.clear(ctx) this.angleX += 0.01 this.angleY += 0.01 // this.angleZ += 0.01 const r = this.radius const center = this.center const steps = 100 ctx.beginPath() for (let i = 0; i <= steps; i++) { const theta = (i / steps) * 2 * Math.PI const point3D = { x: r * Math.cos(theta), y: r * Math.sin(theta), z: 0 } const rotated = rotate3D(point3D, this.angleX, this.angleY, this.angleZ) const x2D = center.x + rotated.x const y2D = center.y + rotated.y if (i === 0) ctx.moveTo(x2D, y2D) else ctx.lineTo(x2D, y2D) } ctx.closePath() ctx.strokeStyle = '#AA6666' ctx.lineWidth = 2 ctx.stroke() ctx.fillStyle = 'rgba(200, 100, 100, 0.3)' ctx.fill() this.point.pen.indicator(ctx, {color: '#AA6666'}) } draw6(ctx) { this.clear(ctx) this.angleX += 0.01 this.angleY += 0.01 this.angleZ += 0.01 const r = this.radius const center = this.center // Rotate the unit vectors let xDir = rotate3D({x: 1, y: 0, z: 0}, this.angleX, this.angleY, this.angleZ) let yDir = rotate3D({x: 0, y: 1, z: 0}, this.angleX, this.angleY, this.angleZ) // Z compensation to counter 3D "shrink" const safeZ = (z) => Math.min(0.999, Math.max(-0.999, z)) const zCorrectedLength = (dir) => r / Math.sqrt(1 + safeZ(dir.z)**2) const rx = zCorrectedLength(xDir) const ry = zCorrectedLength(yDir) const rotation = Math.atan2(xDir.y, xDir.x) ctx.beginPath() ctx.ellipse(center.x, center.y, rx, ry, rotation, 0, 2 * Math.PI) ctx.strokeStyle = '#AA6666' ctx.lineWidth = 2 ctx.stroke() ctx.fillStyle = 'rgba(200, 100, 100, 0.3)' ctx.fill() this.point.pen.indicator(ctx, {color: '#AA6666'}) } } function rotate3D(point, angleX, angleY, angleZ) { let {x, y, z} = point // X Rotation let cosX = Math.cos(angleX), sinX = Math.sin(angleX) let y1 = y * cosX - z * sinX let z1 = y * sinX + z * cosX // Y Rotation let cosY = Math.cos(angleY), sinY = Math.sin(angleY) let x2 = x * cosY + z1 * sinY let z2 = -x * sinY + z1 * cosY // Z Rotation let cosZ = Math.cos(angleZ), sinZ = Math.sin(angleZ) let x3 = x2 * cosZ - y1 * sinZ let y3 = x2 * sinZ + y1 * cosZ return {x: x3, y: y3, z: z2} } ;stage = MainStage.go();
Run
Meta Data
title Egg 2
imports ()
files ('head', 'pointlist', 'point', '../point_src/math.js', '../point_src/point-content.js', 'mouse', 'stage', '../point_src/stage-clock.js', '../point_src/extras.js', '../point_src/random.js', 'dragging', '../point_src/setunset.js', '../point_src/stroke.js', '../point_src/curve-extras.js', 'xybind')
unused_keys ()
unknown_keys ('categories', 'src_dir')
categories ['curve']
src_dir ['../point_src/']
filepath_exists True
path disc-elipse-2.js
filepath disc-elipse-2.js
clean_files ('../point_src/core/head.js', '../point_src/pointlistdraw.js', '../point_src/pointlistgradient.js', '../point_src/pointlistshape.js', '../point_src/pointlistgenerator.js', '../point_src/unpack.js', '../point_src/pointlist.js', '../point_src/pointlistpen.js', '../point_src/pointpen.js', '../point_src/compass.js', '../point_src/center.js', '../point_src/point-content.js', '../point_src/pointdraw.js', '../point_src/relative-xy.js', '../point_src/pointcast.js', '../point_src/point.js', '../point_src/math.js', '../point_src/events.js', '../point_src/automouse.js', '../point_src/stage-resize.js', '../point_src/functions/resolve.js', '../point_src/stage.js', '../point_src/stage-clock.js', '../point_src/extras.js', '../point_src/random.js', '../point_src/functions/clamp.js', '../point_src/distances.js', '../point_src/protractor.js', '../point_src/text/beta.js', '../point_src/dragging.js', '../point_src/setunset.js', '../point_src/stroke.js', '../point_src/curve-extras.js', '../point_src/coupling.js', '../point_src/xybind.js')
markdown {'html': '', 'content': 'title: Egg 2\ncategories: curve\nsrc_dir: ../point_src/\nfiles:\n head\n pointlist\n point\n ../point_src/math.js\n ../point_src/point-content.js\n mouse\n stage\n ../point_src/stage-clock.js\n ../point_src/extras.js\n ../point_src/random.js\n dragging\n ../point_src/setunset.js\n ../point_src/stroke.js\n ../point_src/curve-extras.js\n xybind\n---'}