DRAWPOLY demo.bas

Inspired by figosdev's graphic on another forum plus Johnno's request for poly and polygon (on another forum, but he probably meant irregular poly's and ploygons which we have already at SmallBASIC).

OK this turned out to also be a test of DRAWPOLY !


' DRAWPOLY demo.bas SmallBASIC 0.12.8 [B+=MGA] 2017-03-24

sub
regPoly(x, y, r, nPoints, angleOffset, fillTF)
' x, y are same as for circle,
' r is radius to points
' nPoints is the number of points,
' angleOffset = angle offset IN DEGREES, it will be converted to radians in sub
' this is to allow us to spin the polygon of n sides
local p_angle, rad_angle_offset, x1, x2, y1, y2, i, arr
p_angle = rad(360 / nPoints) : rad_angle_offset = rad(angleOffset)
dim arr(2*nPoints+1)
for i = 0 to nPoints
x1 = x + r * cos(i * p_angle + rad_angle_offset)
y1 = y + r * sin(i * p_angle + rad_angle_offset)
arr(2*i) = x1
arr(2*i + 1) = y1
next
if fillTF then drawpoly arr filled else drawpoly arr
end

cx = xmax/2 : cy = ymax/2 :
'test regPoly fillTF = 1, show spin potential
while asc(inkey) <> 32
cls
for i = 14 to 3 step -1
color i
regPoly cx, cy, i*20, i, a, 1
next
color 15
locate 1,1 : ? "Test regPoly TFfill = 1, press spacebar for next test."
showpage
a = a + 1
wend

'test regPoly fillTF = 0
d = 1 : m = .1 : n = 3
while 1
cls
xo = 0 : yo = 0 : a = 0
r1 = 20 : stepper = 60
for i = 0 to 720 step stepper
color rgb(255*i/720, 0, 128 - 128*i/720)
for j = 0 to 20
regPoly cx - 360 + xo , cy - 180 + yo, r1 + j, n, 0, 0
regPoly cx - 359 + xo , cy - 180 + yo, r1 + j, n, 0, 0 'dang the holes!
regPoly cx - 360 + xo , cy - 181 + yo, r1 + j, n, 0, 0 'dang the holes!
regPoly cx - 361 + xo , cy - 181 + yo, r1 + j, n, 0, 0 'dang the holes!
next
xo = xo + stepper * m : yo = yo + stepper * m/2
if i < 360 then r1 = r1 + stepper else r1 = r1 - stepper
next
showpage
m = m + .1 * d
if m > 1 then d = d * -1
if m <= 0 then m = .1 : d = 1 : n = n + 1
if n >= 15 then n = 3
wend



2nd EDIT, wanted to feature using DRAWPOLY, so I even changed title of code and this thread.

i freaking love this. its a basic program with little nods to fig in it :)

obviously im going to have to try running this.

edit:

as usual, youre a wizard, mark.

Drawpoly is a great addition. Fill is really fast, even on a slow machine. Actually-useful code!

SB can do any non-crossing poly, no restriction of outside-concave angles, like Star of David?

Good Demo MGA, easy to read and puts lots on the screen! - Ted

Yes MGA, that Star Maker type with the spikes is the kind I was wondering about. I do still like having the manual polygon method too.

Here is what I came up with, using the MGA & Figosdev routine.


