07-06-2023, 09:30 PM
This is a rough proof of concept sort of thing, but it does trace out an ellipse. By drawing the figure in quarters, I didn't deal with the headaches of line stepping, so I just used PSET. This makes the semi-major axis points spread out to leave gaps. Left & right mouse buttons drag the foci points, while the mouse wheel changes the base radius of the thing. Mostly vector math and distance formula, you won't find a single trig function. Which is why it's so damn long.
Code: (Select All)
'Vector Math Ellipse- OldMoses
TYPE V2
x AS SINGLE
y AS SINGLE
END TYPE
DIM AS V2 foci(1), fcomp(1), quad(3), origin, center, smaj, smin, smaj_n, smin_n, pt0, pt1, orth
SCREEN _NEWIMAGE(1024, 512, 32)
base_rad% = 100 ' starting circle base radius
origin.x = 0: origin.y = 0 '
foci(0).x = 200: foci(0).y = 150
foci(1).x = 300: foci(1).y = 200
DO
CLS
WHILE _MOUSEINPUT
base_rad% = base_rad% + _MOUSEWHEEL ' base circle size
WEND
IF _MOUSEBUTTON(1) THEN R2_Mouse foci(0) ' move foci(0) to left click position
IF _MOUSEBUTTON(2) THEN R2_Mouse foci(1) ' move foci(1) to right click position
total% = _SHL(base_rad%, 1)
R2_FCenter center, foci(0), foci(1) ' compute center from foci data
fcomp(0) = foci(0): R2_Add fcomp(0), center, -1 ' translate foci(0) relative to center as origin
fcomp(1) = foci(1): R2_Add fcomp(1), center, -1 ' translate foci(1) relative to center as origin
smaj = foci(0): R2_Add smaj, center, -1 ' subtract foci from center to obtain semi-major axis vector <smaj>
IF R2_Mag(smaj) = 0 THEN smaj.x = 1 ' convert <smaj> to i-hat if <smaj> becomes a zero vector
smin.x = smaj.y ' get minor axis orthogonal
smin.y = -smaj.x
FOR f% = 0 TO 1: CIRCLE (foci(f%).x, foci(f%).y), 3: NEXT f% ' draw marker circles at foci
CIRCLE (center.x, center.y), 2 ' draw marker circle at center
'CIRCLE (center.x, center.y), base_rad% ' draw base radius circle
FOR x% = 1 TO base_rad% ' work along the semimajor axis one point at a time
R2_Norm smaj, smaj, x% ' grow major axis vector
R2_Norm smaj_n, smaj, -R2_Mag(smaj) ' get its inverted twin
flag = 0: m% = 0
DO
m% = m% + 1 ' grow an orthogonal <smin> from that point
R2_Norm smin, smin, m%
pt0 = smaj: R2_Add pt0, smin, 1: R2_Add pt0, fcomp(0), -1 '
pt1 = smaj: R2_Add pt1, smin, 1: R2_Add pt1, fcomp(1), -1 '
IF R2_Mag(pt0) + R2_Mag(pt1) >= total% THEN ' until its magnitude equals the hypotenuse to both foci
R2_Norm smin_n, smin, -R2_Mag(smin) ' get its inverted twin
flag = -1
END IF
LOOP UNTIL flag
FOR curve% = 0 TO 3 ' plot point at each quadrant
IF curve% MOD 2 = 0 THEN orth = smin ELSE orth = smin_n
IF curve% > 1 THEN quad(curve%) = smaj_n ELSE quad(curve%) = smaj
R2_Add quad(curve%), orth, 1 ' add semi-major and semi-minor moves
R2_Add quad(curve%), center, 1 ' and add center position to result
PSET (quad(curve%).x, quad(curve%).y), &HFFFF00FF ' plot the point
NEXT curve%
NEXT x%
_DISPLAY
_LIMIT 30
LOOP UNTIL _KEYDOWN(27)
END
SUB R2_Add (re AS V2, se AS V2, m AS SINGLE) 'Add a scalar multiple of <se> to <re>
re.x = re.x + se.x * m
re.y = re.y + se.y * m
END SUB 'R2_Add
SUB R2_FCenter (re AS V2, f AS V2, f1 AS V2) 'find center <re> between two points <f> & <f1>
re = f1 ' set center to second foci initially
R2_Add re, f, -1 ' subtract first foci from center
R2_Add re, re, -.5 ' subtract 1/2 of center from center
R2_Add re, f, 1 ' add 1/2 center to first foci
END SUB 'R2_FCenter
FUNCTION R2_Mag! (v AS V2) 'Obtain magnitude of <v>
R2_Mag! = _HYPOT(v.x, v.y)
END FUNCTION 'R2_Mag!
SUB R2_Mouse (re AS V2)
re.x = _MOUSEX
re.y = _MOUSEY
END SUB 'R2_Mouse
SUB R2_Norm (re AS V2, v AS V2, scalar AS INTEGER) 'grow <v> to scalar length <re>
x! = v.x: y! = v.y
m! = _HYPOT(x!, y!)
IF m! = 0 THEN
re.x = 0: re.y = 0
ELSE
re.x = (x! / m!) * scalar
re.y = (y! / m!) * scalar
END IF
END SUB 'R2_Norm
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
sha_na_na_na_na_na_na_na_na_na: