News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Drawing a circle

Started by LordAdef, January 21, 2018, 04:10:50 PM

Previous topic - Next topic

LordAdef

Hi guys,

First of all, I tried to do it on my own... But I never used FPU or anything except integers in masm.

I searched and found many possible examples here, But I sincerely need a straight algo so I can use it and learn from it.

I need to draw an Fuel gaude indicator.
I provide:

. the centre x , y coords
. the radius
. the angle (or rads, whatever)

So the algo can return the x , y coord for the given angle.

I know this is cold breakfast for all of you... I saw some JJ´s code that look quite clear but there were some MasmBasic there, I´m using Masm only.

The goal is to animate this nice Gauge pointer below:





Siekmanski

#1
PI_2 = 6.283185308      ;2*pi

Total_Steps = 360       ;Steps for a complete rotation
Degree = 45             

Z_rotation:
       s = sin( Degree / Total_Steps * PI_2 )
       c = cos( Degree / Total_Steps * PI_2 )

       x = 0.0
       y = -1.0 ; length of your gauge indicator.

       x_new = ( c * x ) - ( s * y )
       y_new = ( s * x ) + ( c * y )

       x_new = 0.7071
       y_new = -0.7071

axis:

          Y
          +

          |
          |
X- _______ +

          |
          |
          -

Notice that the Y value is negative 1.0.
This is because the origin of the screen you draw to is "left top" and not "left bottom"

Now you can translate both vectors of de gauge indicator to the position on the screen you want it to be.
So infact you rotate the vector at screen position 0,0 and than add the final screen x,y positions to it.

You only need to rotate one vector because the origin vector will always be 0,0


An example how to do the calculations ( not optimized )

.data
PI_2        real4 0.0
Total_Steps real4 360.0 ; full rotation
Rot_Angle   real4 45.0  ; in degrees
C_          real4 0.0
S_          real4 0.0


Needle_X    real4 0.0
Needle_Y    real4 -1.0

New_X       real4 0.0
New_Y       real4 0.0

.code

    fldpi
    fadd    st(0),st(0)
    fstp    PI_2

    fld     Rot_Angle
    fdiv    Total_Steps
    fmul    PI_2
    fsincos
    fstp    C_
    fstp    S_
   
    fld     Needle_X
    fmul    C_
    fld     Needle_Y
    fmul    S_
    fsubp   
    fstp    New_X

    fld     Needle_X
    fmul    S_
    fld     Needle_Y
    fmul    C_
    faddp   
    fstp    New_Y


Now you can draw a line between both vectors.

And because X is 0.0 you can simplify the calculations by not calculating the X rotation:

    fldpi
    fadd    st(0),st(0)
    fstp    PI_2

    fld     Rot_Angle
    fdiv    Total_Steps
    fmul    PI_2
    fsincos
    fstp    C_
    fstp    S_
   
    fld     Needle_Y
    fmul    S_
    fchs
    fstp    New_X
    fld     Needle_Y
    fmul    C_
    fstp    New_Y

Creative coders use backward thinking techniques as a strategy.

avcaballero

Since your app is not time critical, why don't use the GDI api for that? Since the center is always the same, you just need to calculate the extreme of the needle. If you need an example, tell us

Siekmanski

#3
This is a fast routine that calculates the screen coordinates for the Gauge indicator in integer values.

.data
RotationMagic real4 0.01745329252222222222222222222 ; 1/360 * 2*Pi
.code

CalculateGauge proc Xpos:DWORD,Ypos:DWORD,Radius:DWORD,Angle:DWORD
   
    fild    Angle ; in degrees
    fmul    RotationMagic
    fsincos

    fimul   Radius
    fchs
    fiadd   Ypos
    fistp   dword ptr [esp-8]
    fimul   Radius
    fiadd   Xpos
    fistp   dword ptr [esp-4]
    mov     eax,dword ptr [esp-4]   ; New_X
    mov     ecx,dword ptr [esp-8]   ; New_Y
    ret

CalculateGauge endp


    ; calculates the angle in 32 bit integer values.
    invoke  CalculateGauge,100,100,60,45 ; returns New_X in eax and New_Y in ecx

result is: 142,58

Now you can draw a line between (100,100) and (142,58)

Edit: a faster version
Creative coders use backward thinking techniques as a strategy.

LordAdef

Really thanks Marinus!!

It was an incredible time saver. I admit I had already spent a lot of time...  but handling the Maths, and the FPU new stuff was above my pay check.

Your proc will serve me as a way to study FPU, which I was doing reading masm32 help file. This practical example will help me a lot.


Caballero, thanks too! In fact, would you show me your alternative?  I'm sure there will be someone like me search for similar help.

I'll let you know as soon as the toy starts doing its thing!

daydreamer

bresenhams circle algorithm is maybe an alternative
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

LordAdef

I already inserted Marinus´s Algo, couldn´t resist.. not ready yet but it´s already working and showing with precision my Fuel level. Check it out:

http://masm32.com/board/index.php?topic=6200.msg73621#msg73621

Marinus, I took the freedom to repost your algo there, ok? Just to register the development in case someone in the future wanted to have a look (due credit given, of course).


Siekmanski

Creative coders use backward thinking techniques as a strategy.

FORTRANS

Hi,

   If you can live with limited precision, you might just make some
images of the gauge at different levels and copy the closest on to
the screen.  For instance, if 12.5% accuracy is adequate, make
nine images from zero to full.  ( 0.0, 0.125. 0.25, 0.375,... 1.0 )
That might allow a "prettier" looking gauge.  More accuracy will
require more images, so perhaps not an option for you?

Cheers,

Steve N.

avcaballero

> Caballero, thanks too! In fact, would you show me your alternative?  I'm sure there will be someone like me search for similar help.

If it can wait to this weekend, I will try to do anything  :biggrin:

avcaballero

Well, here is my little contribution to this subject. You can resize the window. Everything with GDI functions. Full masm32 source code.

felipe

Hey caballero that's a great contribution, thanks a lot!  :icon14: :icon14:

daydreamer

#12
Quote from: caballero on January 28, 2018, 05:53:13 AM
Well, here is my little contribution to this subject. You can resize the window. Everything with GDI functions. Full masm32 source code.
very nice Clock Caballero,would be nice to replace windows original Clock with :t
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

LordAdef

Thanks Caballero, nice contribution indeed!