' MGA DRAWPOLY subroutine, modified for Spike Stars.
' mod by Ted Clayton 2017/01/25
'
' Spike Stars have an inner-ring polygon,
' and an outer ring that's offset, for Spikes.
' But DrawPoly follows point-by-point,
' so Spike Stars are made by zig-zagging.
'
Initialize ' variables, constants
'
' auto-menu
FOR nSpikes = 3 TO 8 ' We have Stars with 3 to 8 Spikes.
CLS
? "Star with ";nSpikes;" Spikes"
? "#";nSpikes;" of 6"
? "Any key to continue"
? "==================="
SpikesOffset ' straighten stars, by turning them
SpikePoly xc, yc, ri, ro, nSpikes ' calculate vertexes
Wireframe ' connect circled vertexes with lines
FillStar ' do Fill the convex-concave Stars
? "Any key for next Star"
PAUSE ' next Star
NEXT I
? "Finis":END
'
SUB SpikePoly(xc, yc, ri, ro, nSpikes)
' xc, yc are the poly center
' ri is radius of inner points-course
' ro is radius of outer points-course
' nSpikes is the number of star-Spikes
' fillTF for FILL - if zero none, else DO
'local xc, xc, ri, ro, y1, y2, pi, po, arr
'
DIM arr(2 * 2 * nSpikes + 3) ' store vertex values
p_angle = rad(360 / (nSpikes * 2)) ' find angles for Spikes
rad_angle_offset = rad(angleOffset) ' turn-angle, to straighten
'
FOR p = 0 TO nSpikes * 2 + 1 STEP 2 ' do 2 points each loop
xi = xc + ri * cos(p * p_angle + rad_angle_offset) ' do an inner point i
yi = yc + ri * sin(p * p_angle + rad_angle_offset)
xo = xc + ro * cos((p + 1) * p_angle + rad_angle_offset) ' do an outer o
yo = yc + ro * sin((p + 1) * p_angle + rad_angle_offset)
'
arr(2*p + 0) = xi ' save the xi and yi for inner
arr(2*p + 1) = yi
arr(2*p + 2) = xo ' save the xo and yo for outer
arr(2*p + 3) = yo
' 4 DRAWPOLY array values, each loop-pass
NEXT p
END
'
SUB Wireframe
' circle vertexes, and lines from Center
? nSpikes;"-Spike Star Wireframe"
CIRCLE xc, yc, 2, 1, 7
FOR p = 0 TO 2 * 2 * nSpikes + 1 STEP 2 ' inside skeleton
circle arr(p),arr(p+1),2, 1, 7 ' circle vertexes
LINE xc, yc, arr(p),arr(p+1), 7 ' connect vertexes
NEXT p
PAUSE
END
'
SUB FillStar
? "Draw the Star-polygon border"
DRAWPOLY arr COLOR 9 ' border only
PAUSE
? "Color-Fill the polygon solid"
DRAWPOLY arr color 9 filled ' fill all
PAUSE
? "Put the Wireframe on the Fill"
Wireframe ' re-draw wireframe on Fill
END
'
SUB Initialize
' db = 1
xc = INT(XMAX/2) + 50
yc = INT(YMAX/2)
ri = 40
ro = 210
nSpikes = 0
angleOffset = 0
END
'
SUB SpikesOffset
' use angleOffset to straighten Stars
SELECT CASE nSpikes
CASE 3 : angleOffset = -30
CASE 4 : angleOffset = -45
CASE 5 : angleOffset = 18
CASE 6 : angleOffset = 0
CASE 7 : angleOffset = -12.6
CASE 8 : angleOffset = 23
CASE ELSE
? "Star with ";nSpikes;" Spikes, not ready."
END SELECT
END
'
' ==========
' debug code, after arr-FOR
'
'?"LOOP";" p=";p;" xc=";xc;" yc=";yc;" ri=";ri;" ro=";ro;" p-angle=";p_angle
'?"xi=";xi;" yi=";yi;" xo=";xo;" yo=";yo;
'?" cos(p * p_angle)=";cos(p * p_angle);" sin(p * p_angle)=";sin(p * p_angle):pause
'
'for i= 0 to (2 * 2 * nSpikes + 1)
' print i;" - ";arr(i)
' next i
'
' ==========
' debug code, bottom of Initialize
'
' ?"INIT:";" xc=";xc;" yc=";yc;" ri=";ri;" ro=";ro;" xmax=";xmax;" ymax=";ymax
'
' end debug code
' ==========

So you have Star Maker working with DRAWPOLY, nice specially doing fills! I like the wire frame, not sure why it's needed but looks neat!
When loading the arr (for DRAWPOLY) with points, it looks like you do in out, in out,... start with in at first point and end with out as last point in arr. That's one thing I couldn't figure out with my early try with DRAWPOLY, whether I had to repeat the first point at the end or not. In regPoly, I did have to repeat the start point at the end.

"' mod by Ted Clayton 2017/01/25 "
Where is this date coming from?

"Here is what I came up with, using the MGA & Figosdev routine. "
What of figosdev's routine did you use? He is coding in his own fig language, who can get anything from that?
I was inspired by snapshot of his cool graphic.

You commented out all the local variables? Originally the angleOffset parameter (which you have removed) was for turning the star(s) points for moving picture show. What the heck is SpikesOffset sub for?

What the heck happened to the font at this forum??????

Spiked stars have been a favorite for a long time! Wiki Stellation has pics, and shows a different way to make them.

That we have to explicitly make the first point, also be the last point, to close & complete a polygon, stumped me with DRAWPOLY. That was one of several secrets your routine showed me. (Figosdev is hereby booted upstairs from Credits, to Inspiration! ;)

Wireframe started, because my first intact 3-spike star, with 3 inner and 3 outer points, rendered as a perfect triangle with only 3 points showing. Wut? It happened, that I chose the ratio of inner and outer poly-radii, 50 & 100, that puts the outer spike-tip exactly on the line between the inner poly-points. Debug.

