langs a-z

This commit is contained in:
Ingy döt Net 2013-04-10 22:43:41 -07:00
parent db842d013d
commit d066446780
11389 changed files with 98361 additions and 1020 deletions

View file

@ -0,0 +1,81 @@
declare
[QTk] = {Link ['x-oz://system/wp/QTk.ozf']}
Pi = 3.14159265
class PendulumModel
feat
K
attr
angle
velocity
meth init(length:L <= 1.0 %% meters
gravity:G <= 9.81 %% m/s²
initialAngle:A <= Pi/2.) %% radians
self.K = ~G / L
angle := A
velocity := 0.0
end
meth nextAngle(deltaT:DeltaTMS %% milliseconds
?Angle) %% radians
DeltaT = {Int.toFloat DeltaTMS} / 1000.0 %% seconds
Acceleration = self.K * {Sin @angle}
in
velocity := @velocity + Acceleration * DeltaT
angle := @angle + @velocity * DeltaT
Angle = @angle
end
end
%% Animates a pendulum on a given canvas.
class PendulumAnimation from Time.repeat
feat
Pend
Rod
Bob
home:pos(x:160 y:50)
length:140.0
delay
meth init(Pendulum Canvas delay:Delay <= 25) %% milliseconds
self.Pend = Pendulum
self.delay = Delay
%% plate and pivot
{Canvas create(line 0 self.home.y 320 self.home.y width:2 fill:grey50)}
{Canvas create(oval 155 self.home.y-5 165 self.home.y+5 fill:grey50 outline:black)}
%% the pendulum itself
self.Rod = {Canvas create(line 1 1 1 1 width:3 fill:black handle:$)}
self.Bob = {Canvas create(oval 1 1 2 2 fill:yellow outline:black handle:$)}
%%
{self setRepAll(action:Animate delay:Delay)}
end
meth Animate
Theta = {self.Pend nextAngle(deltaT:self.delay $)}
%% calculate x and y from angle
X = self.home.x + {Float.toInt self.length * {Sin Theta}}
Y = self.home.y + {Float.toInt self.length * {Cos Theta}}
in
%% update canvas
try
{self.Rod setCoords(self.home.x self.home.y X Y)}
{self.Bob setCoords(X-15 Y-15 X+15 Y+15)}
catch system(tk(alreadyClosed ...) ...) then skip end
end
end
Pendulum = {New PendulumModel init}
Canvas
GUI = td(title:"Pendulum"
canvas(width:320 height:210 handle:?Canvas)
action:proc {$} {Animation stop} {Window close} end
)
Window = {QTk.build GUI}
Animation = {New PendulumAnimation init(Pendulum Canvas)}
in
{Window show}
{Animation go}

View file

