|
Post by B+ on Jul 3, 2019 14:59:37 GMT
Vince has offered another challenge: Above is my solution translated to JB. He does not allow sprites, would they help?
|
|
|
Post by tsh73 on Jul 4, 2019 8:26:54 GMT
I think he just explicitly prohibit loading ready-made bitmap (in code or from disk) (was first attempt for crescent moon pattern of such kind?)
I don't quite see how using sprites could help anyway.
|
|
|
Post by B+ on Jul 4, 2019 14:43:38 GMT
I think he just explicitly prohibit loading ready-made bitmap (in code or from disk) (was first attempt for crescent moon pattern of such kind?)I don't quite see how using sprites could help anyway. Yes, the first responder "cheated" by converting the screen snap shot of challenge to DATA points creating a .bas file > 2 MB! Still kind of impressive that one could do it that way.
|
|
|
Post by Rod on Jul 6, 2019 11:16:54 GMT
Rough knot
nomainwin WindowWidth = DisplayWidth WindowHeight = DisplayHeight UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2) midx=int(WindowWidth/2) midy=int(WindowHeight/2) open "Knot" for graphics_nsb as #1 #1 "down ; fill black ; color white ; trapclose [quit]"
[knot] a1=10 a2=350 for m= 0 to 360 step 60 midxx=midx-(128*sin(m/57.29577951)) midyy=midy-(128*cos(m/57.29577951)) for n= a1 to a2 x=midxx-(100*sin(n/57.29577951)) y=midyy-(100*cos(n/57.29577951)) x1=midxx-(80*sin(n/57.29577951)) y1=midyy-(80*cos(n/57.29577951)) #1 "set ";x;" ";y #1 "set ";x1;" ";y1 next n a1=a1+60 a2=a2+60 next m a1=20 a2=400 for m= 30 to 360 step 60 midxx=midx-(230*sin(m/57.29577951)) midyy=midy-(230*cos(m/57.29577951)) for n= a1 to a2 x=midxx-(100*sin(n/57.29577951)) y=midyy-(100*cos(n/57.29577951)) x1=midxx-(80*sin(n/57.29577951)) y1=midyy-(80*cos(n/57.29577951)) #1 "set ";x;" ";y #1 "set ";x1;" ";y1 next n a1=a1+60 a2=a2+60 next m #1 "color black ; size 2" for m=1 to 110 #1 "place ";midx;" ";midy;" ; circle ";230+m next wait
[quit] close #1 end
|
|
|
Post by B+ on Jul 6, 2019 14:20:24 GMT
Hi Rod, That's how I started, I made a "skeleton" of the main circles involved. For the snap shot above, I eyeballed where the arcs on each circle began and ended (on one set of inner and outer circles) so you can draw the proper bridges when you come to intersection. Then I worked up math code to determine the 2 points intersection of 2 circles, so I could do it for any radii without eye balling in all the starts and ends of Arcs. Then I hit a wall because I had to determine which intersect point was which when assigning to variables. Solved by referring point/angles back to a "Standard Map of Variables" that orders the points smaller and larger if they were sitting on a standard circle with variable numbers going in clockwise direction with angle increase, ugly as hell but works...
|
|
|
Post by B+ on Jul 7, 2019 14:31:04 GMT
Here is code I use for drawing Arcs:
SUB arc x, y, r, raStart, raStop 'x, y origin, r = radius, c = color
'raStart is first angle clockwise from due East = 0 degrees ' arc will start drawing there and clockwise until raStop angle reached
IF raStop < raStart THEN call arc x, y, r, raStart, PI*2 call arc x, y, r, 0, raStop ELSE ' modified to easier way suggested by Steve 'Why was the line method not good? I forgot. aStep = 1 / (PI * r * r * (raStop - raStart) / (PI*2)) FOR a = raStart TO raStop STEP aStep scan #gr "set ";x + r * COS(a);" ";y + r * SIN(a) NEXT END IF END SUB
|
|
|
Post by tsh73 on Jul 8, 2019 9:10:50 GMT
Not quite here - but I kind of got a way to draw thick curved bordered lines It does overlap nicely (it will not get sharp edges though)
Problem is celtic knot does not overlap "right" way - it knots... So just pouring paint from above would not give needed overlapping
'random wandering nomainwin open "test" for graphics_nsb_nf as #gr #gr "trapclose [quit]" #gr "down; fill lightgray" '#gr "fill white; flush" #gr "home; posxy cx cy" a0=15 'trial and error, but works da=5 d=10 w=20
#gr "place 160 180" #gr "color white" #gr "size ";w+4 #gr "circle ";90
#gr "size ";w #gr "color black" #gr "circle ";90
#gr "place 50 250" #gr "north; turn ";a0 while 1 scan 'wide wite #gr "posxy x0 y0" #gr "color white" #gr "size ";w+4 #gr "go ";d 'thin (black?) over it col$=rainbow$(colI) colI=colI+0.003 #gr "color ";col$ #gr "size ";w #gr "place ";x0;" ";y0 if not(turn) then #gr "go -5; go 5" end if #gr "go ";d
#gr "turn ";da 'turns turn =0 'random point turn if rnd(0)<1/30 then #gr "turn ";120-2*a0 colI=colI+1/6 turn = 1 end if 'bounds turn #gr "posxy xq yq" if xq<20 or xq>cx*2-20 or yq<20 or yq>cy*2-20 then #gr "turn ";180 colI=colI+1/6 turn = 1 end if call pause 10 wend
'#gr "home; circle 50"
#gr "flush" wait
[quit] timer 0 close #gr end
sub pause mil t0=time$("ms") while time$("ms")<t0+mil scan wend exit sub [quit] timer 0 close #gr end end sub
'--------------------------------------------- ' 0..1 into red-green-blue-red continuous colors function rainbow$(x) hi = int((x*6) mod 6)+ 5*(x<0) 'fixed to 0..5 f = (x*6) mod 1 + (x<0) 'frac, 0..1 q = (1-f) select case hi case 0 r = 1: g = f: b = 0 case 1 r = q: g = 1: b = 0 case 2 r = 0: g = 1: b = f case 3 r = 0: g = q: b = 1 case 4 r = f: g = 0: b = 1 case 5 r = 1: g = 0: b = q end select R = int(r*255) G = int(g*255) B = int(b*255) rainbow$= R;" ";G;" ";B end function
|
|
|
Post by tsh73 on Jul 8, 2019 9:13:17 GMT
Here what I got so far. Different kind of celtic knot Since overlapping is complex I end up running over contour trice, pen Up and Down in some places. 'tsh73, Jul 2019 'Celick knot inspired nomainwin open "test" for graphics_nsb_nf as #gr #gr "trapclose [quit]" #gr "down; fill lightgray" 'so white border is visible #gr "home; posxy cx cy" a0=15 'trial and error, but works da=5 d=10 w=20 'notice (180-2*a0)/da-1 '29 N=(180-2*a0)/da-1
#gr "place 50 250" #gr "north; turn ";a0 for k = 1 to 9 'actually, three passes with on/off drawing to make them overlap right 'k = 1..3 - full drawing, 4..6 - right overlap, 6..9 - clearing white lines on turns #gr "down" if k =4 then 'circle #gr "place 160 180" #gr "color white" #gr "size ";w+4 'white is 4 pixels wider, giving approx 2 px border #gr "circle ";90
#gr "size ";w #gr "color black" #gr "circle ";90 end if
if k =4 or k = 7 then 'drawing does not returns exactly, so I'll reset starting point #gr "place 50 250" end if for i = 0 to N if i >int(N/2) and k >3 then #gr "up" 'second pass, only first part of an arc if i >N-1 and k >6 then #gr "down" 'last pass, only end of an arc scan 'wide wite #gr "posxy x0 y0" if k<7 then 'only on first two passes #gr "color white" #gr "size ";w+4 #gr "go ";d end if 'thing black over it #gr "place ";x0;" ";y0 #gr "color black" #gr "size ";w 'now this one is nice. This clears end white line of a bordered line (i<>0 skipps starting point) if i<>0 then #gr "go -5; go 5" #gr "go ";d if i=int(N/2) then #gr "go 5; go -5" 'thi is needed on second pass
#gr "turn ";da 'small turn along the arc call pause 30 next #gr "turn ";120-2*a0 'big turn next
#gr "flush" wait
[quit] timer 0 close #gr end
sub pause mil t0=time$("ms") while time$("ms")<t0+mil scan wend end sub
|
|
|
Post by B+ on Jul 8, 2019 13:59:13 GMT
Hi tsh73,
I like the way you think! I was wondering if a way like this might be attempted along with the circle border one color, fill another. Just plot the track a pencil might travel around the knot.
I worked up a complex monster of getting the 2 intersect coordinates of 2 intersecting circles involving 5 rings with inner and outer circles. Took over 70 variables to get all the points of interest to draw arcs.
Yeah, you might have to go over some places 3 times but if the only alternative is 70 variables... ;-))
Also to me, the rounded corners look better!
You know, whatever you draw in one place can be easily multiplied around the circle because of symmetry. I see a hexagon of your drawing repeated 5 more times around center of screen, then connect inner loops?
Very inspiring.
|
|
|
Post by tsh73 on Jul 8, 2019 14:14:26 GMT
Err.. Where?
EDIT I think I got it. May be.
|
|
|
Post by B+ on Jul 8, 2019 14:20:04 GMT
Sprite rotation or translate point by point like snowflake drawing or the thing you are thinking
|
|
|
Post by B+ on Jul 8, 2019 17:03:09 GMT
Before I loose track of it, here is the code I used for the original screen shot at the start of this thread.
All the Arc start and stop angles were eyeballed but these numbers are scale-able with different radii which are calculated off thickness given as sub argument:
'Celtic Knot Challenge.txt for JB v2 bplus 2019-07-03 trans from QB64 version ' Vince counter challenges!
global PI, xmax, ymax PI = 3.14159265 xmax = 1200 'full screen width ymax = 700
nomainwin UpperLeftX = 100 UpperLeftY = 10
WindowWidth = xmax + 8 'adjust +10 for screen frame plus slight white frame WindowHeight = ymax + 32 'add +32 for screen frame plus slight white frame
'_nf =no full screen, _nsb =no scroll bars open "Celtic Knot Challenge" for graphics_nsb_nf as #gr #gr "trapclose [quit]" #gr "down" #gr "size 1" 'oh this works great for filling gaps between lines!
x = 50: y = 60 FOR i = 1 TO 4 scan call ink 30, 255 - i*40, 50*i x = x + i * 80: y = y + i * 40 call celticKnot x, y, i * 5 NEXT wait
[quit] timer 0 close #gr end
SUB celticKnot xc, yc, thick
distr = 5 * thick r = 4 * thick r1 = 3 * thick hex = PI * 2 / 6 hd2 = hex / 2
FOR nHex = 1 TO 6 scan 'circles with origins in main circle x0 = xc + distr * COS(nHex * hex - hd2) y0 = yc + distr * SIN(nHex * hex - hd2)
'outer radius 'CIRCLE (x0, y0), r call arc x0, y0, r, nHex * hex - .37, nHex * hex + 1.2 call arc x0, y0, r, nHex * hex + 1.47, nHex * hex + 2.77 'inner eye call arc x0, y0, r, nHex * hex + 3.05, nHex * hex + 4.3 call arc x0, y0, r, nHex * hex + 4.55, nHex * hex + 5.6
'inner radius 'CIRCLE (x0, y0), r1 call arc x0, y0, r1, nHex * hex - .1, nHex * hex + 1.15 call arc x0, y0, r1, nHex * hex + 1.51, nHex * hex + 2.73 'inner eye call arc x0, y0, r1, nHex * hex + 3.1, nHex * hex + 4.25 call arc x0, y0, r1, nHex * hex + 4.58, nHex * hex + 5.32
' circles with outside origins x0 = xc + (2 * distr - 1.5 * thick) * COS(nHex * hex) y0 = yc + (2 * distr - 1.5 * thick) * SIN(nHex * hex)
'outer radius 'CIRCLE (x0, y0), r call arc x0, y0, r, nHex * hex + 1.68, nHex * hex + 3.25 call arc x0, y0, r, nHex * hex + 3.51, nHex * hex + 4.6 'inner radius 'CIRCLE (x0, y0), r1 call arc x0, y0, r1, nHex * hex + 1.98, nHex * hex + 3.2 call arc x0, y0, r1, nHex * hex + 3.56, nHex * hex + 4.3
NEXT END SUB
SUB arc x, y, r, raStart, raStop 'x, y origin, r = radius, c = color
'raStart is first angle clockwise from due East = 0 degrees ' arc will start drawing there and clockwise until raStop angle reached
IF raStop < raStart THEN call arc x, y, r, raStart, PI*2 call arc x, y, r, 0, raStop ELSE ' modified to easier way suggested by Steve 'Why was the line method not good? I forgot. aStep = 1 / (PI * r * r * (raStop - raStart) / (PI*2)) FOR a = raStart TO raStop STEP aStep scan #gr "set ";x + r * COS(a);" ";y + r * SIN(a) NEXT END IF END SUB
sub ink r,g,b #gr "color ";r;" ";g;" ";b #gr "backcolor ";r;" ";g;" ";b end sub
Compared to the monster program that calculates the start and stop angles for all the intersect points, this program looks simple.
|
|
|
Post by B+ on Jul 10, 2019 18:07:15 GMT
Sprite rotation or translate point by point like snowflake drawing or the thing you are thinking Here is my idea roughed in: ' Celtic Knot Projector =rough work in progress, B+ 2019-07-10 'using: 'tsh73, Jul 2019 'Celick knot inspired
nomainwin global H$, XMAX, YMAX, PI, DEG, RAD H$ = "gr" XMAX = 1000 '< actual drawing space needed YMAX = 700 '< actual drawing space needed PI = acs(-1) DEG = 180 / PI RAD = PI / 180
WindowWidth = XMAX + 8 WindowHeight = YMAX + 32 UpperLeftX = (1200 - XMAX) / 2 'or delete if XMAX is 1200 or above UpperLeftY = (700 - YMAX) / 2 'or delete if YMAX is 700 or above open "celtic knot points.txt" for output as #1
open "test" for graphics_nsb_nf as #gr #gr "trapclose [quit]" #gr "down; fill lightgray" 'so white border is visible '#gr "home; posxy cx cy"
cx = 156:cy = 164 'home on default screen
a0=15 'trial and error, but works da=5 d=10 w=20 'notice (180-2*a0)/da-1 '29 N=(180-2*a0)/da-1
#gr "place 50 250" #gr "north; turn ";a0 for k = 1 to 9 'actually, three passes with on/off drawing to make them overlap right 'k = 1..3 - full drawing, 4..6 - right overlap, 6..9 - clearing white lines on turns #gr "down" if k =4 then 'circle #gr "place 160 180" #gr "color white" #gr "size ";w+4 'white is 4 pixels wider, giving approx 2 px border #gr "circle ";90
#gr "size ";w #gr "color black" #gr "circle ";90 end if
if k =4 or k = 7 then 'drawing does not returns exactly, so I'll reset starting point #gr "place 50 250" end if for i = 0 to N if i >int(N/2) and k >3 then #gr "up" 'second pass, only first part of an arc if i >N-1 and k >6 then #gr "down" 'last pass, only end of an arc scan 'wide wite #gr "posxy x0 y0" print #1, str$(x0);" ";str$(y0) if k<7 then 'only on first two passes #gr "color white" #gr "size ";w+4 #gr "go ";d end if 'thing black over it #gr "place ";x0;" ";y0 #gr "color black" #gr "size ";w 'now this one is nice. This clears end white line of a bordered line (i<>0 skipps starting point) if i<>0 then #gr "go -5; go 5" #gr "go ";d if i=int(N/2) then #gr "go 5; go -5" 'thi is needed on second pass
#gr "turn ";da 'small turn along the arc call pause 30 next #gr "turn ";120-2*a0 'big turn next close #1 #gr "flush" #gr "down" #gr "fill white" open "celtic knot points.txt" for input as #1 hexAngle = PI/3 dim hCenterX(6), hCenterY(6) 'get 6 hexagon origins for h = 1 to 6 hCenterX(h) = XMAX/2 + 187*cos(h*hexAngle-PI/24) hCenterY(h) = YMAX/2 + 187*sin(h*hexAngle-PI/24) next while eof(#1) = 0 scan line input #1, fline$ FOR h = 1 TO 6 call drawTranslateRotatePoint val(LeftOf$(fline$, " ")), val(RightOf$(fline$, " ")), 156, 164, hCenterX(h), hCenterY(h), h*hexAngle+ PI/6, 1 NEXT wend close #1 for h = 1 to 7 hCX = XMAX/2 + 54*cos(h*hexAngle-PI/24) hCY = YMAX/2 + 54*sin(h*hexAngle-PI/24) if h > 1 then #gr "line ";lastx;" ";lasty;" ";hCX;" ";hCY lastx = hCX:lasty = hCY
next
wait
[quit] timer 0 close #gr end
sub pause mil t0=time$("ms") while time$("ms")<t0+mil scan wend end sub
FUNCTION LeftOf$ (source$, of$) posOf = INSTR(source$, of$) IF posOf > 0 THEN LeftOf$ = MID$(source$, 1, posOf - 1) END FUNCTION
FUNCTION RightOf$ (source$, of$) posOf = INSTR(source$, of$) IF posOf > 0 THEN RightOf$ = MID$(source$, posOf + LEN(of$)) END FUNCTION
SUB drawTranslateRotatePoint x, y, cx, cy, newCenterX, newCenterY, rotate, scale angle = Atan2(y - cy, x - cx) distance = ((x - cx) ^ 2 + (y - cy) ^ 2) ^ .5 newX = newCenterX + scale * distance * COS(angle + rotate) newY = newCenterY + scale * distance * SIN(angle + rotate) #gr "set ";newX;" ";newY END SUB
Function Atan2(y, x) 'Atan2 is a function which determines the angle between points 'x1, y1 and x2, y2. The angle returned is in radians 'The angle returned is always in the range of '-PI to PI radians (-180 to 180 degrees) '============================================================== 'NOTE the position of Y and X arguments 'This keeps Atan2 function same as other language versions '============================================================== If x = 0 Then If y < 0 Then Atan2 = -1.5707963267948967 Else Atan2 = 1.5707963267948967 End If Else chk = atn(y/x) If x < 0 Then If y < 0 Then chk = chk - 3.1415926535897932 Else chk = chk + 3.1415926535897932 End If End If Atan2 = chk End If 'thanks Andy Amaya End Function
Attachment DeletedAttachments:
|
|
|
Post by B+ on Jul 11, 2019 18:02:23 GMT
Easy way! 'Celtic Knot 2.txt for JB v2 bplus 2019-07-11 easier way!! global PI, XMAX, YMAX PI = 3.14159265 XMAX = 700 'full screen width YMAX = 700 nomainwin UpperLeftX = 300 UpperLeftY = 10 WindowWidth = XMAX + 8 'adjust +10 for screen frame plus slight white frame WindowHeight = YMAX + 32 'add +32 for screen frame plus slight white frame open "Celtic Knot 2" for graphics_nsb_nf as #gr '_nf =no full screen, _nsb =no scroll bars #gr "trapclose [quit]" #gr "down" #gr "fill lightgray"
w = 20 'width of rings hexAngle = PI/3 dim hCenterX(6), hCenterY(6), hCX(6), hCY(6) for h = 1 to 6 hCenterX(h) = XMAX/2 + 8*w*cos(h*hexAngle + PI/6) hCenterY(h) = YMAX/2 + 8*w*sin(h*hexAngle + PI/6) hCX(h) = XMAX/2 + 14*w*cos(h*hexAngle) hCY(h) = YMAX/2 + 14*w*sin(h*hexAngle) next #gr "color white" #gr "size ";w+4 for h = 1 to 6 call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI/6 + PI*7/96, h*hexAngle + PI/6 + 2*PI - PI*7/96 call arc hCX(h), hCY(h), 6*w, h*hexAngle + PI*55/96, h*hexAngle + PI*137/96 next #gr "color black" #gr "size ";w for h = 1 to 6 call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI/6 + PI*7/96,h*hexAngle + PI/6 + 2*PI - PI*7/96 call arc hCX(h), hCY(h), 6*w, h*hexAngle + PI*55/96,h*hexAngle + PI*137/96 next 'bridges for h = 1 to 6 #gr "color white" #gr "size ";w+4 'white arc 7 call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI*51/96 , h*hexAngle + PI*57/96 call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI*102/96 , h*hexAngle + PI*109/96 call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI*148/96 , h*hexAngle +PI*155/96 call arc hCX(h), hCY(h), 6*w, h*hexAngle + PI*83/96,h*hexAngle + PI*90/96
#gr "color black" #gr "size ";w 'black arc 2 before 3 after call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI*49/96 , h*hexAngle + PI*60/96 call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI*100/96 , h*hexAngle + PI*112/96 call arc hCenterX(h), hCenterY(h), 6*w, h*hexAngle + PI*146/96 , h*hexAngle +PI*158/96 call arc hCX(h), hCY(h), 6*w, h*hexAngle + PI*81/96,h*hexAngle + PI*92/96 next #gr "flush" wait
[quit] timer 0 close #gr end
SUB arc x, y, r, raStart, raStop 'x, y origin, r = radius, c = color 'raStart is first angle clockwise from due East = 0 degrees ' arc will start drawing there and clockwise until raStop angle reached
IF raStop < raStart THEN call arc x, y, r, raStart, PI*2 call arc x, y, r, 0, raStop ELSE aStep = 1 / (PI * r * 2) FOR a = raStart TO raStop STEP aStep scan #gr "set ";x + r * COS(a);" ";y + r * SIN(a) NEXT END IF END SUB
Attachments:
|
|
|
Post by tsh73 on Jul 11, 2019 21:02:32 GMT
I've got almost exactly the same picture. Just can't stop polishing program (now it has things like "if (i >int(n/2)-2 and i <int(n/2)+2) or ... ", I think I thought of better way to do it)
|
|