restricted-linear-bar.js

total 0
used 0
limit 0
/* --- title: Restricted Linear Bar (Pure Linkage Network) categories: linkage constraints wheels files: head point ../point_src/point-content.js pointlist mouse stage stroke dragging ../point_src/constrain-distance.js --- */ class WheelNode { constructor(opts = {}) { this.center = opts.center || new Point({ x: 200, y: 180, radius: 36, color: '#8855dd' }) this.rimRadius = opts.rimRadius || this.center.radius this.motor = opts.motor || 0 this.drivePoint = opts.drivePoint this.rim = new Point({ x: 0, y: 0, radius: 6, color: '#55ccaa' }) this.syncRim() } syncRim() { this.rim.update(projectFrom(this.center, this.rimRadius, this.center.rotation)) } step() { if (this.motor !== 0) { this.center.rotation += this.motor } else if (this.drivePoint) { this.center.lookAt(this.drivePoint) } this.syncRim() } draw(ctx) { this.center.pen.circle(ctx, { color: '#666666', width: 2, radius: this.rimRadius }) this.center.pen.line(ctx, this.rim, '#666666', 2) this.center.pen.indicator(ctx) this.rim.pen.indicator(ctx) } } class LinkageUnit { constructor(opts = {}) { this.pointA = opts.pointA || new Point({ x: 200, y: 320, radius: 8, color: '#22aa66' }) this.pointB = opts.pointB || new Point({ x: 320, y: 320, radius: 8, color: '#2277cc' }) this.length = opts.length || this.pointA.distanceTo(this.pointB) this.pivot = opts.pivot this.pivotDistanceA = opts.pivotDistanceA this.trackA = opts.trackA this.trackB = opts.trackB this.activeHandle = undefined if (this.pivot && this.pivotDistanceA == undefined) { this.pivotDistanceA = this.pivot.distanceTo(this.pointA) } } hasPoint(point) { return point === this.pointA || point === this.pointB || point === this.pivot } setActiveHandle(point) { this.activeHandle = point } clearActiveHandle() { this.activeHandle = undefined } setTrackA(point) { this.trackA = point } setTrackB(point) { this.trackB = point } applyTracking() { if (this.trackA) { this.pointA.update(this.trackA) } if (this.trackB) { this.pointB.update(this.trackB) } } solve() { this.applyTracking() if (this.pivot && this.activeHandle !== this.pointA) { constraints.distance(this.pivot, this.pointA, this.pivotDistanceA) } if (this.activeHandle === this.pointA) { constraints.distance(this.pointA, this.pointB, this.length) } else if (this.activeHandle === this.pointB) { constraints.distance(this.pointB, this.pointA, this.length) if (this.pivot) { constraints.distance(this.pivot, this.pointA, this.pivotDistanceA) } } else { constraints.distance(this.pointA, this.pointB, this.length) } } draw(ctx, color = '#f2a21b') { this.pointA.pen.line(ctx, this.pointB, color, 4) this.pointA.pen.indicator(ctx) this.pointB.pen.indicator(ctx) if (this.pivot) { this.pivot.pen.indicator(ctx, '#ee7722') } } } class MainStage extends Stage { canvas = 'playspace' mounted() { this.setupNetwork() this.dragging.add( this.motorWheel.center, this.passiveWheel.center, this.pivotA, this.j1, this.j2, this.j3, this.linkWheelToChain.pointA, this.linkWheelToChain.pointB, this.linkChainAB.pointA, this.linkChainAB.pointB, this.linkChainBC.pointA, this.linkChainBC.pointB, this.linkChainToPassive.pointA, this.linkChainToPassive.pointB, this.linkPassiveToTail.pointA, this.linkPassiveToTail.pointB ) this.dragging.onDragStart = this.onDragStart.bind(this) this.dragging.onDragEnd = this.onDragEnd.bind(this) } setupNetwork() { this.motorWheel = new WheelNode({ center: new Point({ x: 170, y: 170, radius: 34, color: '#aa66dd' }), rimRadius: 34, motor: 1.8 }) this.passiveWheel = new WheelNode({ center: new Point({ x: 610, y: 220, radius: 46, color: '#66aadd', rotation: 180 }), rimRadius: 46 }) this.pivotA = new Point({ x: 260, y: 360, radius: 10, color: '#ee7722' }) this.j1 = new Point({ x: 300, y: 300, radius: 7, color: '#22aa66' }) this.j2 = new Point({ x: 420, y: 320, radius: 7, color: '#22aa66' }) this.j3 = new Point({ x: 520, y: 370, radius: 7, color: '#22aa66' }) // A motor wheel drives the first linkage endpoint directly. this.linkWheelToChain = new LinkageUnit({ pointA: this.motorWheel.rim, pointB: this.j1, length: 170, pivot: this.pivotA }) // Direct linkage-to-linkage bars: A->B->C chain. this.linkChainAB = new LinkageUnit({ pointA: this.j1, pointB: this.j2, length: 150 }) this.linkChainBC = new LinkageUnit({ pointA: this.j2, pointB: this.j3, length: 130 }) // Chain output drives a passive wheel via its rim. this.linkChainToPassive = new LinkageUnit({ pointA: this.j3, pointB: this.passiveWheel.rim, length: 150 }) // Passive wheel output feeds another linkage. this.linkPassiveToTail = new LinkageUnit({ pointA: this.passiveWheel.rim, pointB: new Point({ x: 760, y: 390, radius: 7, color: '#22aa66' }), length: 150 }) this.linkages = [ this.linkWheelToChain, this.linkChainAB, this.linkChainBC, this.linkChainToPassive, this.linkPassiveToTail ] this.passiveWheel.drivePoint = this.j3 } onDragStart(ev, point) { this.linkages.forEach(link => { if (link.hasPoint(point)) { link.setActiveHandle(point) } }) } onDragEnd() { this.linkages.forEach(link => link.clearActiveHandle()) } solveNetwork(iterations = 7) { for (let i = 0; i < iterations; i += 1) { this.motorWheel.step() this.passiveWheel.step() this.linkages.forEach(link => link.solve()) // Keep wheel centers tied to their own radius/rim relation. constraints.distance(this.motorWheel.center, this.motorWheel.rim, this.motorWheel.rimRadius) constraints.distance(this.passiveWheel.center, this.passiveWheel.rim, this.passiveWheel.rimRadius) } } draw(ctx) { this.clear(ctx) this.solveNetwork() this.motorWheel.draw(ctx) this.passiveWheel.draw(ctx) this.linkWheelToChain.draw(ctx, '#e08a1a') this.linkChainAB.draw(ctx, '#e08a1a') this.linkChainBC.draw(ctx, '#e08a1a') this.linkChainToPassive.draw(ctx, '#e08a1a') this.linkPassiveToTail.draw(ctx, '#e08a1a') } } stage = MainStage.go();
Run
Meta Data
title Restricted Linear Bar (Pure Linkage Network)
imports ()
files ('head', 'point', '../point_src/point-content.js', 'pointlist', 'mouse', 'stage', 'stroke', 'dragging', '../point_src/constrain-distance.js')
unused_keys ()
unknown_keys ('categories',)
categories ['', 'linkage', 'constraints', 'wheels']
filepath_exists True
path restricted-linear-bar.js
filepath restricted-linear-bar.js
clean_files ('../point_src/core/head.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/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/events.js', '../point_src/automouse.js', '../point_src/stage-hooks.js', '../point_src/stage-resize.js', '../point_src/functions/resolve.js', '../point_src/stage.js', '../point_src/setunset.js', '../point_src/stroke.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/constrain-distance.js')
markdown {'html': '', 'content': '---\ntitle: Restricted Linear Bar (Pure Linkage Network)\ncategories:\n linkage\n constraints\n wheels\nfiles:\n head\n point\n ../point_src/point-content.js\n pointlist\n mouse\n stage\n stroke\n dragging\n ../point_src/constrain-distance.js\n---'}