But also there was and is the thought, of applying an old shading-technique to these stellations. One side of a spike is shaded lighter, the other darker. It gives a faux base-relief effect. The overall spike-star is all divided up into the exactly-correct triangle-subdivisions for shading, by drawing a line from the Center, to each of the inner and outer points. And wireframe does look nice.

Some clunky FILL code, especially for true polygons, won't work on internally convex figures, like spike-stars. All the interior angles have to be under 180, or really 120. Since I had not been able to get DRAWPOLY to draw me a poly, I didn't know. (So-called clunk-FILL is faster, and if all figures are divided into triangle-meshes, they are all concave. Gamerz secret.)

I kinda lost sight of the fact that this is supposed to be a callable routine, in the process of solving problems with the double-layer poly method. Got sloppy. What I did here, needs some cleaning up to return it to a proper SUB. It could include more Generalization, and angleOffset values can be auto-calculated (I was doing it on my fingers), to make each or any type of poly render with the right orientation (DRAWPOLY starts from the same point for all figures, and most come up crooked by default.)

I do use angleOffset, to set rad_angle_offset, which then turns each type of star the right amount to make it render nicely-aligned on-screen. My SpikesOffset SUB assigns a custom angleOffset value to make each star-type sit-pretty. SpikesOffset is more like StarOffset, should be renamed. Your angleOffset is meant for rotation or animation, and my use of it is only for static-alignment, so I should use a different name, keep angleOffset freed up for where you are going with it.

Great project - Thanks!

Aha! Shading and coloring use with wire frame, outstanding idea! hmm... can that be built into one routine, maybe not, so maybe create a sort of drawstring for each star in use? maybe updating it's current angle? maybe making Star Maker a function that returns the Star's array for further use in program...

Ted, I was reviewing your code late last night after full day with One handed clock and TriQuad so it was only scan. I was writing without full understanding how everything fit together. Later I realized you might want all your stars pointing North and were attempting to adjust each star by nPoints. Do you know? 0 degrees or radians from center of screen is due East, which is what all star points are aligned to. If you want all stars aligned to due North use another offset of -90 degrees or -pi/2 in the Star maker routine in the SIN and COS calculations, so they all start from North... but that's starting Out, In, Out, in... hmm.... does it matter starting In or Out first?... if they all start due South with In Out In Out, that should put the points at due North when an odd number... but evens...? Well, I will play with it today when I see more fully how you got DRAWPOLY working. Using DRAWPOLY's fill even if break down to all triangles is still better than carrying a bulky handmade triangle fill routine in a program.

Yes, and all the stars could be built (and filled independently) with a bunch of triangles with the center point in common.

Oh yeah I know, MGA. I confused March with January, yesterday. 8)

I think you're right, that starting with an outer spike-tip, and turning them all -90, seems like it will properly orient all the different stars. That's a lot better than collecting fudge-angles. The alignment-key, is to have one spike pointing straight up. I thought about whether to start from the inner or the outer course, and couldn't see a difference. Making everybody go North will tidy it up good!

As it stands, I suspect the Loop is calculating an extra point, past the First point it needs to return to, to complete the Poly. Going normal-poly next-next-next, it can return precisely to the start-point. But going In-Out, or now Out-In, in pairs, I don't see a way to land on the Start point and stop right there. Not nicely. There is a second duplicate, after 'homing' on Start, I think. Didn't blow up anything ... but I'll scope this out.

I will make a closer inspection of the Star Maker code, see how it's handling things; what might help here.

As for sub-dividing these stellations into triangles, either just for wireframing or to go on with shading, we have two of the points for each triangle in-hand, every time we make a wire-Line. The 3rd point is either the next one in the ARRay, or the previous one. All have the Center in common. Just right on around.

I have some other tending-to, but will get right back to this.

"He is coding in his own fig language, who can get anything from that?"

oh its not that bad! heres 5 consecutive lines of the fig code, and the same in qbasic (i havent used smallbasic in a while except to try your program.) (note: line1, line2, etc are not part of the code.)

line1: for p -3.14159 3.14159 .003067958984375
in qb: for p = -3.14159 to 3.14159 step .003067958984375

line2: e w cos times 380 divby 2 int
in qb: e = int(cos(w) * 380 / 2)

line3: rc r divby 2 int
in qb: rc = int(r / 2)

line4: rd 256 minus rc rgbcolour rc rc rc 11
in qb: rd = 256 - rc : rgbcolour(rc, rc, rc, 11) ' of course you need an rgbcolour function

line5: x p times 2 cos times e plus c int
in qb: x = int(cos(p * 2) * e + c)

hows that work? left to right!

