Computer Science Canada

[source code] Modeling a wave

Author:  Tony [ Mon Apr 21, 2003 11:01 pm ]
Post subject:  [source code] Modeling a wave

Inspired by my physics class and waves unit, I've came up with a short procedure for modeling waves. I will probably be making some apps using this procedure in the future.

code:

procedure drawWave(wav,amp:real, move:int)

%wav - wave length in pixels :real value
%amp - wave amplitude in pixels :real value
%move - displacement of wave in pixels horizontaly :int value

for i:1 - move ..maxx -move
drawline(i+move,round(cos(i/wav*6.3)*amp)+round(maxy/2),i+1+move,round(cos((i+1)/wav*6.3)*amp)+round(maxy/2),black)
end for

end drawWave


In reality its just a cosine graph, modified to allow for accurate wave modeling.

This in fact is how all graphs should be done in programming. If you're drawing dots for each X value, you'll have a lot of blank spaces unless your line is perfectly horizontal (or at 45 angle), so you have to draw a line instead. From current point to the next one.

Parameters' explanations are commented inside the procedure. Here's a sample of how you call it
code:

drawWave(25,20,0)

That will draw you a wave with 25 pixel wavelength and 20 pixel amplitude. It is in its original position (moved 0).

To find frequency you need to know the time. The frequency is maxx/waveLength/time(in seconds).

Author:  Catalyst [ Mon Apr 21, 2003 11:36 pm ]
Post subject: 

i modded your proc a bit so its friendlier with real numbers (i dont like ints) also add a couple more params and made a little prog

code:

View.Set ("graphics:640;640,position:300;300,offscreenonly,nobuttonbar")
var clr : int
for i : 1 .. 256
    clr := RGB.AddColor (1, i / 256, 0)
end for
procedure drawWave (x, y : real, width : real, wav, amp : real, move : real)

    var count : real := (x - move)
    var Y : real
    loop
        count += 1
        Y := round ((cos (count / wav * 6.3) * amp) + y)
        drawline (round (count + move), round ((cos (count / wav * 6.3) * amp) + y), round (count + 1 + move), round ((cos ((count + 1) / wav * 6.3) * amp) + y), round (((Y / maxy) * 255) + 255))
        exit when count >= (x + width)
    end loop

end drawWave

var count : real := 10
loop
    count += 0.1
    drawWave (0, maxy / 2, maxx, count / 100, count / 1, round (count))
    View.Update
    drawfillbox (0, 0, maxx, maxy, 7)
end loop

Author:  Martin [ Tue Apr 22, 2003 8:33 pm ]
Post subject: 

Lookin good guys

Author:  rizzix [ Sun May 25, 2003 7:57 pm ]
Post subject: 

heh,
guys i've come up with an easier solution!
you need to know how to use OO side of turing though...