@ -0,0 +1,107 @@
Procedure handleError(x, msg.s)
If Not x
MessageRequester("Error", msg)
End
EndIf
EndProcedure
#ScreenW = 320
#ScreenH = 210
handleError(OpenWindow(0, 0, 0, #ScreenW, #ScreenH, "Animated Pendulum", #PB_Window_SystemMenu), "Can't open window.")
handleError(InitSprite(), "Can't setup sprite display.")
handleError(OpenWindowedScreen(WindowID(0), 0, 0, #ScreenW, #ScreenH, 0, 0, 0), "Can't open screen.")
Enumeration ;sprites
#bob_spr
#ceiling_spr
#pivot_spr
EndEnumeration
TransparentSpriteColor(#PB_Default, RGB(255, 0, 255))
CreateSprite(#bob_spr, 32, 32)
StartDrawing(SpriteOutput(#bob_spr))
Box(0, 0, 32, 32, RGB(255, 0, 255))
Circle(16, 16, 15, RGB(253, 252, 3))
DrawingMode(#PB_2DDrawing_Outlined)
Circle(16, 16, 15, RGB(0, 0, 0))
StopDrawing()
CreateSprite(#pivot_spr, 10, 10)
StartDrawing(SpriteOutput(#pivot_spr))
Box(0, 0, 10, 10, RGB(255, 0, 255))
Circle(5, 5, 4, RGB(125, 125, 125))
DrawingMode(#PB_2DDrawing_Outlined)
Circle(5, 5, 4, RGB(0,0 , 0))
StopDrawing()
CreateSprite(#ceiling_spr,#ScreenW,2)
StartDrawing(SpriteOutput(#ceiling_spr))
Box(0,0,SpriteWidth(#ceiling_spr), SpriteHeight(#ceiling_spr), RGB(126, 126, 126))
StopDrawing()
Structure pendulum
length.d ; meters
constant.d ; -g/l
gravity.d ; m/s²
angle.d ; radians
velocity.d ; m/s
EndStructure
Procedure initPendulum(*pendulum.pendulum, length.d = 1.0, gravity.d = 9.81, initialAngle.d = #PI / 2)
With *pendulum
\length = length
\gravity = gravity
\angle = initialAngle
\constant = -gravity / length
\velocity = 0.0
EndWith
EndProcedure
Procedure updatePendulum(*pendulum.pendulum, deltaTime.d)
deltaTime = deltaTime / 1000.0 ;ms
Protected acceleration.d = *pendulum\constant * Sin(*pendulum\angle)
*pendulum\velocity + acceleration * deltaTime
*pendulum\angle + *pendulum\velocity * deltaTime
EndProcedure
Procedure drawBackground()
ClearScreen(RGB(190,190,190))
;draw ceiling
DisplaySprite(#ceiling_spr, 0, 47)
;draw pivot
DisplayTransparentSprite(#pivot_spr, 154,43) ;origin in upper-left
EndProcedure
Procedure drawPendulum(*pendulum.pendulum)
;draw rod
Protected x = *pendulum\length * 140 * Sin(*pendulum\angle) ;scale = 1 m/140 pixels
Protected y = *pendulum\length * 140 * Cos(*pendulum\angle)
StartDrawing(ScreenOutput())
LineXY(154 + 5,43 + 5, 154 + 5 + x, 43 + 5 + y) ;draw from pivot-center to bob-center, adjusting for origins
StopDrawing()
;draw bob
DisplayTransparentSprite(#bob_spr, 154 + 5 - 16 + x, 43 + 5 - 16 + y) ;adj for origin in upper-left
EndProcedure
Define pendulum.pendulum, event
initPendulum(pendulum)
drawPendulum(pendulum)
AddWindowTimer(0, 1, 50)
Repeat
event = WindowEvent()
Select event
Case #pb_event_timer
drawBackground()
Select EventTimer()
Case 1
updatePendulum(pendulum, 50)
drawPendulum(pendulum)
EndSelect
FlipBuffers()
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver

View file

@ -0,0 +1,59 @@
//
// example: solve ODE for pendulum
//
// we first define the first derivative function for the solver
dudt = function(t, u, p)
{
// t-> time
// u->[theta, dtheta/dt ]
// p-> g/L, parameter
rval = zeros(2,1);
rval[1] = u[2];
rval[2] = -p[1] * sin(u[1]);
return rval;
};
// now we solve the problem
// physical parameters
L = 5; // (m), the length of the arm of the pendulum
p = mks.g / L; // RLaB has a built-in list 'mks' which contains large number of physical constants and conversion factors
T0 = 2*const.pi*sqrt(L/mks.g); // approximate period of the pendulum
// initial conditions
theta0 = 30; // degrees, initial angle of deflection of pendulum
u0 = [theta0*const.pi/180, 0]; // RLaB has a built-in list 'const' of mathematical constants.
// times at which we want solution
t = [0:4:1/64] * T0; // solve for 4 approximate periods with at time points spaced at T0/64
// prepare ODEIV solver
optsode = <<>>;
optsode.eabs = 1e-6; // relative error for step size
optsode.erel = 1e-6; // absolute error for step size
optsode.delta_t = 1e-6; // maximum dt that code is allowed
optsode.stdout = stderr(); // open the text console and in it print the results of each step of calculation
optsode.imethod = 5; // use method No. 5 from the odeiv toolkit, Runge-Kutta 8th order Prince-Dormand method
//optsode.phase_space = 0; // the solver returns [t, u1(t), u2(t)] which is default behavior
optsode.phase_space = 1; // the solver returns [t, u1(t), u2(t), d(u1)/dt(t), d(u2)/dt]
// solver do my bidding
y = odeiv(dudt, p, t, u0, optsode);
// Make an animation. We choose to use 'pgplot' rather then 'gnuplot' interface because the former is
// faster and thus less cache-demanding, while the latter can be very cache-demanding (it may slow your
// linux system quite down if one sends lots of plots for gnuplot to plot).
plwins (1); // we will use one pgplot-window
plwin(1); // plot to pgplot-window No. 1; necessary if using more than one pgplot window
plimits (-L,L, -1.25*L, 0.25*L);
xlabel ("x-coordinate");
ylabel ("z-coordinate");
plegend ("Arm");
for (i in 1:y.nr)
{
// plot a line between the pivot point at (0,0) and the current position of the pendulum
arm_line = [0,0; L*sin(y[i;2]), -L*cos(y[i;2])]; // this is because theta is between the arm and the z-coordinate
plot (arm_line);
sleep (0.1); // sleep 0.1 seconds between plots
}

View file

@ -0,0 +1,36 @@
include c:\cxpl\codes; \intrinsic 'code' declarations
proc Ball(X0, Y0, R, C); \Draw a filled circle
int X0, Y0, R, C; \center coordinates, radius, color
int X, Y;
for Y:= -R to R do
for X:= -R to R do
if X*X + Y*Y <= R*R then Point(X+X0, Y+Y0, C);
def L = 2.0, \pendulum arm length (meters)
G = 9.81, \acceleration due to gravity (meters/second^2)
Pi = 3.14,
DT = 1.0/72.0; \delta time = screen refresh rate (seconds)
def X0=640/2, Y0=480/2; \anchor point = center coordinate
real S, V, A, T; \arc length, velocity, acceleration, theta angle
int X, Y; \ball coordinates
[SetVid($101); \set 640x480x8 graphic display mode
T:= Pi*0.75; V:= 0.0; \starting angle and velocity
S:= T*L;
repeat A:= -G*Sin(T);
V:= V + A*DT;
S:= S + V*DT;
T:= S/L;
X:= X0 + fix(L*100.0*Sin(T)); \100 scales to fit screen
Y:= Y0 + fix(L*100.0*Cos(T));
Move(X0, Y0); Line(X, Y, 7); \draw pendulum
Ball(X, Y, 10, $E\yellow\);
while port($3DA) & $08 do []; \wait for vertical retrace to go away
repeat until port($3DA) & $08; \wait for vertical retrace signal
Move(X0, Y0); Line(X, Y, 0); \erase pendulum
Ball(X, Y, 10, 0\black\);
until KeyHit; \keystroke terminates program
SetVid(3); \restore normal text screen
]