[X] p times 2 cos times e plus c int
x =
x [P] times 2 cos times e plus c int
x = p
x p [TIMES 2] cos times e plus c int
x = p * 2
x p times 2 [COS] times e plus c int
x = cos(p * 2)
x p times 2 cos [TIMES E] plus c int
x = cos(p * 2) * e
x p times 2 cos times e [PLUS C] int
x = cos(p * 2) * e + c
x p times 2 cos times e plus c [INT]
x = int(cos(p * 2) * e + c)

smalltalk also does math left to right, except that fig ignores parentheses, and smalltalk will (i believe) follow the order the parentheses describe.

See
http://smallbasic.sourceforge.net/?q=node/1684

Since jsalai is not impressed with string math I started.

And no one seems interested in TriQuad game. I thought was so cool that I added sound effects, splash screen and instructions...

Oh well, I know "That Guy" is interested in talking about his fig! ;-))

Oh yes I was especially interest to see the coded splash-opener and TEXT-FORM Instructions too! It's ok that we will probably have our rent raised now - even Forum programs deserve to be presentable ... not to say, comprehensible. Only had time to glance at the source-code yesterday, true, and have to run back to work now.

I was especially interested to see there is a Star Maker remake, but did not look because then I would have been late. I might get a decent break at lunch. Work will slow again soon. - Ted

"Oh well, I know "That Guy" is interested in talking about his fig! ;-))"

hey, only when people show a real interest--
or they make a forum thread that mentions it--
or if they seem to imply something worth defending it from :)
or if i find another excuse... but most of the time its gotta be one of those mentioned.

This is definitely a breakthrough for using DRAWPOLY, here is old screen saver #1 now with DRAWPOLY replacing bulky triangleFill sub:


' remake screen saver 1.bas SmallBASIC 0.12.8 [B+=MGA] 2017-03-26
REM screen saver number 1.bas 2016-02-11 SmallBASIC 0.12.0 [B+=MGA]
' a version of old mystic triangle

randomize
ntri=18
dim x1(ntri),x2(ntri),x3(ntri),y1(ntri),y2(ntri),y3(ntri),ct(ntri)
dim dx1(ntri),dx2(ntri),dx3(ntri),dy1(ntri),dy2(ntri),dy3(ntri)

label restart
for
i=1 to ntri
x1(i)=(xmax+200)*rnd-100:x2(i)=(xmax+200)*rnd-100:x3(i)=(xmax+200)*rnd-100
y1(i)=(ymax+200)*rnd-100:y2(i)=(ymax+200)*rnd-100:y3(i)=(ymax+200)*rnd-100
dx1(i)=10*rnd*rdir:dx2(i)=10*rnd*rdir:dx3(i)=10*rnd*rdir
dy1(i)=5*rnd*rdir:dy2(i)=5*rnd*rdir:dy3(i)=5*rnd*rdir
c1=int(rnd*2):c2=int(rnd*2):c3=int(rnd*2)
ct(i)=rgb(255*rnd*c1,255*rnd*c2,255*rnd*c3)
if ct(i)=0 then ct(i)=rgb(255,0,0)
next
while 1
if len(inkey) then goto restart
cls
for i=1 to ntri
color ct(i)
dim arr()
arr << x1(i) : arr << y1(i)
arr << x2(i) : arr << y2(i)
arr << x3(i) : arr << y3(i)
arr << x1(i) : arr << y1(i) '<<< this is the trick with drawpoly,
' include first point again
drawpoly arr filled
'ftriangle x1(i),y1(i),x2(i),y2(i),x3(i),y3(i),ct(i)
x1(i)=x1(i)+dx1(i)
if x1(i)<-100 then dx1(i)=dx1(i)*-1
if x1(i)>xmax+100 then dx1(i)=dx1(i)*-1
x2(i)=x2(i)+dx2(i)
if x2(i)<-100 then dx2(i)=dx2(i)*-1
if x2(i)>xmax+100 then dx2(i)=dx2(i)*-1
x3(i)=x3(i)+dx3(i)
if x3(i)<-100 then dx3(i)=dx3(i)*-1
if x3(i)>xmax+100 then dx3(i)=dx3(i)*-1
y1(i)=y1(i)+dy1(i)
if y1(i)<-100 then dy1(i)=dy1(i)*-1
if y1(i)>ymax+100 then dy1(i)=dy1(i)*-1
y2(i)=y2(i)+dy2(i)
if y2(i)<-100 then dy2(i)=dy2(i)*-1
if y2(i)>ymax+100 then dy2(i)=dy2(i)*-1
y3(i)=y3(i)+dy3(i)
if y3(i)<-100 then dy3(i)=dy3(i)*-1
if y3(i)>ymax+100 then dy3(i)=dy3(i)*-1
next
showpage
delay 10
wend
func
rdir()
if int(rnd*2) then rdir=1 else rdir=-1
end