Ellipse trouble
#1
Photo 
I want to make a program that creates dots in the shape of an ellipse.

So not knowing about the math involved I assumed it would be fairly simple.   Then I googled and youtubed and that didn't help much.   I did end up with a mild headache though.

There's a fancy formula that stands out from everything I've been learning, but I really don't know how to use it properly.   So I thought I'd ask here, in case anyone knows.

The formula is:


x2/a2 + y2/b2 = 1     ( x-squared over a-squared + y-squared over b-squared = 1)


It's been too long since I've worked with algebra so I'm just unsure of how to solve for x.    The "=1" part is not helping at all  Big Grin


I've learned the basic principles of the ellipse itself, and so here is an example I'm working with:


The ellipse is 200 wide (2a) by 100 tall  (2b)

a = 100
b = 50
located at position 0,0

I know the distance between the focal points is 86.603 in this case

If I could understand how to find a simple x,y point, I'm sure I'd be on my way to writing a program immediately.

The top center point in this case is x0, y50.   So I'm wondering what the x value is if y=48.   Or if y=46.   Or all the way to y=2.    

Cheers,
James
Reply
#2
James,

Solving the equation for x is the easy part:
x^2/a^2 + y^2/b^2 = 1
x^2/a^2 = 1 - y^2/b^2
x^2 = (1 - y^2/b^2 )*a^2
x = +sqr((1 - y^2/b^2 )*a^2)
and
x = -sqr((1 - y^2/b^2 )*a^2)
if I haven't made a mistake.

But you can use CIRCLE to draw ellipses.  Or, if you are into self-flagellation, there are algorithms using PSET.

Here is a start using CIRCLE (the ASPECT parameter!):

Code: (Select All)
Screen _NewImage(1024, 768, 256)
Cls 0, 15
Color 0, 15

