#INCLUDE JsGraph.inc #INCLUDE ControlPanel.inc <style> .Wiki .GraphHeader { font-weight:bold; } .Wiki .descr { font-size:small; line-height: 1.3em; margin-top:0.2em; } .Wiki div.JsGraph { margin-bottom: 0; clear: both; } #ControlPanel1-t-Slider-Handle { background: #666; } #ControlPanel1-pp-Slider-Handle, #ControlPanel1-py-Slider-Handle, #ControlPanel1-ny-Slider-Handle { background-color: #C0C; } #ControlPanel1-px-Slider-Handle, #ControlPanel1-nx-Slider-Handle { background-color: #00C; } #ControlPanel1-ptRel-Slider-Handle, #ControlPanel1-nt-Slider-Handle { background-color: #0A0; } #ControlPanel2-yZoom-Slider-Handle, #ControlPanel2-xZoom-Slider-Handle { background-color: #666; } </style> <jscript> function sq( x ) { return x * x; } function CModel() { this.yZoom = 1; this.xZoom = 1; this.FPtr = true; this.APtr = false; this.GPtr = false; this.VPtr = true; this.t = 1; this.trel = 0.5; this.ptRel = 0; this.m = 1; this.g = 16; this.h0 = 0; this.pp = 8; this.pt = 0; this.px = 0; this.py = 0; this.nt = 5; this.nx = 5; this.ny = 6; this.ntLast = this.nt; this.nxLast = this.nx; this.nyLast = this.ny; this.te = 2; this.s = 10; this.ppmax = 16; this.steps = 150; this.CompAll(); } CModel.prototype.Init = function() { this.ntLast = this.nt; this.nxLast = this.nx; this.nyLast = this.ny; this.t = this.trel * this.te; this.dt = this.te / this.steps; this.dx = this.s / this.steps; this.pt = 0.99 * this.ptRel * this.te / this.nt / Math.PI; // limit so that t never exceeds 0 or te this.tPoly = []; this.xPoly = []; this.yPoly = []; this.vPoly = []; this.EkPoly = []; this.EpPoly = []; this.LPoly = []; this.xNatPoly = []; this.yNatPoly = []; this.wmin = 0; this.w = 0; this.wPrec = 0; this.xPub = 0; this.yPub = 0; this.vxPub = 0; this.vyPub = 0; this.vPub = 0; this.axPub = 0; this.ayPub = 0; this.aPub = 0; this.EkPub = 0; this.EpPub = 0; this.LPub = 0; this.wPub = 0; } CModel.prototype.Reset = function() { this.ntLast = this.nt; this.nxLast = this.nx; this.nyLast = this.ny; } CModel.prototype.VarFunc = function( p, n, t ) { return p * Math.sin( n * Math.PI * t / this.te ); } CModel.prototype.CompU = function( t ) { this.u = t + this.VarFunc( this.pt, this.nt, t ); } CModel.prototype.CompDU = function( t ) { this.du = 1 + this.nt * this.pt * Math.PI * Math.cos( this.nt * Math.PI * t / this.te ) / this.te; } CModel.prototype.CompDDU = function( t ) { this.ddu = - sq(this.nt) * this.pt * sq(Math.PI) * Math.sin( this.nt * Math.PI * t / this.te ) / sq(this.te); } CModel.prototype.CompXnat = function( t ) { this.xNat = this.s * t / this.te; } CModel.prototype.CompYnat = function( t ) { this.yNat = -this.g * t * (t - this.te) / 2; } CModel.prototype.CompX = function() { this.x = this.s * this.u / this.te + this.VarFunc( this.px, this.nx, this.u ); } CModel.prototype.CompY = function() { this.y = -this.pp * this.u * (this.u - this.te) + this.VarFunc( this.py, this.ny, this.u ); } CModel.prototype.CompVX = function() { this.vx = (this.s * this.du + this.nx * this.px * Math.PI * this.du * Math.cos( this.nx * Math.PI * this.u / this.te ) ) / this.te; } CModel.prototype.CompVY = function() { this.vy = this.ny * this.py * Math.PI * this.du * Math.cos( this.ny * Math.PI * this.u / this.te ) / this.te - this.pp * ( 2 * this.u - this.te ) * this.du; } CModel.prototype.CompV = function() { this.v2 = this.vx * this.vx + this.vy * this.vy; this.v = Math.sqrt( this.v2 ); } CModel.prototype.CompAX = function() { this.ax = this.s * this.ddu / this.te + this.nx * this.px * Math.PI * this.ddu * Math.cos( this.nx * Math.PI * this.u / this.te ) / this.te - sq(this.nx) * this.px * sq(Math.PI) * sq(this.du) * Math.sin( this.nx * Math.PI * this.u / this.te ) / sq(this.te); } CModel.prototype.CompAY = function() { this.ay = this.ny * this.py * Math.PI * this.ddu * Math.cos( this.ny * Math.PI * this.u / this.te ) / this.te - sq(this.ny) * this.py * sq(Math.PI) * sq(this.du) * Math.sin( this.ny * Math.PI * this.u / this.te ) / sq(this.te) - this.pp * (2 * this.u - this.te) * this.ddu - 2 * this.pp * sq(this.du); } CModel.prototype.CompA = function() { this.a = Math.sqrt( sq(this.ax) + sq(this.ay) ); } CModel.prototype.CompEK = function() { this.Ek = 0.5 * this.m * this.v2; } CModel.prototype.CompEP = function() { this.Ep = this.m * this.g * (this.y + this.h0); } CModel.prototype.CompL = function() { this.L = this.Ek - this.Ep; } CModel.prototype.CompWmin = function() { var te3 = this.te * this.te * this.te; var v = this.s / this.te; var p = this.g / 2; this.wmin = (this.m / 6) * (te3 * sq(p) - te3 * this.g * p + 3 * this.te * ( sq(v) - 2 * this.g * this.h0 ) ); } CModel.prototype.CompXYatTime = function( t ) { this.CompU( t ); this.CompX(); this.CompY(); } CModel.prototype.CompXYVAatTime = function( t ) { this.CompXYatTime( t ); this.CompDU( t ); this.CompDDU( t ); this.CompVX(); this.CompVY(); this.CompV(); this.CompAX(); this.CompAY(); this.CompA(); } CModel.prototype.CompAllAtTime = function( t ) { this.CompXYVAatTime( t ); this.CompEK(); this.CompEP(); this.CompL(); this.CompXnat( t ); this.CompYnat( t ); } CModel.prototype.CompAll = function() { // change px, py, pt if zero and corresponding nx, ny, nt is changed if (Math.abs(this.px) < 1e-5 && this.nx != this.nxLast) this.px += 1; if (Math.abs(this.py) < 1e-5 && this.ny != this.nyLast) this.py += 1; if (Math.abs(this.ptRel) < 1e-5 && this.nt != this.ntLast) this.ptRel += 0.5; this.Init(); this.CompWmin(); var w = 0; var llast = 0; var limit = this.te + this.dt/2; for (var t = 0; t <= limit; t += this.dt) { this.CompAllAtTime( t ); this.tPoly.push( t ); this.xPoly.push( this.x ); this.yPoly.push( this.y ); this.vPoly.push( this.v ); this.EkPoly.push( this.Ek ); this.EpPoly.push( this.Ep ); this.LPoly.push( this.L ); this.xNatPoly.push( this.xNat ); this.yNatPoly.push( this.yNat ); if (t > 0) { w += (llast + this.L) / 2 * this.dt; } llast = this.L; } var wComp = w; var w = 0; var llast = 0; var dt = this.dt / 2; var limit = this.te + dt/2; for (var t = 0; t <= limit; t += dt) { this.CompAllAtTime( t ); if (t > 0) { w += (llast + this.L) / 2 * dt; } llast = this.L; } this.w = w; this.wPrec = Math.abs( w - wComp ); this.CompAllAtTime( this.t ); this.xPub = this.x; this.yPub = this.y; this.vxPub = this.vx; this.vyPub = this.vy; this.vPub = this.v; this.axPub = this.ax; this.ayPub = this.ay; this.aPub = this.a; this.EkPub = this.Ek; this.EpPub = this.Ep; this.LPub = this.L; this.wPub = this.w; } var model = new CModel(); function DrawH() { g1.Reset(); var snorm = 10; var mx = (14 - snorm) / 2; var xmin = (model.s - model.s/model.xZoom)/2 - mx/model.xZoom; var xmax = (model.s + model.s/model.xZoom)/2 + mx/model.xZoom; var my = 2; g1.SetWindowWH( xmin, -my/model.yZoom, xmax-xmin, (10+2*my)/model.yZoom ); g1.SetColor( '#DDD' ); g1.Grid( 1, 1, false ); g1.SetLineAttr( '#CCF', 4 ); g1.Polygon( model.xNatPoly, model.yNatPoly ); g1.SetMarkerAttr( 'Circle', 10, 'black', 'black', 2 ) ; g1.Marker( 0, 0 ); g1.Marker( model.s, 0 ); g1.SetLineAttr( '#44F', 1 ); g1.Polygon( model.xPoly, model.yPoly ); g1.SetMarkerAttr( 'Circle', 3, '#44F', '#44F', 1 ); var dt = 0.05; for (var t = 0; t <= model.te+dt/1000; t += dt) { model.CompXYatTime( t ); g1.Marker( model.x, model.y ); } g1.SetMarkerAttr( 'Circle', 4, '#F44', '#f44', 1 ); var dt = 0.25; for (var t = 0; t <= model.te+dt/1000; t += dt) { model.CompXYatTime( t ); g1.Marker( model.x, model.y ); } model.CompXYVAatTime( model.t ); g1.SetMarkerAttr( 'Circle', 8, 'gray', 'white', 2 ) ; g1.Marker( model.x, model.y ); var as = 0.05; var vs = 0.1; if (model.APtr || model.GPtr) { g1.SetMarkerAttr( 'Arrow1', 6, 'orange', 'orange', 1 ) ; var ay = model.ay; g1.Arrow( model.x, model.y, model.x+model.ax*as, model.y+ay*as ); } if (model.GPtr) { g1.SetMarkerAttr( 'Arrow1', 6, '#F88', '#F88', 1 ) ; var ay = model.ay + model.g; g1.Arrow( model.x, model.y, model.x+model.ax*as, model.y+ay*as ); g1.SetMarkerAttr( 'Arrow1', 6, '#88F', '#88F', 1 ) ; var ay = model.ay + model.g; g1.Arrow( model.x+model.ax*as, model.y+ay*as, model.x+model.ax*as, model.y+model.ay*as ); } if (model.FPtr) { g1.SetMarkerAttr( 'Arrow1', 6, 'red', 'red', 1 ) ; var ay = model.ay + model.g; g1.Arrow( model.x-model.ax*as, model.y-ay*as, model.x, model.y ); } if (model.VPtr) { g1.SetMarkerAttr( 'Arrow1', 6, 'green', 'green', 1 ) ; g1.Arrow( model.x, model.y, model.x+model.vx*vs, model.y+model.vy*vs ); } } function DrawE() { g2.Reset(); var wWidth = g2.CanvasWidth / 18; var wMargin = 4; g2.SetViewport( 0, 0, -wWidth, 0 ); g2.SetViewportRel( 0, 0, wMargin/2, 0 ); g2.SetWindowWH( 0, -150/model.yZoom, model.te, 450/model.yZoom ); g2.SetColor( '#DDD' ); g2.Grid( 0.25, 25 ); g2.OpenPath(); g2.Polygon( model.tPoly, model.LPoly ); g2.LineTo( model.te, 0 ); g2.LineTo( 0, 0 ); g2.ClosePath(); g2.SetBgColor( '#FDB' ); g2.Path( 2 ); g2.SetBgColor( 'white' ); g2.SetLineAttr( 'black', 2 ); g2.AxesX( 0 ); model.CompAllAtTime( model.t ); g2.SetLineAttr( 'red', 2 ); g2.Polygon( model.tPoly, model.LPoly ); g2.Marker( model.t, model.L ); g2.SetLineAttr( 'cyan', 1 ); g2.Polygon( model.tPoly, model.EkPoly ); g2.Marker( model.t, model.Ek ); g2.SetLineAttr( 'magenta', 1 ); g2.Polygon( model.tPoly, model.EpPoly ); g2.Marker( model.t, model.Ep ); g2.SetWindowWH( 0, -20/model.yZoom, model.te, 60/model.yZoom ); g2.SetLineAttr( 'green', 2 ); g2.Polygon( model.tPoly, model.vPoly ); g2.Marker( model.t, model.v ); g2.SetLineAttr( 'black', 2 ); g2.AxesY( 0 ); // ----- var winYRange = 160 / model.yZoom; var winYMin = -110 / model.yZoom; var winYMax = winYRange + winYMin; g2.ResetAttrs(); g2.SetViewport( g2.CanvasWidth-wWidth, 0, wWidth ); g2.SetViewportRel( wMargin/2, 0, 0, 0 ); g2.SetWindowWH( 0, winYMin, wWidth, winYRange ); g2.SetLineAttr( '#DDD', 1 ); g2.GridY( 10 ); g2.SetLineAttr( 'black', 1 ); g2.Frame(); g2.TicsY( 0, 10, 2, 0, true, false ); var m = 4; g2.SetBgColor( '#DDD' ); g2.Rect( m, model.wmin, wWidth-m, model.w, 2 ); g2.SetBgColor( 'orange' ); g2.Rect( m, 0, wWidth-m, model.w, 2 ); g2.SetLineAttr( 'black', 1 ); g2.Line( m, model.wmin, wWidth-m, model.wmin ); g2.SetLineAttr( 'red', 1 ); g2.Line( m, model.w, wWidth-m, model.w ); g2.SetLineAttr( 'black', 2 ); g2.AxesX(); var mSize = 6; var mMargin = 2; var mMid = wWidth / 2; var diff = Math.abs( model.w - model.wmin ) * 2; if (model.wmin >= winYMin && model.wmin <= winYMax) { var col = 'black'; if (diff < model.wPrec) col = 'white'; g2.SetMarkerAttr( 'ArrowRight', mSize, 'black', col, 1 ); g2.Marker( mMid-mMargin, model.wmin ); } if (model.w >= winYMin && model.w <= winYMax) { var col = 'red'; if (diff < model.wPrec) col = 'white'; g2.SetMarkerAttr( 'ArrowLeft', mSize, 'red', col, 1 ); g2.Marker( mMid+mMargin, model.w ); } if (model.wmin < winYMin) { g2.SetMarkerAttr( 'ArrowDown', mSize, 'black', 'black', 1 ); g2.Marker( mMid, winYMin ); } if (model.w < winYMin) { g2.SetMarkerAttr( 'ArrowDown', mSize, 'red', 'red', 1 ); g2.Marker( mMid, winYMin ); } if (model.w > winYMax) { g2.SetMarkerAttr( 'ArrowUp', mSize, 'red', 'red', 1 ); g2.Marker( mMid, winYMax ); } if (model.wmin > winYMax) { g2.SetMarkerAttr( 'ArrowUp', mSize, 'black', 'black', 1 ); g2.Marker( mMid, winYMax ); } } var FrameTimer = null; function DrawAll() { if (FrameTimer) return; FrameTimer = requestAnimationFrame( DoDrawAll ); } function DoDrawAll() { FrameTimer = null; model.CompAll(); panel.Update(); panel2.Update(); panel3.Update(); panel4.Update(); panel5.Update(); DrawH(); DrawE(); } function Reset() { panel.Reset(); panel3.Reset(); model.Reset(); DrawAll(); } xOnLoad( DrawAll ); </jscript> {{col|50}} {{div|$GraphHeader}}Flugbahn: {{span|x(t), y(t)|style=color:blue}}{{end div}} <jscript> var g1 = NewGraph2D( { Height: '100%', DrawFunc: DrawH, AutoReset: false, BorderWidth: 1, ScaleRef: 300, LimitScalePix: false, AutoScalePix: true } ); </jscript> {{div|$descr}}Hellblau: Flugbahn der Natur = f( g, t<sub>e</sub>, s ) /// Blaue Punkte: Positionen im Abstand von (_0.05: s_) /// Roter Pfeil: gefühlte Schubkraft im Flugobjekt{{end div}} {{col}} {{div|$GraphHeader}}Lagrangian {{span|L(t)|style=color:red}} = {{span|T(t)|style=color:cyan}}-{{span|V(t)|style=color:magenta}}; {{span|v(t)|style=color:green}} {{div|$FloatRight|style=color:orange}}Wirkung{{end div}}{{end div}} <jscript> var g2 = NewGraph2D( { Height: '100%', DrawFunc: DrawE, AutoReset: false, BorderWidth: 1, ScaleRef: 300, LimitScalePix: false, AutoScalePix: true } ); </jscript> {{div|$descr}}Orange Fläche: Wirkung = Integral des Lagrangian /// Oranger Balken, roter Pfeil: Wirkung /// Schwarzer Pfeil: Kleinste Wirkung{{end div}} {{col|end}} {{col|50}} {{div|$GraphHeader}}Flugbahn-Variationen [javascript:Reset()|{{ButtonText|Reset|small|$FloatRight}}]{{end div}} <jscript> var panel3 = ControlPanels.NewSliderPanel( { ModelRef: 'model', ReadOnly: true, OnModelChange: DrawAll } ); panel3.AddValueSliderField( { Name: 't', Label: '(t)', SliderValueRef: 'trel', Min: 0, Max: 1 } ); panel3.AddValueSliderField( { Name: 'pp', Label: 'p', Min: 0, Max: model.ppmax, Steps: 64 } ); panel3.AddValueSliderField( { Name: 'py', Label: 'p<sub>y</sub>', Min: -2, Max: 2, Steps: 40 } ); panel3.AddValueSliderField( { Name: 'ny', Label: 'n<sub>y</sub>', Min: 2, Max: 10, Steps: 8 } ); panel3.AddValueSliderField( { Name: 'px', Label: 'p<sub>x</sub>', Min: -2, Max: 2, Steps: 40 } ); panel3.AddValueSliderField( { Name: 'nx', Label: 'n<sub>x</sub>', Min: 1, Max: 9, Steps: 8 } ); panel3.AddValueSliderField( { Name: 'ptRel', Label: 'p<sub>v</sub>', Min: -1, Max: 1, Steps: 40 } ); panel3.AddValueSliderField( { Name: 'nt', Label: 'n<sub>v</sub>', Min: 1, Max: 9, Steps: 8 } ); panel3.Render(); </jscript> {{col}} {{div|$GraphHeader}}Rahmenbedingungen [javascript:Reset()|{{ButtonText|Reset|small|$FloatRight}}]{{end div}} <jscript> var panel = ControlPanels.NewSliderPanel( { ModelRef: 'model', ReadOnly: true, OnModelChange: DrawAll, PanelFormat: 'NoMargin' } ); panel.AddValueSliderField( { Name: 'te', Label: 't<sub>e</sub>', Min: 1, Max: 3, Steps: 100 } ); panel.AddValueSliderField( { Name: 's', Min: 5, Max: 15, Steps: 40 } ); panel.AddValueSliderField( { Name: 'g', Min: 0, Max: 32, Steps: 64 } ); panel.AddValueSliderField( { Name: 'm', Min: 0, Max: 2, Steps: 40 } ); panel.AddValueSliderField( { Name: 'h0', Label: 'h<sub>0</sub>', Min: -5, Max: 5, Steps: 100 } ); panel.AddValueSliderField( { Name: 'xZoom', Label: '<span style="color:gray">(x)</style>', Min: 0.2, Max: 2, Steps: 36 } ); panel.AddValueSliderField( { Name: 'yZoom', Label: '<span style="color:gray">(y)</style>', Min: 0.2, Max: 2, Steps: 36 } ); panel.Render(); var panel5 = ControlPanels.NewPanel( { NCols: 1, ModelRef: 'model', OnModelChange: DrawAll, PanelFormat: 'OneCol' } ); panel5.AddCheckboxField( { Name: 'Pfeile', ColSpan: 3, Items: [ { Name: 'FPtr', Text: '<span style="color:red">Schubkraft</span>' }, { Name: 'APtr', Text: '<span style="color:#F80">a(t)</span>' }, { Name: 'GPtr', Text: '<span style="color:#88F">g</span>' }, { Name: 'VPtr', Text: '<span style="color:green">v(t)</span>' } ] } ); panel5.Render(); </jscript> {{col|end}} {{col|50}} <jscript> var panel2 = ControlPanels.NewPanel( { NCols: 2, PanelFormat: 'InputMaxWidth', ModelRef: 'model', ReadOnly: true } ); panel2.AddTextField( { Name: 'xPub', Label: '<span style="color:blue">x(t)</style>' } ); panel2.AddTextField( { Name: 'yPub', Label: '<span style="color:blue">y(t)</style>' } ); panel2.AddTextField( { Name: 'vxPub', Label: '<span style="color:green">v<sub>x</sub>(t)</style>' } ); panel2.AddTextField( { Name: 'vyPub', Label: '<span style="color:green">v<sub>y</sub>(t)</style>' } ); panel2.AddTextField( { Name: 'axPub', Label: '<span style="color:orange">a<sub>x</sub>(t)</style>' } ); panel2.AddTextField( { Name: 'ayPub', Label: '<span style="color:orange">a<sub>y</sub>(t)</style>' } ); panel2.Render(); </jscript> {{col}} <jscript> var panel4 = ControlPanels.NewPanel( { NCols: 2, PanelFormat: 'InputMaxWidth', ModelRef: 'model', ReadOnly: true } ); panel4.AddTextField( { Name: 'vPub', Label: '<span style="color:green">v(t)</style>' } ); panel4.AddTextField( { Name: 'aPub', Label: '<span style="color:orange">a(t)</style>' } ); panel4.AddTextField( { Name: 'EkPub', Label: '<span style="color:cyan">T(t)</style>' } ); panel4.AddTextField( { Name: 'EpPub', Label: '<span style="color:magenta">V(t)</style>' } ); panel4.AddTextField( { Name: 'LPub', Label: '<span style="color:red">L(t)</style>' } ); panel4.AddTextField( { Name: 'wPub', Label: '<span style="color:#F80">W</style>' } ); panel4.Render(); </jscript> {{col|end}}