September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -14,15 +14,15 @@ pendulum = runGraphics $
(openWindowEx "Pendulum animation task" Nothing (600,400) DoubleBuffered (Just 30))
closeWindow
(\w -> mapM_ ((\ g -> setGraphic w g >> getWindowTick w).
(\ (x, y) -> overGraphic (line (300, 0) (x, y))
(ellipse (x - 12, y + 12) (x + 12, y - 12)) )) pts)
(\ (x, y) -> overGraphic (line (300, 0) (x, y))
(ellipse (x - 12, y + 12) (x + 12, y - 12)) )) pts)
where
dt = 1/30
t = - pi/4
l = 1
g = 9.812
nextAVT (a,v,t) = (a', v', t + v' * dt) where
a' = - (g / l) * sin t
v' = v + a' * dt
a' = - (g / l) * sin t
v' = v + a' * dt
pts = map (\(_,t,_) -> (toInt.(300+).(300*).cos &&& toInt. (300*).sin) (pi/2+0.6*t) )
$ iterate nextAVT (- (g / l) * sin t, t, 0)
$ iterate nextAVT (- (g / l) * sin t, t, 0)

View file

@ -0,0 +1,51 @@
import Graphics.Gloss
-- Initial conditions
g_ = (-9.8) :: Float --Gravity acceleration
v_0 = 0 :: Float --Initial tangential speed
a_0 = 0 / 180 * pi :: Float --Initial angle
dt = 0.01 :: Float --Time step
t_f = 15 :: Float --Final time for data logging
l_ = 200 :: Float --Rod length
-- Define a type to represent the pendulum:
type Pendulum = (Float, Float, Float) -- (rod length, tangential speed, angle)
-- Pendulum's initial state
initialstate :: Pendulum
initialstate = (l_, v_0, a_0)
-- Step funtion: update pendulum to new position
movePendulum :: Float -> Pendulum -> Pendulum
movePendulum dt (l,v,a) = ( l , v_2 , a + v_2 / l * dt*10 )
where v_2 = v + g_ * (cos a) * dt
-- Convert from Pendulum to [Picture] for display
renderPendulum :: Pendulum -> [Picture]
renderPendulum (l,v,a) = map (uncurry Translate newOrigin)
[ Line [ ( 0 , 0 ) , ( l * (cos a), l * (sin a) ) ]
, polygon [ ( 0 , 0 ) , ( -5 , 8.66 ) , ( 5 , 8.66 ) ]
, Translate ( l * (cos a)) (l * (sin a)) (circleSolid (0.04*l_))
, Translate (-1.1*l) (-1.3*l) (Scale 0.1 0.1 (Text currSpeed))
, Translate (-1.1*l) (-1.3*l + 20) (Scale 0.1 0.1 (Text currAngle))
]
where currSpeed = "Speed (pixels/s) = " ++ (show v)
currAngle = "Angle (deg) = " ++ (show ( 90 + a / pi * 180 ) )
-- New origin to beter display the animation
newOrigin = (0, l_ / 2)
-- Calcule a proper window size (for angles between 0 and -pi)
windowSize :: (Int, Int)
windowSize = ( 300 + 2 * round (snd newOrigin)
, 200 + 2 * round (snd newOrigin) )
-- Run simulation
main :: IO ()
main = do --plotOnGNU
simulate window background fps initialstate render update
where window = InWindow "Animate a pendulum" windowSize (40, 40)
background = white
fps = round (1/dt)
render xs = pictures $ renderPendulum xs
update _ = movePendulum

View file

@ -0,0 +1,28 @@
function degToRad( d )
return d * 0.01745329251
end
function love.load()
g = love.graphics
rodLen, gravity, velocity, acceleration = 260, 3, 0, 0
halfWid, damp = g.getWidth() / 2, .989
posX, posY, angle = halfWid
TWO_PI, angle = math.pi * 2, degToRad( 90 )
end
function love.update( dt )
acceleration = -gravity / rodLen * math.sin( angle )
angle = angle + velocity; if angle > TWO_PI then angle = 0 end
velocity = velocity + acceleration
velocity = velocity * damp
posX = halfWid + math.sin( angle ) * rodLen
posY = math.cos( angle ) * rodLen
end
function love.draw()
g.setColor( 250, 0, 250 )
g.circle( "fill", halfWid, 0, 8 )
g.line( halfWid, 4, posX, posY )
g.setColor( 250, 100, 20 )
g.circle( "fill", posX, posY, 20 )
end

View file

@ -0,0 +1,35 @@
pendulum = .pendulum~new(10, 30)
before = .datetime~new
do 100 -- somewhat arbitrary loop count
call syssleep .2
now = .datetime~new
pendulum~update(now - before)
before = now
say " X:" pendulum~x " Y:" pendulum~y
end
::class pendulum
::method init
expose length theta x y velocity
use arg length, theta
x = rxcalcsin(theta) * length
y = rxcalccos(theta) * length
velocity = 0
::attribute x GET
::attribute y GET
::constant g -9.81 -- acceleration due to gravity
::method update
expose length theta x y velocity
use arg duration
acceleration = self~g / length * rxcalcsin(theta)
durationSeconds = duration~microseconds / 1000000
x = rxcalcsin(theta, length)
y = rxcalccos(theta, length)
velocity = velocity + acceleration * durationSeconds
theta = theta + velocity * durationSeconds
::requires rxmath library

View file

@ -1,68 +1,76 @@
include ..\arwen\arwen.ew
include ..\arwen\axtra.ew
--
-- demo\rosetta\animate_pendulum2.exw
-- ==================================
--
include pGUI.e
constant main = create(Window, "Animated Pendulum", 0, 0, 20, 20, 625, 690, 0),
mainDC = getPrivateDC(main),
backDC = c_func(xCreateCompatibleDC, {NULL}), -- the background
viewDC = c_func(xCreateCompatibleDC, {NULL}), -- with animation
grey = #909090
Ihandle dlg, canvas, timer
cdCanvas cddbuffer, cdcanvas
constant MainTimer = createTimer()
integer dw = 0, dh = 0 -- client area width and height
atom bmBack, bmView
integer bmX = 0, bmY = 0 -- actual size of the bitmaps
constant dt = 1E-3
constant g = 50
integer sX = 0, sY = 0 -- suspension point of pendulum
integer len
atom alpha = PI/2,
omega = 0,
epsilon
omega = 0
function mainHandler(integer id, integer msg, atom wParam, object lParam)
integer eX, eY -- moving end of pendulum
if msg=WM_SIZE then
{{},{},dw,dh} = getClientRect(main)
if dw>bmX or dh>bmY then
-- we need bigger bitmaps
bmBack = c_func(xCreateCompatibleBitmap, {mainDC, dw, dh})
{} = deleteObject(selectObject(backDC,bmBack))
-- clear the background
setPenColor(grey)
drawRectangleh(backDC, True, 0, 0, dw, dh)
bmView = c_func(xCreateCompatibleBitmap, {mainDC, dw, dh})
{} = deleteObject(selectObject(viewDC,bmView))
{bmX,bmY} = {dw,dh}
end if
-- new suspension point and length
sX = floor(dw/2)
sY = floor(dh/8)
len = sX-20
elsif msg=WM_PAINT then
-- start with a fresh copy of the background
void = c_func(xBitBlt,{viewDC,0,0,dw,dh,backDC,0,0,SRCCOPY})
eX = floor(len*sin(alpha)+sX)
eY = floor(len*cos(alpha)+sY)
drawLinesh(viewDC,{Red,{sX,sY,eX,eY},Yellow})
drawEllipseh(viewDC,eX-5,eY-5,eX+5,eY+5)
void = c_func(xBitBlt,{mainDC,0,0,dw,dh,viewDC,0,0,SRCCOPY})
elsif msg=WM_TIMER then
epsilon = -len*sin(alpha)*g
omega += dt*epsilon
alpha += dt*omega
repaintWindow(main)
elsif msg=WM_SHOWWINDOW then
startTimer(MainTimer,main,33)
elsif msg=WM_CHAR
and wParam=VK_ESCAPE then
closeWindow(main)
if id or object(lParam) then end if -- suppress warnings
end if
return 0
function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
cdCanvasActivate(cddbuffer)
cdCanvasClear(cddbuffer)
-- new suspension point and length
integer sX = floor(w/2)
integer sY = floor(h/8)
integer len = sX-30
atom dt = 1/w
-- move:
atom epsilon = -len*sin(alpha)*g
omega += dt*epsilon
alpha += dt*omega
-- repaint:
integer eX = floor(len*sin(alpha)+sX)
integer eY = floor(len*cos(alpha)+sY)
cdCanvasSetForeground(cddbuffer, CD_DARK_GREY)
cdCanvasLine(cddbuffer, sX, h-sY, eX, h-eY)
cdCanvasSetForeground(cddbuffer, CD_BLACK)
cdCanvasSector(cddbuffer, eX, h-eY, 35, 35, 0, 360)
cdCanvasFlush(cddbuffer)
return IUP_DEFAULT
end function
setHandler({main},routine_id("mainHandler"))
WinMain(main, SW_NORMAL)
function timer_cb(Ihandle /*ih*/)
IupUpdate(canvas)
return IUP_IGNORE
end function
function map_cb(Ihandle ih)
cdcanvas = cdCreateCanvas(CD_IUP, ih)
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
cdCanvasSetBackground(cddbuffer, CD_GREY)
return IUP_DEFAULT
end function
function esc_close(Ihandle /*ih*/, atom c)
if c=K_ESC then return IUP_CLOSE end if
return IUP_CONTINUE
end function
procedure main()
IupOpen()
canvas = IupCanvas(NULL)
IupSetAttribute(canvas, "RASTERSIZE", "640x380")
IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
timer = IupTimer(Icallback("timer_cb"), 20)
dlg = IupDialog(canvas)
IupSetAttribute(dlg, "TITLE", "Animated Pendulum")
IupSetCallback(dlg, "K_ANY", Icallback("esc_close"))
IupShow(dlg)
IupSetAttribute(canvas, "RASTERSIZE", NULL)
IupMainLoop()
IupClose()
end procedure
main()

View file

@ -0,0 +1,85 @@
//Input variables (Assumptions: massless pivot, no energy loss)
bob_mass=10;
g=-9.81;
L=2;
theta0=-%pi/6;
v0=0;
t0=0;
//No. of steps
steps=300;
//Setting deltaT or duration (comment either of the lines below)
//deltaT=0.1; t_max=t0+deltaT*steps;
t_max=5; deltaT=(t_max-t0)/steps;
if t_max<=t0 then
error("Check duration (t0 and t_f), number of steps and deltaT.");
end
//Initial position
not_a_pendulum=%F;
t=zeros(1,steps); t(1)=t0; //time
theta=zeros(1,steps); theta(1)=theta0; //angle
F=zeros(1,steps); F(1)=bob_mass*g*sin(theta0); //force
A=zeros(1,steps); A(1)=F(1)/bob_mass; //acceleration
V=zeros(1,steps); V(1)=v0; //linear speed
W=zeros(1,steps); W(1)=v0/L; //angular speed
for i=2:steps
t(i)=t(i-1)+deltaT;
V(i)=A(i-1)*deltaT+V(i-1);
W(i)=V(i)/L;
theta(i)=theta(i-1)+W(i)*deltaT;
F(i)=bob_mass*g*sin(theta(i));
A(i)=F(i)/bob_mass;
if (abs(theta(i))>=%pi | (abs(theta(i))==0 & V(i)==0)) & ~not_a_pendulum then
disp("Initial conditions do not describe a pendulum.");
not_a_pendulum = %T;
end
end
clear i
//Ploting the pendulum
bob_r=0.08*L;
bob_shape=bob_r*exp(%i.*linspace(0,360,20)/180*%pi);
bob_pos=zeros(20,steps);
rod_pos=zeros(1,steps);
for i=1:steps
rod_pos(i)=L*exp(%i*(-%pi/2+theta(i)));
bob_pos(:,i)=bob_shape'+rod_pos(i);
end
clear i
scf(0); clf(); xname("Simple gravity pendulum");
plot2d(real([0 rod_pos(1)]),imag([0 rod_pos(1)]));
axes=gca();
axes.isoview="on";
axes.children(1).children.mark_style=3;
axes.children(1).children.mark_size=1;
axes.children(1).children.thickness=3;
plot2d(real(bob_pos(:,1)),imag(bob_pos(:,1)));
axes=gca();
axes.children(1).children.fill_mode="on";
axes.children(1).children.foreground=2;
axes.children(1).children.background=2;
if max(imag(bob_pos))>0 then
axes.data_bounds=[-L-bob_r,-L-1.01*bob_r;L+bob_r,max(imag(bob_pos))];
else
axes.data_bounds=[-L-bob_r,-L-1.01*bob_r;L+bob_r,bob_r];
end
//Animating the plot
disp("Duration: "+string(max(t)+deltaT-t0)+"s.");
sleep(850);
for i=2:steps
axes.children(1).children.data=[real(bob_pos(:,i)), imag(bob_pos(:,i))];
axes.children(2).children.data=[0, 0; real(rod_pos(i)), imag(rod_pos(i))];
sleep(deltaT*1000)
end
clear i

View file

@ -0,0 +1,35 @@
'Pendulum
'By Dutchman
' --- constants
g=9.81 ' accelleration of gravity
l=1 ' length of pendulum
GET SCREEN SIZE sw,sh
pivotx=sw/2
pivoty=150
' --- initialise graphics
GRAPHICS
DRAW COLOR 1,0,0
FILL COLOR 0,0,1
DRAW SIZE 2
' --- initialise pendulum
theta=1 ' initial displacement in radians
speed=0
' --- loop
DO
bobx=pivotx+100*l*SIN(theta)
boby=pivoty-100*l*COS(theta)
GOSUB Plot
PAUSE 0.01
accel=g*SIN(theta)/l/100
speed=speed+accel
theta=theta+speed
UNTIL 0
END
' --- subroutine
Plot:
REFRESH OFF
GRAPHICS CLEAR 1,1,0.5
DRAW LINE pivotx,pivoty TO bobx,boby
FILL CIRCLE bobx,boby SIZE 10
REFRESH ON
RETURN