i use a simple convention (cuz i'm kinda limited by turing!!),
used all caps for procedure, and all lower-case for functions
take note of the equation: y = a(func(k(x - d))) + c
where func = (sine, cos or tan)

to set the amplitude u call wave_object->A(value)
to get the amplitude u call something := wave_object->a

to draw the wave u call wave_object->drawWave(border : int, colour : int)

to change the scale of degree-to-pixel ratio (default is 1:1 i think)
u call wave_object->SCALE(value : real)

attached is the wave library file.
have fun!!!

o btw: dont use the Tangent Wave i haven't completed it yet!
but if u insist u can (just remember it gets undefined at 90 degrees)

Author:  rizzix [ Sun May 25, 2003 8:00 pm ]
Post subject:  hmmm.....

how do i know i attached the file?
i'm new here!

thanks..

Author:  Catalyst [ Sun May 25, 2003 8:06 pm ]
Post subject: 

u cant attach files in the source code area

Author:  Catalyst [ Sun May 25, 2003 8:07 pm ]
Post subject: 

put it in submissions

Author:  rizzix [ Sun May 25, 2003 8:09 pm ]
Post subject: 

ok thx


but this should work right?...
code:


% y = a(func(k(x - d))) + c
    class TrigWave
        export a, A, k, K, d, D, c, C,
            ix, IX, iy, IY, x1, X1, x2, X2,
            drawWave, scale, SCALE,
            LEFT, RIGHT, UP, DOWN, lambda
        var _a, _k, _d, _c : real   % a, k, d, c: of equation
        var _ix, _iy : int          % initial: x and y
        var _x1, _x2 : int          % range/period
        var _scale : real

        _scale := 1
        _a := 10
        _k := 1
        _d := 0
        _c := 0
        _x1 := round (-180 * _scale)
        _x2 := round (180 * _scale)
        _ix := round (maxx / 2)
        _iy := round (maxy / 2)

        % set/get a
        fcn a : real
            result (_a / 10) / _scale
        end a
        proc A (_A : real)
            _a := (_A * 10) * _scale
        end A

        % set/get k
        fcn k : real
            result _k * _scale
        end k
        proc K (_K : real)
            _k := _K / _scale
        end K

        % set/get d
        fcn d : real
            result _d / _scale
        end d
        proc D (_D : real)
            _d := _D * _scale
        end D

        % set/get c
        fcn c : real
            result _c / _scale
        end c
        proc C (_C : real)
            _c := _C * _scale
        end C

        % set/get ix
        fcn ix : int
            result _ix
        end ix
        proc IX (_IX : int)
            _ix := _IX
        end IX

        % set/get iy
        fcn iy : int
            result _iy
        end iy
        proc IY (_IY : int)
            _iy := _IY
        end IY

        % set/get x1
        fcn x1 : int
            result round (_x1 / _scale)
        end x1
        proc X1 (_X1 : int)
            _x1 := round (_X1 * _scale)
        end X1

        % set/get x2
        fcn x2 : int
            result round (_x2 / _scale)
        end x2
        proc X2 (_X2 : int)
            _x2 := round (_X2 * _scale)
        end X2

        % get lambda
        fcn lambda : real
            result x2 - x1
        end lambda

        %set/get scale
        fcn scale : real
            result _scale
        end scale
        proc SCALE (_SCALE : real)
            var old_scale : real := scale
            _scale := _SCALE
            A ((_a / 10) / old_scale)
            K (_k / old_scale)
            D (_d / old_scale)
            C (_c / old_scale)
            X1 (round (_x1 / old_scale))
            X2 (round (_x2 / old_scale))
        end SCALE

        % translate left x units
        proc LEFT (x : real)
            D (d - x)
        end LEFT

        % translate right x units
        proc RIGHT (x : real)
            D (d + x)
        end RIGHT

        % translate up x units
        proc UP (x : real)
            C (c + x)
        end UP

        % translate down x units
        proc DOWN (x : real)
            C (c - x)
        end DOWN

        % draw the wave
        deferred proc drawWave (border_width : real, colr : int)
    end TrigWave


    class SineWave
        inherit TrigWave
        body proc drawWave (border_width : real, colr : int)
            for x : _x1 .. _x2
                drawline (x + ix, round (((_a - border_width) * sind (_k * (x - _d))) + _c) + iy, x + ix, round ((_a * sind (_k * (x - _d - 1))) + _c) + iy, colr)
            end for
        end drawWave
    end SineWave


    class CosineWave
        inherit TrigWave
        body proc drawWave (border_width : real, colr : int)
            for x : _x1 .. _x2
                drawline (x + ix, round (((_a - border_width) * cosd (_k * (x - _d))) + _c) + iy, x + ix, round ((_a * cosd (_k * (x - _d - 1))) + _c) + iy, colr)
            end for
        end drawWave
    end CosineWave


    class TangentWave
        inherit TrigWave
        body proc drawWave (border_width : real, colr : int)
            for x : _x1 .. _x2
                drawline (x + ix, round (((_a - border_width) * cosd (_k * (x - _d))) + _c) + iy, x + ix, round ((_a * cosd (_k * (x - _d - 1))) + _c) + iy, colr)
            end for
        end drawWave
    end TangentWave


Author:  rizzix [ Sun May 25, 2003 8:14 pm ]
Post subject: 

here's an example using it!

code:

    View.Set ("graphics:800;600,offscreenonly,nobuttonbar")
    var wave2 : ^SineWave
    new wave2
    wave2 -> A(2)
    wave2 -> SCALE (2)
    var x : int := 1
    loop
        drawGrid (20)
        wave2 -> drawWave (5, blue)
        wave2 -> K (150 - x)
        wave2 -> C (150 - x)
        x += 1
        if x >= 360 then
            x := 0
        end if
        delay (20)
        View.Update
        cls
        wave2 -> D (360 - x)
        put "Scale:          ", "1 degree : ", wave2 -> scale, " pixel(s)"
        put "Range:          ", wave2 -> x1, ", ", wave2 -> x2
        put "Amplitude:      ", wave2 -> a, " x 10"
        put "horizontal exp: ", wave2 -> k
        put "Phase Shift:    ", wave2 -> d
        put "Vertical Shift: ", wave2 -> c
        put "Lambda:         ", wave2 -> lambda
    end loop
    free wave2

Author:  rizzix [ Sun May 25, 2003 8:17 pm ]
Post subject: 

oh eh almost forgot!

code:

proc drawGrid (inc : int)
        for x : 0 .. maxx by inc
            drawline (x, 0, x, maxy, grey)
        end for
        for y : 0 .. maxy by inc
            drawline (0, y, maxx, y, grey)
        end for
        drawline (0, round (maxy / 2), maxx, round (maxy / 2), red)
        drawline (round (maxx / 2), 0, round (maxx / 2), maxy, red)
end drawGrid


to draw a grid

Author:  Catalyst [ Sun May 25, 2003 10:18 pm ]
Post subject: 

cool Very Happy

Author:  Tony [ Sun May 25, 2003 11:16 pm ]
Post subject: 

looks awesome... just have attach wave parts together to make it solid Wink

Author:  PHP God [ Mon May 26, 2003 4:26 pm ]
Post subject: 

cool sine wave, how bout a sawtooth, or a square, or a sine-square. I'm into electronic music so this crap fascinates me.

Author:  rizzix [ Mon May 26, 2003 4:53 pm ]
Post subject: 

oh! ok np

simply subtract 1 from _d for y2 in the drawline proc

ex:

drawline (x + ix, round (((_a - border_width) * sind (_k * (x - _d))) + _c) + iy, x + ix, round ((_a * sind (_k * (x - _d - 1))) + _c) + iy, colr)

i fixed the code above...

Author:  rizzix [ Mon May 26, 2003 5:39 pm ]
Post subject: 

some additional info...

The cool thing about this class is that it defines default values for everything
so u can draw a wave by simply writing a few lines..

var wave : ^SineWave
new wave
wave -> drawWave(0, red)
free wave

By default:
the wave is drawn at centre of screen
but the default range is from -180 to 180
thus it technically begins drawing 180 pixels to the left of the middle

the scale of the wave is 1:1 (degrees : pixels)
setting the scale to 2 doubles the size, length etc, of the wave, yet display
the correct values for a,k,d,c,lambda etc..
you can also set it to a value < 1, letting u to display a wave of a larger length.

The amplitude of the wave is 10 pixels by default. So setting a to 2 results in an
amplitude of 20 pixels

you need to specify the thickness of the wave to be drawn, which by default fills the
wave from the inside to the very edge. Setting a negative value results in the opposite.

And yes the TangentWave is incomplete. Alas, i have no time, so if anyone is interested go ahead and extend the TrigWave class with a complete solution for the TangentWave. I'm currently working on a simple record-base DBMS solution for my ISP in school. Its a success, so far. I've eliminated all those gazillion bugs. It amazingly scalable and flexible.

I'll post the complete system here (its not extremely huge, as i said it is quite simple), but only after the ISP.

Author:  Tony [ Mon May 26, 2003 6:19 pm ]
Post subject: 

thats cool... And yeah, you should post your ISPs after you hand them in cuz some teachers think that everybody is stupid and just copies code of the net...

and if its big, plz upload in file

Author:  brazilian_princess [ Thu May 29, 2003 9:39 pm ]
Post subject: 

how do u run that??? *can u tell i suck at comps?*

Author:  krishon [ Thu May 29, 2003 9:46 pm ]
Post subject: 

lol, funny avatar

Author:  Homer_simpson [ Thu May 29, 2003 10:02 pm ]
Post subject: 

i think her avatar is really nice...

Author:  rizzix [ Fri May 30, 2003 3:07 pm ]
Post subject: 

brazilian_princess wrote:
how do u run that??? *can u tell i suck at comps?*


well copy all that code into a file...
make sure the loop is pasted towards the end of the file

the press F1


: