BlankSlateApp has a LabCanvas and Terminal, and lets you experiment building things with scripts. Here is a sample script to try (copy the text and paste into Terminal input area).
var r = PointMass.makeSquare(4); var dr = new DisplayShape(r); dr.setStrokeStyle('red'); dr.setThickness(4); displayList.add(dr); r.setPosition(new Vector(0, 0)); var clock = new Clock(); var timer = new Timer(); var callback = function () { r.setAngle(Math.sin(clock.getTime())); simCanvas.paint(); }; timer.setCallBack(callback); clock.resume(); timer.startFiring();Here is another script to try, this one replicates what SimpleApp does.
var point1 = PointMass.makeRectangle(1, 1.5, 'block'); var fixedPt = PointMass.makeSquare(1, 'fixed'); fixedPt.setMass(Infinity); fixedPt.setPosition(new Vector(-4, 0)); var spring1 = new Spring('spring', fixedPt, Vector.ORIGIN, point1, Vector.ORIGIN, 1, 3); var shape1 = new DisplayShape(point1); shape1.setFillStyle('orange'); displayList.add(shape1); var dspring = new DisplaySpring(spring1); dspring.setWidth(1.0); dspring.setColorCompressed('yellow'); dspring.setColorExpanded('blue'); displayList.add(dspring); var clock = new Clock(); var timer = new Timer(); timer.setCallBack(() => { point1.setPosition(new Vector(1 + 3*Math.sin(3*clock.getTime()), 0)); simCanvas.paint(); }); timer.startFiring(); clock.resume();Here is a script that runs the SingleSpringSim
var simRect = new DoubleRect(-3, -2, 3, 2); simView.setSimRect(simRect); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var simList = sim.getSimList(); var block = new DisplayShape(simList.getPointMass('block')); block.setFillStyle('blue'); displayList.add(block); var spring = new DisplaySpring(simList.getSpring('spring')); spring.setWidth(0.4); spring.setThickness(6); displayList.add(spring); var deSolver = new ModifiedEuler(sim); var clock = new Clock(); var lastTime = 0; timer.setCallBack(() => { var now = clock.getTime(); deSolver.step(now - lastTime); lastTime = now; sim.modifyObjects(); simCanvas.paint(); }); timer.startFiring(); clock.resume();This script runs SingleSpringSim with a SimRunner and SimpleAdvance, so you don't need to set up your own callback for stepping the diffeq forward.
var simRect = new DoubleRect(-3, -2, 3, 2); simView.setSimRect(simRect); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var block = new DisplayShape(simList.getPointMass('block')); block.setFillStyle('blue'); displayList.add(block); var spring = new DisplaySpring(simList.getSpring('spring')); spring.setWidth(0.4); spring.setThickness(6); displayList.add(spring); simRun.resume();This script runs SingleSpringSim with a SimRunner and SimpleAdvance, and adds a pan-zoom control.
var simRect = new DoubleRect(-3, -2, 3, 2); simView.setSimRect(simRect); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var block = new DisplayShape(simList.getPointMass('block')); block.setFillStyle('blue'); displayList.add(block); var spring = new DisplaySpring(simList.getSpring('spring')); spring.setWidth(0.4); spring.setThickness(6); displayList.add(spring); var panzoom = CommonControls.makePanZoomControls(simView); simDiv.appendChild(panzoom); panzoom.style.display = 'block'; simRun.resume();This script runs PendulumSim with a SimRunner and SimpleAdvance.
var simRect = new DoubleRect(-1.4, -0.9, 1.4, 0.9); simView.setSimRect(simRect); var sim = new PendulumSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var rod = new DisplayLine(simList.getConcreteLine('rod')); displayList.add(rod); var drive = new DisplayArc(simList.getArc('drive')); displayList.add(drive); var bob = new DisplayShape(simList.getPointMass('bob')); bob.setFillStyle('blue'); displayList.add(bob); sim.getVarsList().getVariable(PendulumSim.en.ANGLE).setValue(Math.PI/8); simRun.resume();This script runs RollerSingleSim with a SimRunner and SimpleAdvance.
var simRect = new DoubleRect(-3.4, -3.4, 3.4, 3.4); simView.setSimRect(simRect); var sim = new RollerSingleSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var npath = new NumericalPath(new CirclePath(3)); var displayPath = new DisplayPath(); displayPath.setScreenRect(simView.getScreenRect()); displayPath.addPath(npath); displayList.add(displayPath); sim.setPath(npath); var ball1 = new DisplayShape(simList.getPointMass('ball1')); ball1.setFillStyle('blue'); displayList.add(ball1); var axes = new DisplayAxes(simView.getSimRect()); displayList.add(axes); simRun.resume();This script runs SingleSpringSim with a SimRunner and SimpleAdvance, and adds a checkbox to show the clock.
var simRect = new DoubleRect(-3, -2, 3, 2); simView.setSimRect(simRect); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var block = new DisplayShape(simList.getPointMass('block')); block.setFillStyle('blue'); displayList.add(block); var spring = new DisplaySpring(simList.getSpring('spring')); spring.setWidth(0.4); spring.setThickness(6); displayList.add(spring); simRun.resume(); var dispClock = new DisplayClock(()=>sim.getTime(), ()=>simRun.getClock().getRealTime()); dispClock.setPosition(new Vector(1.2, -1.6)); var cb = new CheckBoxControlBase('show clock', ()=>displayList.contains(dispClock), (value)=>{if (value) {displayList.add(dispClock)} else {displayList.remove(dispClock) }}); app.addControl(cb);This script runs SingleSpringSim with a SimRunner and SimpleAdvance, and includes DisplayAxes and EnergyBarGraph.
var simRect = new DoubleRect(-3, -2, 3, 2); simView.setSimRect(simRect); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var block = new DisplayShape(simList.getPointMass('block')); block.setFillStyle('blue'); displayList.add(block); var spring = new DisplaySpring(simList.getSpring('spring')); spring.setWidth(0.4); spring.setThickness(6); displayList.add(spring); var axes = new DisplayAxes(simView.getSimRect()); displayList.add(axes); var energy = new EnergyBarGraph(sim); var r = simView.getCoordMap().screenToSimRect(simView.getScreenRect()); energy.setVisibleArea(r); displayList.add(energy); simRun.resume();This script runs SingleSpringSim with a SimRunner and SimpleAdvance, and includes a DisplayGraph with some controls for which variables to graph.
simView.setSimRect(new DoubleRect(-3, -2, 3, 2)); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var block = new DisplayShape(simList.getPointMass('block')); block.setFillStyle('blue'); displayList.add(block); var spring = new DisplaySpring(simList.getSpring('spring')); spring.setWidth(0.4); spring.setThickness(6); displayList.add(spring); var axes = new DisplayAxes(simView.getSimRect()); displayList.add(axes); const graphDiv = document.getElementById('graph_div'); const canvas = document.createElement('canvas'); graphDiv.appendChild(canvas); var graphCanvas = new LabCanvas(canvas, 'canvas1'); graphCanvas.setSize(800, 800); simRun.addCanvas(graphCanvas); var graphView = new SimView('graphView', new DoubleRect(-3, -8, 3, 8)); graphView.setHorizAlign('FULL'); graphView.setVerticalAlign('FULL'); graphCanvas.addView(graphView); var line = new GraphLine('X_Y_GRAPH_LINE', sim.getVarsList()); line.setXVariable('position'); line.setYVariable(1); line.setColor('lime'); graphView.addMemo(line); var displayGraph = new DisplayGraph(line); displayGraph.setScreenRect(graphView.getScreenRect()); graphView.getDisplayList().prepend(displayGraph); var axes = new DisplayAxes(graphView.getSimRect()); graphView.getDisplayList().add(axes); var xChoice = new ChoiceControl(line.getParameterNumber('X_VARIABLE')); app.addControl(xChoice); var yChoice = new ChoiceControl(line.getParameterNumber('Y_VARIABLE')); app.addControl(yChoice); simRun.resume();This script runs SingleSpringSim with a SimRunner and SimpleAdvance, and adds a NumericControlBase to modify the block mass, and a NumericControl to modify the spring stiffness.
var simRect = new DoubleRect(-3, -2, 3, 2); simView.setSimRect(simRect); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var block = simList.getPointMass('block'); var blockDisp = new DisplayShape(block); blockDisp.setFillStyle('blue'); displayList.add(blockDisp); var spring = simList.getSpring('spring'); var springDisp = new DisplaySpring(spring); springDisp.setWidth(0.4); springDisp.setThickness(6); displayList.add(springDisp); var massControl = new NumericControlBase('mass', ()=>block.getMass(), (value)=>block.setMass(value)); app.addControl(massControl); var springControl = new NumericControl(sim.getParameterNumber('spring stiffness')); app.addControl(springControl); var startButton = new ButtonControl('start', ()=>simRun.resume()); app.addControl(startButton); var img = Util.createImage(Util.IMAGES_DIR+'/pause.png', 30); var stopButton = new ButtonControl('stop', ()=>simRun.pause(), img); app.addControl(stopButton);This script runs SingleSpringSim with a DisplayGraph that has an AutoScale resizing it, a 'clear graph' button, and an Observer that resizes the DisplayAxes.
simView.setSimRect(new DoubleRect(-3, -2, 3, 2)); var sim = new SingleSpringSim(); simCtrl.setEventHandler(sim); var advance = new SimpleAdvance(sim); var simRun = new SimRunner(advance); var simList = sim.getSimList(); var block = new DisplayShape(simList.getPointMass('block')); block.setFillStyle('blue'); displayList.add(block); var spring = new DisplaySpring(simList.getSpring('spring')); spring.setWidth(0.4); spring.setThickness(6); displayList.add(spring); var axes = new DisplayAxes(simView.getSimRect()); displayList.add(axes); const graphDiv = document.getElementById('graph_div'); const canvas = document.createElement('canvas'); graphDiv.appendChild(canvas); var graphCanvas = new LabCanvas(canvas, 'canvas1'); graphCanvas.setSize(800, 800); simRun.addCanvas(graphCanvas); var graphView = new SimView('graphView', new DoubleRect(-3, -8, 3, 8)); graphView.setHorizAlign('FULL'); graphView.setVerticalAlign('FULL'); graphCanvas.addView(graphView); var line = new GraphLine('X_Y_GRAPH_LINE', sim.getVarsList()); line.setXVariable('position'); line.setYVariable(1); line.setColor('lime'); graphView.addMemo(line); var displayGraph = new DisplayGraph(line); displayGraph.setScreenRect(graphView.getScreenRect()); graphView.getDisplayList().prepend(displayGraph); var axes = new DisplayAxes(graphView.getSimRect()); graphView.getDisplayList().add(axes); var xChoice = new ChoiceControl(line.getParameterNumber('X_VARIABLE')); app.addControl(xChoice); var yChoice = new ChoiceControl(line.getParameterNumber('Y_VARIABLE')); app.addControl(yChoice); const auto = new AutoScale('auto-scale', line, graphView); new GenericObserver(graphView, evt => { if (evt.nameEquals(SimView.COORD_MAP_CHANGED)) { const r = graphView.getCoordMap().screenToSimRect(graphView.getScreenRect()); axes.setSimRect(r); }}, 'resize axes'); var clearButton = new ButtonControl('clear graph', ()=>line.reset()); app.addControl(clearButton); simRun.resume();