Circle (512, 384), 200
Circle (512, 384), 100
Circle (512, 384), 200, 9, , , 2 ' blue
Circle (512, 384), 200, 10, , , .5 ' green
___________________________________________________________________________________
I am mostly grateful for the people who came before me.  Will the people after me be grateful for me?
Reply
#3
If you need tilted ones I have that too (https://staging.qb64phoenix.com/showthre...04#pid1204) here are filled ellipsii
Code: (Select All)
_Title "Fill Ellipse Demo" ' b+ 2022-08-23
Screen _NewImage(800, 600, 32)
_ScreenMove 200, 50
Do
    fEllipse Rnd * _Width, Rnd * _Height, Rnd * 100, Rnd * 100, _RGB32(Rnd * 255, Rnd * 255, Rnd * 255, Rnd * 255)
    _Limit 30
Loop


Sub fEllipse (CX As Long, CY As Long, xr As Long, yr As Long, C As _Unsigned Long)
    If xr = 0 Or yr = 0 Then Exit Sub
    Dim h2 As _Integer64, w2 As _Integer64, h2w2 As _Integer64
    Dim x As Long, y As Long
    w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
    Line (CX - xr, CY)-(CX + xr, CY), C, BF
    Do While y < yr
        y = y + 1
        x = Sqr((h2w2 - y * y * w2) \ h2)
        Line (CX - x, CY + y)-(CX + x, CY + y), C, BF
        Line (CX - x, CY - y)-(CX + x, CY - y), C, BF
    Loop
End Sub
xr = xradius yr = yradius don't have to guess with fractions that Circle uses.
b = b + ...
Reply
#4
my weak ellipse drawing for you if you don't want to use circle.  My pset method is missing something because I do not recall the math in that area where sqr() can't be called. Bplus is better here. The method using draw actually comes out decent enough.

Code: (Select All)
'badellipse
Screen _NewImage(800, 600, 256)
'pset ellipse
ex = 200
ey = 300
a = 160
b = 50
For y = 0 To 100 Step 0.2
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2 'have to calculate outside sqr() to avoid math error
    If n > 0 Then
        x = Sqr(n)
        PSet (x + ex, y + ey), 15
        PSet (ex - x, y + ey), 15
        PSet (ex - x, ey - y), 15
        PSet (x + ex, ey - y), 15
    End If
Next y


'draw ellipse
ex = 600
ey = 300
a = 160
b = 50
Draw "bm" + Str$(ex) + "," + Str$(ey)
For y = 0 To 100 Step 1 'using larger steps than earlier because draw is slower but laying down line segments
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y < 1 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(x + ex) + "," + Str$(y + ey)
    End If
Next y
For y = 100 To 0 Step -1
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y > 99 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(ex - x) + "," + Str$(y + ey)
    End If
Next y
For y = 0 To 100 Step 1
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y < 0 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(ex - x) + "," + Str$(ey - y)
    End If
Next y
For y = 100 To 0 Step -1
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y > 99 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(x + ex) + "," + Str$(ey - y)
    End If
Next y
Reply
#5
(08-23-2022, 04:07 PM)dcromley Wrote: James,

Solving the equation for x is the easy part:
x^2/a^2 + y^2/b^2 = 1
x^2/a^2 = 1 - y^2/b^2
x^2 = (1 - y^2/b^2 )*a^2
x = +sqr((1 - y^2/b^2 )*a^2)
and
x = -sqr((1 - y^2/b^2 )*a^2)
if I haven't made a mistake.

But you can use CIRCLE to draw ellipses.  Or, if you are into self-flagellation, there are algorithms using PSET.

Here is a start using CIRCLE (the ASPECT parameter!):

Thank you.   This is great info.   Nice to finally see the formula exactly as I would need to use it!

I've seen those extra commas before somewhere and had no clue what they meant.   I'll look into this more, assuming this is what you mean by ASPECT.
Reply
#6
(08-23-2022, 04:54 PM)bplus Wrote: If you need tilted ones I have that too (https://staging.qb64phoenix.com/showthre...04#pid1204)  here are filled ellipsii
Code: (Select All)
_Title "Fill Ellipse Demo" ' b+ 2022-08-23
Screen _NewImage(800, 600, 32)
_ScreenMove 200, 50
Do
    fEllipse Rnd * _Width, Rnd * _Height, Rnd * 100, Rnd * 100, _RGB32(Rnd * 255, Rnd * 255, Rnd * 255, Rnd * 255)
    _Limit 30
Loop


Sub fEllipse (CX As Long, CY As Long, xr As Long, yr As Long, C As _Unsigned Long)
    If xr = 0 Or yr = 0 Then Exit Sub
    Dim h2 As _Integer64, w2 As _Integer64, h2w2 As _Integer64
    Dim x As Long, y As Long
    w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
    Line (CX - xr, CY)-(CX + xr, CY), C, BF
    Do While y < yr
        y = y + 1
        x = Sqr((h2w2 - y * y * w2) \ h2)
        Line (CX - x, CY + y)-(CX + x, CY + y), C, BF
        Line (CX - x, CY - y)-(CX + x, CY - y), C, BF
    Loop
End Sub
xr = xradius  yr = yradius don't have to guess with fractions that Circle uses.

Amazing....thank you
Reply
#7
(08-23-2022, 05:37 PM)James D Jarvis Wrote: my weak ellipse drawing for you if you don't want to use circle.  My pset method is missing something because I do not recall the math in that area where sqr() can't be called. Bplus is better here. The method using draw actually comes out decent enough.

Code: (Select All)
'badellipse
Screen _NewImage(800, 600, 256)
'pset ellipse
ex = 200
ey = 300
a = 160
b = 50
For y = 0 To 100 Step 0.2
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2 'have to calculate outside sqr() to avoid math error
    If n > 0 Then
        x = Sqr(n)
        PSet (x + ex, y + ey), 15
        PSet (ex - x, y + ey), 15
        PSet (ex - x, ey - y), 15
        PSet (x + ex, ey - y), 15
    End If
Next y


'draw ellipse
ex = 600
ey = 300
a = 160
b = 50
Draw "bm" + Str$(ex) + "," + Str$(ey)
For y = 0 To 100 Step 1 'using larger steps than earlier because draw is slower but laying down line segments
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y < 1 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(x + ex) + "," + Str$(y + ey)
    End If
Next y
For y = 100 To 0 Step -1
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y > 99 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(ex - x) + "," + Str$(y + ey)
    End If
Next y
For y = 0 To 100 Step 1
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y < 0 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(ex - x) + "," + Str$(ey - y)
    End If
Next y
For y = 100 To 0 Step -1
    n = (1 - y ^ 2 / b ^ 2) * a ^ 2
    If n > 0 Then
        x = Sqr(n)
        If y > 99 Then Draw "bm" + Str$(x + ex) + "," + Str$(y + ey)
        Draw "m" + Str$(x + ex) + "," + Str$(ey - y)
    End If
Next y

This is similar to what I was trying to achieve.   I haven't used the "draw" command yet - I'll read up on this.   Thank you.
Reply
#8
Here is tilted ellipsii with some fun coloring:
Code: (Select All)
Screen _NewImage(800, 600, 32)
_ScreenMove 250, 50
Dim Shared pR, pG, pB, pA, cN

Do
    lc = lc + 1
    If lc = 100 Then Cls: lc = 0
    resetPlasma
    cx = Rnd * _Width: cy = Rnd * _Height: a = Rnd * 100: b = Rnd * 100: ang = _Pi(Rnd * 2)
    For i = 0 To 1 Step .0005
        EllipseTilt cx, cy, i * a, i * b, ang, Plasma~&
    Next
    _Limit 30
Loop Until _KeyDown(27)


Function Plasma~& () ' this creates a wonderful sequence of colors  cN, pR, pG, pB are Shared
    cN = cN + .1 ' might want to keep cN single and increment by .5, .1.. depending on needs
    Plasma~& = _RGB32(127 + 127 * Sin(pR * cN), 127 + 127 * Sin(pG * cN), 127 + 127 * Sin(pB * cN), 3)
End Function

Sub resetPlasma ' this sets up to use changePlasma pR, pG, pB are Shared
    pR = Rnd ^ 2: pG = Rnd ^ 2: pB = Rnd ^ 2: pA = Rnd * 100: cN = 0
End Sub


'=========================================================================================================== drawing
'thanks STxAxTIC from Toolbox
Sub EllipseTilt (CX, CY, a, b, ang, C As _Unsigned Long)
    Dim k, i, j
    '  CX = center x coordinate
    '  CY = center y coordinate
    '   a = semimajor axis  major radius
    '   b = semiminor axis  minor radius
    ' ang = clockwise orientation of semimajor axis in radians (0 default)
    '   C = fill color
    For k = 0 To 6.283185307179586 Step .025 'not sure about the stepper it should depend on a and b
        i = a * Cos(k) * Cos(ang) + b * Sin(k) * Sin(ang)
        j = -a * Cos(k) * Sin(ang) + b * Sin(k) * Cos(ang)
        i = i + CX
        j = -j + CY
        If k <> 0 Then
            Line -(i, j), C
        Else
            PSet (i, j), C
        End If
    Next
End Sub

Hmm... looks like imperfect overlap occasionally.

Update: Overlap problem fixed, I think.
b = b + ...
Reply
#9
Well the ellipse formula works easily, so I copied and pasted it and ended up making a cat face out of all ellipses.   

Code: (Select All)
'ellipse


Randomize Timer

Dim scx, scy As Integer



scx = 800
scy = 600

Screen _NewImage(scx, scy, 32)


Const PI = 3.141592654#

Dim c0(100) As Long

Dim x, h, r
Dim xx, yy, x1, y1
Dim a, b, c, d, y, xx1, xx2, cc


c0(0) = _RGB(0, 0, 0) 'black
c0(1) = _RGB(255, 255, 255) 'white
c0(2) = _RGB(255, 0, 0) 'red
c0(3) = _RGB(0, 255, 0) 'green
c0(4) = _RGB(0, 0, 255) 'blue
c0(5) = _RGB(115, 135, 0) 'yellow
c0(6) = _RGB(0, 255, 255) 'cyan
c0(7) = _RGB(85, 50, 50) 'magenta
c0(8) = _RGB(200, 150, 150)
c0(9) = _RGB(0, 125, 125)
c0(10) = _RGB(185, 185, 185)
c0(11) = _RGB(55, 255, 55)
c0(12) = _RGB(55, 55, 55)
c0(13) = _RGB(44, 44, 44)
c0(14) = _RGB(66, 66, 66)


Cls


'A = (Sin(x * (PI / 180)))
'B = (Cos(x * (PI / 180)))
'C = (Tan(x * (PI / 180)))






Cls



'ear left
a = 50
b = 120
yy = 210
mm = 260
For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (mm - x, yy - y)-(mm + x, yy - y), c0(13)
    Line (mm - x, yy + y)-(mm + x, yy + y), c0(13)
Next j

'ear right
a = 50
b = 120
yy = 210
mm = 540
For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (mm - x, yy - y)-(mm + x, yy - y), c0(13)
    Line (mm - x, yy + y)-(mm + x, yy + y), c0(13)
Next j


'ear left inner
a = 40
b = 110
yy = 210
mm = 260
For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (mm - x, yy - y)-(mm + x, yy - y), c0(14)
    Line (mm - x, yy + y)-(mm + x, yy + y), c0(14)
Next j

'ear right inner
a = 40
b = 110
yy = 210
mm = 540
For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (mm - x, yy - y)-(mm + x, yy - y), c0(14)
    Line (mm - x, yy + y)-(mm + x, yy + y), c0(14)
Next j





'face

xx = scx / 2
yy = 300

a = 200
b = 140

For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (xx - x, yy - y)-(xx + x, yy - y), c0(12)
    Line (xx - x, yy + y)-(xx + x, yy + y), c0(12)
Next j





'chin
a = 40
b = 30
yy = 390

For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (xx - x, yy - y)-(xx + x, yy - y), c0(13)
    Line (xx - x, yy + y)-(xx + x, yy + y), c0(13)
Next j


'mouth left
a = 40
b = 30
yy = 370
mm = 360
For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (mm - x, yy - y)-(mm + x, yy - y), c0(14)
    Line (mm - x, yy + y)-(mm + x, yy + y), c0(14)
Next j

'mouth right
a = 40
b = 30
yy = 370
mm = 440
For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (mm - x, yy - y)-(mm + x, yy - y), c0(14)
    Line (mm - x, yy + y)-(mm + x, yy + y), c0(14)
Next j



'upper nose
a = 30
b = 35
yy = 333

For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (xx - x, yy - y)-(xx + x, yy - y), c0(13)
    Line (xx - x, yy + y)-(xx + x, yy + y), c0(13)
Next j



'nose
a = 30
b = 10
yy = 350

For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (xx - x, yy - y)-(xx + x, yy - y), c0(7)
    Line (xx - x, yy + y)-(xx + x, yy + y), c0(7)
Next j


'nose
a = 15
b = 10
yy = 360

For j = 0 To b
    y = b - j
    x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
    Line (xx - x, yy - y)-(xx + x, yy - y), c0(7)
    Line (xx - x, yy + y)-(xx + x, yy + y), c0(7)
Next j





'==================================================================

'==================================================================

'==================================================================

'==================================================================

'==================================================================

'==================================================================



'animate blinking


a = 50 'eye white width
b = 25 'eye white height
c = 25 'eye colour height
d = 7 'eye colour width


xx1 = 300
yy1 = 280

xx2 = 500
yy2 = 120


cc = 13

Dim v, v2, v3, v4 As Long




Do


    'blink down
    For j = 0 To b
        y = b - j
        x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
        Line (xx1 - x, yy1 - y)-(xx1 + x, yy1 - y), c0(cc)
        Line (xx1 - x, yy1 + y)-(xx1 + x, yy1 + y), c0(cc)
        Line (xx2 - x, yy1 - y)-(xx2 + x, yy1 - y), c0(cc)
        Line (xx2 - x, yy1 + y)-(xx2 + x, yy1 + y), c0(cc)
        For jj = 1 To 100000
        Next jj
    Next j

    For jj = 1 To 1000000
        For jjj = 1 To 30
        Next jjj
    Next jj



    'open eyes
    For j = b To 0 Step -1
        y = b - j
        x = Sqr((1 - y ^ 2 / b ^ 2) * a ^ 2)
        Line (xx1 - x, yy1 - y)-(xx1 + x, yy1 - y), c0(5)
        Line (xx1 - x, yy1 + y)-(xx1 + x, yy1 + y), c0(5)
        Line (xx2 - x, yy1 - y)-(xx2 + x, yy1 - y), c0(5)
        Line (xx2 - x, yy1 + y)-(xx2 + x, yy1 + y), c0(5)
        yc = b - j
        x = Sqr((1 - yc ^ 2 / c ^ 2) * d ^ 2)
        Line (xx1 - x, yy1 - yc)-(xx1 + x, yy1 - yc), c0(0)
        Line (xx1 - x, yy1 + yc)-(xx1 + x, yy1 + yc), c0(0)
        Line (xx2 - x, yy1 - yc)-(xx2 + x, yy1 - yc), c0(0)
        Line (xx2 - x, yy1 + yc)-(xx2 + x, yy1 + yc), c0(0)
        For jj = 1 To 200000
        Next jj
    Next j


    v = (Rnd * 10) + .2
    _Delay v
Loop







End
Reply
#10
This thread reminded me of the old .rip ellipse project. If I recall correctly, Mark, Steve and Bill, and I came up with the gold standard for ellipse drawing speed. It was fun to blow Bill's mind by putting SQR in the formula in such a way it made it faster. Of course, in his defense, Bill's only a theoretical physicist!

Pete Big Grin
Reply




Users browsing this thread: 5 Guest(s)