Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
08-23-2022, 03:29 PM
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
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
Posts: 65
Threads: 13
Joined: Apr 2022
Reputation:
5
08-23-2022, 04:07 PM
(This post was last modified: 08-23-2022, 04:11 PM by dcromley.
Edit Reason: note
)
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?
Posts: 2,700
Threads: 124
Joined: Apr 2022
Reputation:
134
08-23-2022, 04:54 PM
(This post was last modified: 08-23-2022, 04:56 PM by bplus.)
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 + ...
Posts: 545
Threads: 116
Joined: Apr 2022
Reputation:
39
08-23-2022, 05:37 PM
(This post was last modified: 08-23-2022, 05:38 PM by James D Jarvis.)
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
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
(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.
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
(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
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
(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.
Posts: 2,700
Threads: 124
Joined: Apr 2022
Reputation:
134
08-23-2022, 08:51 PM
(This post was last modified: 08-23-2022, 11:23 PM by bplus.)
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 + ...
Posts: 230
Threads: 25
Joined: Aug 2022
Reputation:
23
08-23-2022, 11:33 PM
(This post was last modified: 08-23-2022, 11:35 PM by james2464.)
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
Posts: 1,616
Threads: 157
Joined: Apr 2022
Reputation:
77
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
|