pseudo3D-coin-classy.js

total 0
used 0
limit 0
/* --- title: Pseudo-3D Z-Depth Sorting categories: pseudo3D files: ../point_src/math.js ../point_src/core/head.js ../point_src/pointpen.js ../point_src/pointdraw.js ../point_src/point-content.js ../point_src/point.js ../point_src/events.js ../point_src/automouse.js ../point_src/stage.js ../point_src/rotate.js stroke ../point_src/distances.js ../point_src/dragging.js --- */ class PointCoin { /* point.coin */ constructor(p) { this.parent = p this.spin = { x: this.rotSize , y: this.rotSize , z: 0//-this.rotSize } // Change these values to rotate around the coin center or an offset pivot. // this.rotationOriginMode = 'center' // 'center' | 'offset' this.rotationOriginMode = 'offset' // 'center' | 'offset' this.rotationOriginOffset = new Point({x: 0, y: 0, z: 0}) this.projectionPoint = this.getRotationOriginPoint() this.projectionLength = 1000 this.perspectiveCenter = this.parent.copy() this.rotSize = 0 this.performSpin = true // Four-curve coin profile in point-local plane space. this.coinCurveConfig = { axisStep: 1 , radius: undefined // Circle approximation constant for each cubic quarter arc. , k: .5522847498307936 } } getRotationOriginPoint(){ if(this.rotationOriginMode == 'offset'){ return this.parent.add( this.rotationOriginOffset.x , this.rotationOriginOffset.y , this.rotationOriginOffset.z ) } return this.parent.copy() } projectPointBasis(source, axisStep=1){ let center = source.copy() let basisX = source.add(axisStep, 0, 0) let basisY = source.add(0, axisStep, 0) // Use rotate helpers directly so this demo does not depend on PointList. let rotated = pseudo3DRotate( [center, basisX, basisY] , this.spin , this.projectionPoint , false ) let projected = pseudo3DRotatePerspective( rotated , this.perspectiveCenter , this.projectionLength ) let p = projected[0] let px = projected[1] let py = projected[2] return { source , p , vx: {x: px.x - p.x, y: px.y - p.y} , vy: {x: py.x - p.x, y: py.y - p.y} } } step(){ this.spin = { x: 0 // this.rotSize , y: this.rotSize , z: 0//-this.rotSize } this.projectionPoint = this.getRotationOriginPoint() let axisStep = this.coinCurveConfig.axisStep ?? 1 this.projectedCoin = this.projectPointBasis(this.parent, axisStep) } draw(ctx){ if(this.performSpin){ this.rotSize += 1 } this.step() // Four-segment cubic casting for the coin profile. let curve = this.getProjectedCoinBezier(this.projectedCoin, this.coinCurveConfig) ctx.beginPath() ctx.moveTo(curve.start.x, curve.start.y) curve.segments.forEach((seg)=>{ ctx.bezierCurveTo( seg.c1.x, seg.c1.y, seg.c2.x, seg.c2.y, seg.end.x, seg.end.y ) }); ctx.closePath() let v = this.spin.y % 360 let col = (v > 90 && v < 270) ? '#000': 'purple' ctx.fillStyle = col ctx.fill() // p.pen.fill(ctx, {color: col}) ctx.strokeStyle = `hsl(277 60% 80%)` ctx.lineWidth = 3 ctx.stroke() new Point(curve.start.x, curve.start.y).pen.indicator(ctx, {color:'orange'}); curve.segments.forEach((seg)=>{ new Point(seg.c1.x, seg.c1.y).pen.indicator(ctx, {color:'yellow'}); new Point(seg.c2.x, seg.c2.y).pen.indicator(ctx, {color:'yellow'}); new Point(seg.end.x, seg.end.y).pen.indicator(ctx, {color:'red'}); }) } getProjectedCoinBezier(item, conf={}){ let radius = conf.radius ?? item.source?.radius ?? 6 let k = conf.k ?? .5522847498307936 let map = (u, v)=> this.mapPlaneLocalToScreen(item, u, v, radius) let a0 = map(1, 0) let a1 = map(0, 1) let a2 = map(-1, 0) let a3 = map(0, -1) // Four cubic curves: one segment per quarter arc. return { start: a0 , segments: [ { c1: map(1, k) , c2: map(k, 1) , end: a1 } , { c1: map(-k, 1) , c2: map(-1, k) , end: a2 } , { c1: map(-1, -k) , c2: map(-k, -1) , end: a3 } , { c1: map(k, -1) , c2: map(1, -k) , end: a0 } ] } } mapPlaneLocalToScreen(item, u, v, radius){ let p = item.p let ex = item.vx let ey = item.vy return { x: p.x + ((ex.x * u) + (ey.x * v)) * radius , y: p.y + ((ex.y * u) + (ey.y * v)) * radius } } } Polypoint.extend.prop('Point', function coin() { return new PointCoin(this) }) class MainStage extends Stage { canvas='playspace' // live=false live = true mounted(){ this.point = new Point({ x: this.center.x , y: this.center.y , z: 0 , radius: 100 }) // this.point.coin = new PointCoin(this.point) } onMousedown(){ this.point.coin.performSpin = !this.point.coin.performSpin } draw(ctx){ this.clear(ctx) let p = this.point; p.coin.draw(ctx) } } ;stage = MainStage.go();
Run
Meta Data
title Pseudo-3D Z-Depth Sorting
imports ()
files ('../point_src/math.js', '../point_src/core/head.js', '../point_src/pointpen.js', '../point_src/pointdraw.js', '../point_src/point-content.js', '../point_src/point.js', '../point_src/events.js', '../point_src/automouse.js', '../point_src/stage.js', '../point_src/rotate.js', 'stroke', '../point_src/distances.js', '../point_src/dragging.js')
unused_keys ()
unknown_keys ('categories',)
categories ['pseudo3D']
filepath_exists True
path pseudo3D-coin-classy.js
filepath pseudo3D-coin-classy.js
clean_files ('../point_src/math.js', '../point_src/core/head.js', '../point_src/pointpen.js', '../point_src/pointdraw.js', '../point_src/compass.js', '../point_src/center.js', '../point_src/point-content.js', '../point_src/relative-xy.js', '../point_src/pointcast.js', '../point_src/point.js', '../point_src/events.js', '../point_src/automouse.js', '../point_src/stage-hooks.js', '../point_src/functions/resolve.js', '../point_src/stage.js', '../point_src/rotate.js', '../point_src/setunset.js', '../point_src/stroke.js', '../point_src/distances.js', '../point_src/protractor.js', '../point_src/text/beta.js', '../point_src/dragging.js')
markdown {'html': '<hr />', 'content': '---\ntitle: Pseudo-3D Z-Depth Sorting\ncategories: pseudo3D\nfiles:\n ../point_src/math.js\n ../point_src/core/head.js\n ../point_src/pointpen.js\n ../point_src/pointdraw.js\n ../point_src/point-content.js\n ../point_src/point.js\n ../point_src/events.js\n ../point_src/automouse.js\n ../point_src/stage.js\n ../point_src/rotate.js\n stroke\n ../point_src/distances.js\n ../point_src/dragging.js\n\n---'}