Ok. I fixed the color. It is not missing the pattern. The shapes are just overlapping each other..... and I think it must be within the rule of this
challenge.
_DEFINE A-Z AS _FLOAT
DIM SHARED ViewScreen, BlendedScreen
CONST Gold = &HFFFFD700~& ' _RGB32(255,215,0)
CONST Silver = &HFFC0C0C0~& ' _RGB32(192,192,192)
ViewScreen = _NEWIMAGE(800, 800, 32): SCREEN ViewScreen
BlendedScreen = _NEWIMAGE(1536, 100, 32)
CircleScreen = _NEWIMAGE(400, 400, 32) '200 radius outer circle
CreateBlendedScreen
width = 6
DIM k(3 TO 7) AS _UNSIGNED LONG
k(3) = Gold
k(4) = Silver
k(5) = &HFFFF0000 'Red
k(6) = &HFFFFFFFF 'White
k(7) = &HFF0000FF 'Blue
FOR x = 200 TO 600 STEP 400
FOR y = 200 TO 600 STEP 400
length = 200
FOR i = 3 TO 7
DrawPattern x, y, length, width, i, k(i)
length = (length - 2 * width) * COS(_PI / i) - 1
NEXT
NEXT
NEXT
SLEEP
END
SUB DrawPattern (Xcenter, Ycenter, Radius, Width, N, Kolor AS _UNSIGNED LONG)
CreateCircleScreen Xcenter, Ycenter, Radius, Width
'DisplayImage ViewScreen, Xcenter, Ycenter, 0, 0
CreatePolygon Xcenter, Ycenter, Radius - Width, Width, N, Kolor
END SUB
SUB CreatePolygon (Xcenter, YCenter, Radius AS LONG, width AS LONG, N AS LONG, Kolor AS _UNSIGNED LONG)
a = _PI(2) / N
FOR i = 0 TO 1
x = 0
IF i THEN Radius = Radius - width
FOR p = 0 TO _PI(2) STEP a
IF x THEN oldx = x: oldy = y
x = Xcenter + SIN(p) * Radius
y = YCenter + COS(p) * Radius
IF oldx THEN LINE (oldx, oldy)-(x, y), Kolor
NEXT
x2 = Xcenter + SIN(p) * Radius
y2 = YCenter + COS(p) * Radius
LINE (x, y)-(x2, y2), Kolor
NEXT
x = Xcenter + SIN(p) * (Radius + width / 2)
y = YCenter + COS(p) * (Radius + width / 2)
PAINT (x, y), Kolor
END SUB
SUB CreateCircleScreen (Xcenter, YCenter, radius AS LONG, width AS LONG)
'CreateCircleScreen = _NEWIMAGE(radius * 2, radius * 2, 32)
'_DEST CreateCircleScreen
p = _PI(2) * radius
tempimage = _NEWIMAGE(p, width, 32)
_PUTIMAGE , BlendedScreen, tempimage
_SOURCE tempimage
FOR i = 0 TO p - 1 STEP .25
FOR w = 0 TO width - 1
ai = 360 / p
a = _D2R(ai * i)
x = Xcenter + SIN(a) * (radius - w)
y = YCenter + COS(a) * (radius - w)
PSET (x, y), POINT(i, w)
NEXT
NEXT
_SOURCE ViewScreen
' _DEST ViewScreen
_FREEIMAGE tempimage
END SUB
SUB CreateBlendedScreen
'step from red to green
DIM kolor AS _FLOAT, i AS _FLOAT
_DEST BlendedScreen
FOR i = 0 TO 255
kolor = kolor + 1
LINE (i, 0)-STEP(0, 99), _RGB32(255, kolor, 0)
NEXT
FOR i = 256 TO 511
kolor = kolor - 1
LINE (i, 0)-STEP(0, 99), _RGB32(kolor, 255, 0)
NEXT
FOR i = 512 TO 767
kolor = kolor + 1
LINE (i, 0)-STEP(0, 99), _RGB32(0, 255, kolor)
NEXT
FOR i = 768 TO 1023
kolor = kolor - 1
LINE (i, 0)-STEP(0, 99), _RGB32(0, kolor, 255)
NEXT
FOR i = 1024 TO 1279
kolor = kolor + 1
LINE (i, 0)-STEP(0, 99), _RGB32(kolor, 0, 255)
NEXT
FOR i = 1280 TO 1535
kolor = kolor - 1
LINE (i, 0)-STEP(0, 99), _RGB32(255, 0, kolor)
NEXT
_DEST ViewScreen
END SUB
SUB DisplayImage (Image AS LONG, x AS INTEGER, y AS INTEGER, angle AS SINGLE, mode AS _BYTE)
'Image is the image handle which we use to reference our image.
'x,y is the X/Y coordinates where we want the image to be at on the screen.
'angle is the angle which we wish to rotate the image.
'mode determines HOW we place the image at point X,Y.
'Mode 0 we center the image at point X,Y
'Mode 1 we place the Top Left corner of oour image at point X,Y
'Mode 2 is Bottom Left
'Mode 3 is Top Right
'Mode 4 is Bottom Right
DIM px(3) AS INTEGER, py(3) AS INTEGER, w AS INTEGER, h AS INTEGER
DIM sinr AS SINGLE, cosr AS SINGLE, i AS _BYTE
w = _WIDTH(Image): h = _HEIGHT(Image)
SELECT CASE mode
CASE 0 'center
px(0) = -w \ 2: py(0) = -h \ 2: px(3) = w \ 2: py(3) = -h \ 2
px(1) = -w \ 2: py(1) = h \ 2: px(2) = w \ 2: py(2) = h \ 2
CASE 1 'top left
px(0) = 0: py(0) = 0: px(3) = w: py(3) = 0
px(1) = 0: py(1) = h: px(2) = w: py(2) = h
CASE 2 'bottom left
px(0) = 0: py(0) = -h: px(3) = w: py(3) = -h
px(1) = 0: py(1) = 0: px(2) = w: py(2) = 0
CASE 3 'top right
px(0) = -w: py(0) = 0: px(3) = 0: py(3) = 0
px(1) = -w: py(1) = h: px(2) = 0: py(2) = h
CASE 4 'bottom right
px(0) = -w: py(0) = -h: px(3) = 0: py(3) = -h
px(1) = -w: py(1) = 0: px(2) = 0: py(2) = 0
END SELECT
sinr = SIN(angle / 57.2957795131): cosr = COS(angle / 57.2957795131)
FOR i = 0 TO 3
x2 = (px(i) * cosr + sinr * py(i)) + x: y2 = (py(i) * cosr - px(i) * sinr) + y
px(i) = x2: py(i) = y2
NEXT
_MAPTRIANGLE (0, 0)-(0, h - 1)-(w - 1, h - 1), Image TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
_MAPTRIANGLE (0, 0)-(w - 1, 0)-(w - 1, h - 1), Image TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
END SUB
Steve,
Cool to know you were using this method for circle. I think you already posted a similar demo for printing text in this way somewhere before....
Only thing I really noticed that seemed off is just a little math. Your polygons are from the outer ring of your circle and not the inner ring. ;)I am already subtracting radius with line width but it is not working as expected. See on line 32 of my second code.
I am already subtracting radius with line width but it is not working as expected. See on line 32 of my second code.
I scaled and overlapped different, took too long to get those color rings going (completely different method) and match the color of triangles. What do you call that Steve? :D
Edit: oops missing stuff on right side, fixed.
Getting closer. In Steve's, the upper left big circle overlaps the 2nd circle inside the middle circle. Mark, your pattern underlaps it. Sorry, I had to make up a new word to describe the observation.
Really close, though, especially the colors.
Pete
Hi Steve,
Line method leaves gaps near outer edge in odd places, math rounding or something, just enough to make the drawing imperfect. Maybe I am missing something...
Oh hey! Try outer Radius and then one or two layers down to catch the gaps with way less steps, maybe?
OPTION _EXPLICIT
_TITLE "Rainbow Ring" 'bplus 2019-07-07
'DoubleRing mod by Steve 2019-07-08
' QB64 X 64 v 1.3
CONST xmax = 1220, ymax = 760, PI = 3.141592653589793
SCREEN _NEWIMAGE(xmax, ymax, 32)
_SCREENMOVE 100, 0
RANDOMIZE TIMER
DIM SHARED graphicsCalls AS _INTEGER64
DIM offset, start, test
start = TIMER
FOR test = 1 TO 20
CLS
offset = offset + PI / 120
'compare two subs comment out one or the other next 2 lines
'rainbowRing xmax / 2, ymax / 2, 250, 50, offset
'ring xmax / 2, ymax / 2, 250, 50, offset
Doublering xmax / 2, ymax / 2, 250, 50, offset
_DISPLAY
NEXT
PRINT "The number of graphics calls was:"; graphicsCalls
PRINT "Time:"; TIMER - start
_DISPLAY
SUB Doublering (x, y, outerR, innerR, offset)
DIM pm2, pd3, pd6, a, aStep, x1, y1, x2, y2, c AS _UNSIGNED LONG
pm2 = PI * 2
pd3 = PI / 3
pd6 = pd3 / 2 'pd6 aligns red at 90 degrees bottom of circle and light almost white cyan at top, looks good Steve!
'aStep = 1 / (20.1 * pm2 * outerR) 'this is what I used for screen shot
FOR a = 0 TO pm2 STEP 1 / outerR ' <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this the flaw to this method????
x1 = x + outerR * COS(a - pd6 + offset)
y1 = y + outerR * SIN(a - pd6 + offset)
x2 = x + innerR * COS(a - pd6 + offset)
y2 = y + innerR * SIN(a - pd6 + offset)
IF a < pd3 THEN
c = _RGB32(255 * a / pd3, 255, 0)
ELSEIF a < 2 * pd3 THEN
c = _RGB32(255, 255 - 255 * (a - pd3) / pd3, 0)
ELSEIF a < 3 * pd3 THEN
c = _RGB32(255, 0, 255 * (a - 2 * pd3) / pd3)
ELSEIF a < 4 * pd3 THEN
c = _RGB32(255 - 255 * (a - 3 * pd3) / pd3, 0, 255)
ELSEIF a < 5 * pd3 THEN
c = _RGB32(0, 255 * (a - 4 * pd3) / pd3, 255)
ELSE
c = _RGB32(0, 255, 255 - 255 * (a - 5 * pd3) / pd3)
END IF
LINE (x1, y1)-(x2, y2), c
LINE (x1 + 1, y1)-(x2 + 1, y2), c
graphicsCalls = graphicsCalls + 1
NEXT
END SUB
SUB rainbowRing (x, y, outerR, innerR, offset) 'no lines, do arc/circle style
DIM pm2, pd3, pd6, r, a, aStep, x1, y1, x2, y2, c AS _UNSIGNED LONG
pm2 = PI * 2
pd3 = PI / 3
pd6 = pd3 / 2 'pd6 aligns red at 90 degrees bottom of circle and light almost white cyan at top, looks good Steve!
FOR r = innerR TO outerR 'step 1? seems to be OK
'how many pixels 2*PI*R around the curve = how many steps needed to take around circle?
'aStep = 1 / (pm2 * outerR) 'nope not efficient
aStep = 1 / (pm2 * r) '<<<< EDIT/UPDATE: aha!! this makes all the difference !!! (first tried outerR)
FOR a = 0 TO pm2 STEP aStep '>>>>>>>>>>> yeah seems to cover well and does not seem like allot
x1 = x + r * COS(a - pd6 + offset)
y1 = y + r * SIN(a - pd6 + offset)
IF a < pd3 THEN
c = _RGB32(255 * a / pd3, 255, 0)
ELSEIF a < 2 * pd3 THEN
c = _RGB32(255, 255 - 255 * (a - pd3) / pd3, 0)
ELSEIF a < 3 * pd3 THEN
c = _RGB32(255, 0, 255 * (a - 2 * pd3) / pd3)
ELSEIF a < 4 * pd3 THEN
c = _RGB32(255 - 255 * (a - 3 * pd3) / pd3, 0, 255)
ELSEIF a < 5 * pd3 THEN
c = _RGB32(0, 255 * (a - 4 * pd3) / pd3, 255)
ELSE
c = _RGB32(0, 255, 255 - 255 * (a - 5 * pd3) / pd3)
END IF
PSET (x1, y1), c
graphicsCalls = graphicsCalls + 1
NEXT
NEXT
END SUB
SUB ring (x, y, outerR, innerR, offset)
DIM pm2, pd3, pd6, a, aStep, x1, y1, x2, y2, c AS _UNSIGNED LONG
pm2 = PI * 2
pd3 = PI / 3
pd6 = pd3 / 2 'pd6 aligns red at 90 degrees bottom of circle and light almost white cyan at top, looks good Steve!
'aStep = 1 / (20.1 * pm2 * outerR) 'this is what I used for screen shot
FOR a = 0 TO pm2 STEP .00005 ' <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this the flaw to this method????
x1 = x + outerR * COS(a - pd6 + offset)
y1 = y + outerR * SIN(a - pd6 + offset)
x2 = x + innerR * COS(a - pd6 + offset)
y2 = y + innerR * SIN(a - pd6 + offset)
IF a < pd3 THEN
c = _RGB32(255 * a / pd3, 255, 0)
ELSEIF a < 2 * pd3 THEN
c = _RGB32(255, 255 - 255 * (a - pd3) / pd3, 0)
ELSEIF a < 3 * pd3 THEN
c = _RGB32(255, 0, 255 * (a - 2 * pd3) / pd3)
ELSEIF a < 4 * pd3 THEN
c = _RGB32(255 - 255 * (a - 3 * pd3) / pd3, 0, 255)
ELSEIF a < 5 * pd3 THEN
c = _RGB32(0, 255 * (a - 4 * pd3) / pd3, 255)
ELSE
c = _RGB32(0, 255, 255 - 255 * (a - 5 * pd3) / pd3)
END IF
LINE (x1, y1)-(x2, y2), c
graphicsCalls = graphicsCalls + 1
NEXT
END SUB
Now, think of using that process in reverse to “unroll” your circle onto a flat piece of paper.
The circumference of that circle is, of course, 2 * Pi * Radius, so we absolutely know how many pixels we need for it — the LENGTH of that ring, if we “unrolled” it onto a piece of paper.
And, if we define how thick we want the ring to be (Radius for the whole circle, less than that for just a ring — like a donut — from that circle.), we can use that to define the definitive HEIGHT of the size of “paper” we’d unroll that ring upon.
With a length of 2 * Pi * Radius, and a height of Radius, we can “unroll” a complete circular surface onto a flat piece of paper. Just go around, pixel-by-pixel, read one point on each ring in a clockwise direction, and plot its value sequentially to the points in a straight line; then move inwards on the circle, and downwards on your lines.
A round circle can be mapped to a square piece of paper, rather easily, using this method. (Similar to the concept of mapping the globe onto a piece of paper.)
Reverse the process, and you can take a square image, and warp it back onto a circle again, easily enough.
t$ = "You are right, Steve!"
SCREEN _NEWIMAGE(640, 480, 32)
CircleHandle = CreateImage(t$) 'Get a handle for our routine
x = 440: xdirection = -1
y = 240: ydirection = -1
DO
CLS
x = x + xdirection: IF x < 180 OR x > 440 THEN xdirection = -xdirection
y = y + ydirection: IF y < 180 OR y > 280 THEN ydirection = -ydirection
CircleText2 CircleHandle, x, y, rot, 180 'Add options to routine to make it more flexible.
rot = rot + .01
_DISPLAY
_LIMIT 60
LOOP UNTIL _KEYHIT
_FREEIMAGE CircleHandle
FUNCTION CreateImage (t$)
W = _PRINTWIDTH(t$) * _FONTWIDTH + 10
H = _FONTHEIGHT + 10
CreateImage = _NEWIMAGE(W, H, 256)
_DEST CreateImage 'Change Dest
CLS
_PRINTSTRING (5, 5), t$
_DEST 0 'Restore Dest
END FUNCTION
SUB CircleText2 (imagehandle, Xcenter, YCenter, Rot, Radius)
'No need to build and rebuild the image, over and over, since we drew it and saved it in the previous routine.
_SOURCE imagehandle 'Change Source
W = _WIDTH(imagehandle): H = _HEIGHT(imagehandle) 'Get our sizes from whatever the image's is.
DIM k AS _UNSIGNED LONG
g = _PI(2) / W 'Moved to outside the loop since the value doesn't change
FOR hh = 0 TO H - 1
FOR ww = 0 TO W - 1
IF POINT(ww, hh) THEN k = &HFFFFFFFF ELSE k = &HFFFF0000
x = Xcenter + SIN(g * ww + Rot) * Radius + hh
y = YCenter + COS(g * ww + Rot * 2) * Radius + hh
'No need for DEST call, as we never change it
PSET (x, y), k
PSET (x + 1, y), k 'Remark out this line and see how performance is affected.
NEXT ww, hh
_SOURCE 0 'Restore Source
END SUB
I came real, real close.... if a black screen could be considered close. ;)