Author Topic: Pattern Challenge 2  (Read 2718 times)

0 Members and 1 Guest are viewing this topic.

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
Pattern Challenge 2
« on: July 02, 2019, 03:21:05 pm »
In spirit of bplus's thread, I challenge you to draw the attached image.  The only rule is that it has to be a fully re-sizable vector image that doesn't lose detail with change in size (ie no bitmaps/putimage).  Bonus points if you can make the circles and widths variable size. I will be very impressed if someone pulls this off!

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
Re: Pattern Challenge 2
« Reply #1 on: July 02, 2019, 04:33:39 pm »
Cool... Has a Celt-like feel... Nice.
Logic is the beginning of wisdom.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #2 on: July 02, 2019, 06:31:01 pm »
Hi _vince,

You got me thinking... :D

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: Pattern Challenge 2
« Reply #3 on: July 02, 2019, 09:57:22 pm »
I haven’t tried this yet, as I’ve been pressed for time with family stuff, but isn’t this just a series of 4 rotated arcs?

For example, take the far north circle and study it.  It’s 4 arcs with equidistant gaps in it.  Far south, NE, SE, NW, SW are as well; just rotated.  What remains are a series of 2 half-circle arcs, just as the previous 4; just offset to meet the endpoints of the previous arcs...

I haven’t did it yet,but it seems to me like that’s how one would do it.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #4 on: July 02, 2019, 11:34:55 pm »
Still cleaning up end points. My eyes so blurry I can't do anymore tonight but I have a good start:
  [ You are not allowed to view this attachment ]  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #5 on: July 03, 2019, 12:05:46 pm »
Hi _vince,

I did share your challenge at JB with my snap shot of my solution translated to JB.

Obviously I can scale size and change color easy enough but change thickness or width between inner & outer radii? nope!

Needs formula to convert thickness at radius to arc degrees, which I attempted and failed because that still needed more adjustments for the angle at which the thickness was being seen from the arc's origin. (If anyone can follow what I just said, I will be impressed!)

So I am wondering, is your code able to change thickness or distance between inner and outer radii? ie you can draw a large knot with a very thin thickness of a small knot with a very thick "rope" for "knot".

My code is based on the outer radius being 4 * thickness and inner radius being 3 * thickness. So still more challenge left for me... maybe?

Oh, another good thing to try is to see if the border lines can hold PAINT.
« Last Edit: July 03, 2019, 12:07:36 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
Re: Pattern Challenge 2
« Reply #6 on: July 03, 2019, 02:42:55 pm »
Hi
It should be well in the Escher's tables...
each circle is incomplete at the point of touching the invisible external exagon... and each circle is under the circle at its right and  upon the circle that is at its left!....
but all these affirmations are only bad hypothesis...

if you create a function that draws arches with two lines  and you build this image you cannot get any good images because in a circular situation the arch on the left must be drawn before the arch at right, but the last arch is at left of the first arch.

LOL

as in the Escher's pictures if you try to see in different manner you can get the rivelation of the solution...
you can divide the circle into an arch of 180* that have a single part void of the dimension of the distance between the two lines...
after creating this function  you need calculate the start and end point of each arch of the 18 arches

Good math to who has will and patience to get the good calculations.
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #7 on: July 03, 2019, 03:22:35 pm »
Ohhhh Escher! I love Escher drawings :-) hmm... challenge #3?


Well I thought I had cleaned up all my end points pretty well until I tried PAINT and found a couple holes, fixed now:

  [ You are not allowed to view this attachment ]  
« Last Edit: July 03, 2019, 03:27:40 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #8 on: July 03, 2019, 03:55:18 pm »
This is the skeleton from which I eyeballed 12 arcs with 24 start and end angles for the Arc sub to draw (in Radians of course).
Code: QB64: [Select]
  1. _TITLE "Vince Celtic Challenge Skeleton"
  2. CONST xmax = 1200, ymax = 700, pi = 3.14159265
  3. CONST xc = xmax / 2, yc = ymax / 2
  4. SCREEN _NEWIMAGE(xmax, ymax, 32)
  5. _SCREENMOVE 100, 20
  6.  
  7. celticKnot xc, yc, 30
  8.  
  9. SUB celticKnot (xc, yc, thick)
  10.     DIM distr, r, r1, hex, hd2, nHex, x0, y0, c AS _UNSIGNED LONG
  11.  
  12.     distr = 5 * thick
  13.     r = 4 * thick
  14.     r1 = 3 * thick
  15.     hex = pi * 2 / 6
  16.     hd2 = hex / 2
  17.  
  18.     FOR nHex = 1 TO 6
  19.         IF nHex <= 2 THEN c = &HFFFFFFFF ELSE c = &HFF444444
  20.         'circles with origins in main circle
  21.         x0 = xc + distr * COS(nHex * hex - hd2)
  22.         y0 = yc + distr * SIN(nHex * hex - hd2)
  23.  
  24.         'outer radius
  25.         CIRCLE (x0, y0), r, c
  26.         'inner radius
  27.         CIRCLE (x0, y0), r1, c
  28.  
  29.  
  30.         ' circles with outside origins
  31.         x0 = xc + (2 * distr - 1.5 * thick) * COS(nHex * hex)
  32.         y0 = yc + (2 * distr - 1.5 * thick) * SIN(nHex * hex)
  33.         IF nHex = 1 THEN c = &HFF0000FF ELSE c = &HFF444444
  34.         'outer radius
  35.         CIRCLE (x0, y0), r, c
  36.         'inner radius
  37.         CIRCLE (x0, y0), r1, c
  38.  
  39.     NEXT
  40.  
  41.  

I had to have Vince screen shot on the side to see where all there bridges go.

Vince how did you do yours?

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
Re: Pattern Challenge 2
« Reply #9 on: July 04, 2019, 10:17:15 am »
Nice bplus.  I'm assuming you eye-balled each arc angle instead of calculating the intersection points in terms of all the parameters?  Mine takes four variables:  three radii (r, r1, r2) and width to render the image.  There is some tedious geometry but there are a lot of symmetries so it's very prone to simplifications.  I'd imagine it can be done with very little code.  I'll give this another couple of days before posting my solution.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #10 on: July 06, 2019, 12:19:23 am »
A brain buster but the math is doing all the eyeballing now, so can change thickness and circle opening closing at will (within limits of design).




Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #11 on: July 06, 2019, 10:33:00 pm »
Quote
I'd imagine it can be done with very little code.

Not by bplus! :D

Code: QB64: [Select]
  1. _TITLE "Celtic Challenge Advanced Sub" 'B+ 2019-07-06 develop as a sub
  2. ' parameters are x, y origin, radius of Knot, thicknes of rings, border color and fill color
  3. ' is there a max radius of knot?
  4.  
  5. CONST xmax = 700, ymax = 700, pi = 3.14159265
  6. CONST xc = xmax / 2, yc = ymax / 2
  7. SCREEN _NEWIMAGE(xmax, ymax, 32)
  8. _SCREENMOVE 100, 20
  9.  
  10. DIM knot, thick, w$
  11.     CLS
  12.     INPUT "Enter knot size, 20 to 150 best "; knot
  13.     INPUT "Enter ring thickness, 1 to 20% knot best ", thick
  14.     INPUT "Enter f to fill in with green, best not to fill when thickness < %5 knot "; w$
  15.     IF w$ = "f" THEN celticKnot xc, yc, knot, thick, &HFFFFFF00, &HFF00BB00 ELSE celticKnot xc, yc, knot, thick, &HFFFFFF00, 0
  16.     INPUT "press enter to cont... "; w$
  17.     _DISPLAY
  18.  
  19.  
  20. 'the max thickness for the knotRadius is .25 * knotRadius, ideal max is about 20%
  21. ' use 0 for fill color to skip PAINT jobs, recommended for small or thin knots
  22. SUB celticKnot (xc, yc, knotR, ringThick, outline AS _UNSIGNED LONG, fill AS _UNSIGNED LONG)
  23.     DIM r, r1, hex, hd2, nHex
  24.  
  25.     'a good naming system is crucial i/o = inner/outer circle,
  26.     'p1/m1 plus1/minus1 (actually it's plus and minus 1/2 for outer rings)
  27.     DIM xi, yi, xim1, yim1, xip1, yip1, xom1, yom1, xop1, yop1
  28.  
  29.     'points of interest
  30.     DIM xm1, xm2, xm3, xm4, xm5, xm6, xm7, xm9, xm10, xm12
  31.     DIM ym1, ym2, ym3, ym4, ym5, ym6, ym7, ym9, ym10, ym12
  32.     DIM xn1, xn2, xn3, xn4, xn5, xn6, xn8, xn9, xn10, xn11
  33.     DIM yn1, yn2, yn3, yn4, yn5, yn6, yn8, yn9, yn10, yn11
  34.     DIM xp1, xp2, xp3, xp4, xp5, xp6, xp7, xp8
  35.     DIM xq1, xq2, xq3, xq4, xq5, xq6
  36.     DIM yp1, yp2, yp3, yp4, yp5, yp6, yp7, yp8
  37.     DIM yq1, yq2, yq3, yq4, yq5, yq6
  38.  
  39.     r = .8 * knotR '4
  40.     r1 = r - ringThick '3 * ringThick ' 3
  41.     hex = pi * 2 / 6
  42.     hd2 = hex / 2
  43.  
  44.     FOR nHex = 1 TO 6
  45.  
  46.         '5 circle origin sets
  47.  
  48.         'inner ring before main ring
  49.         xim1 = xc + knotR * COS((nHex - 1) * hex - hd2)
  50.         yim1 = yc + knotR * SIN((nHex - 1) * hex - hd2)
  51.  
  52.         'main inner ring to draw up
  53.         xi = xc + knotR * COS(nHex * hex - hd2)
  54.         yi = yc + knotR * SIN(nHex * hex - hd2)
  55.  
  56.         'inner ring after main
  57.         xip1 = xc + knotR * COS((nHex + 1) * hex - hd2)
  58.         yip1 = yc + knotR * SIN((nHex + 1) * hex - hd2)
  59.  
  60.         'outer ring before main ring
  61.         xom1 = xc + (2 * knotR - 1.5 * ringThick) * COS((nHex - 1) * hex)
  62.         yom1 = yc + (2 * knotR - 1.5 * ringThick) * SIN((nHex - 1) * hex)
  63.  
  64.         'outer ring after main ring
  65.         xop1 = xc + (2 * knotR - 1.5 * ringThick) * COS(nHex * hex)
  66.         yop1 = yc + (2 * knotR - 1.5 * ringThick) * SIN(nHex * hex)
  67.  
  68.         'working main ring from 0 to 2*pi  one segment at a time
  69.  
  70.         'first point of interest on main is out circle /\ out circle of op1
  71.         intersect2Circles xi, yi, r, xop1, yop1, r, xm1, ym1, xm4, ym4
  72.         intersect2Circles xi, yi, r, xop1, yop1, r1, xm2, ym2, xm3, ym3
  73.  
  74.         intersect2Circles xi, yi, r, xop1, yop1, r1, xm2, ym2, xm3, yn3
  75.         intersect2Circles xi, yi, r1, xop1, yop1, r1, xn2, yn2, xn3, yn3
  76.  
  77.         minorArc xi, yi, r, rAngle(xi, yi, xm1, ym1), rAngle(xi, yi, xm3, ym3), outline
  78.         minorArc xi, yi, r1, rAngle(xi, yi, xn2, yn2), rAngle(xi, yi, xn3, yn3), outline
  79.  
  80.         'inside main outside po1
  81.         intersect2Circles xi, yi, r1, xop1, yop1, r, xn1, yn1, xn4, yn4
  82.  
  83.         'outside main with outside im1
  84.         intersect2Circles xi, yi, r, xim1, yim1, r, xm5, ym5, xm10, ym10
  85.  
  86.         'inside main outside im1
  87.         intersect2Circles xi, yi, r1, xim1, yim1, r, xn5, yn5, xn10, yn10
  88.  
  89.         minorArc xi, yi, r, rAngle(xi, yi, xm4, ym4), rAngle(xi, yi, xm5, ym5), outline
  90.         minorArc xi, yi, r1, rAngle(xi, yi, xn4, yn4), rAngle(xi, yi, xn5, yn5), outline
  91.  
  92.  
  93.         'outside main to inside im1
  94.         intersect2Circles xi, yi, r, xim1, yim1, r1, xm6, ym6, xm9, ym9
  95.  
  96.         'inside main to inside im1
  97.         intersect2Circles xi, yi, r1, xim1, yim1, r1, xn6, yn6, xn9, yn9
  98.  
  99.         minorArc xi, yi, r, rAngle(xi, yi, xm6, ym6), rAngle(xi, yi, xm9, ym9), outline
  100.         minorArc xi, yi, r1, rAngle(xi, yi, xn6, yn6), rAngle(xi, yi, xn9, yn9), outline
  101.  
  102.         'outer main to outer om1
  103.         intersect2Circles xi, yi, r, xom1, yom1, r, xm7, ym7, xm12, ym12
  104.  
  105.         'inner main to inner om1
  106.         intersect2Circles xi, yi, r1, xom1, yom1, r1, xn8, yn8, xn11, yn11
  107.  
  108.         minorArc xi, yi, r, rAngle(xi, yi, xm10, ym10), rAngle(xi, yi, xm12, ym12), outline
  109.         minorArc xi, yi, r1, rAngle(xi, yi, xn10, yn10), rAngle(xi, yi, xn11, yn11), outline
  110.  
  111.  
  112.         'now for the two that fold inward
  113.  
  114.         'outer op1 to outer  ip1
  115.         intersect2Circles xop1, yop1, r, xip1, yip1, r, xp1, yp1, xp4, yp4
  116.         'outer op1 to inner p1
  117.         intersect2Circles xop1, yop1, r, xip1, yip1, r1, xp2, yp2, xp3, yp3
  118.         'inner op1 to inner p1
  119.         intersect2Circles xop1, yop1, r1, xip1, yip1, r1, xq2, yq2, xq3, yq3
  120.  
  121.         minorArc xop1, yop1, r, rAngle(xop1, yop1, xp1, yp1), rAngle(xop1, yop1, xp3, yp3), outline
  122.         minorArc xop1, yop1, r1, rAngle(xop1, yop1, xq2, yq2), rAngle(xop1, yop1, xq3, yq3), outline
  123.  
  124.         'inner op1 outer inner p1
  125.         intersect2Circles xop1, yop1, r1, xip1, yip1, r, xq1, yq1, xq4, yq4
  126.  
  127.         minorArc xop1, yop1, r, rAngle(xop1, yop1, xp4, yp4), rAngle(xop1, yop1, xm1, ym1), outline
  128.  
  129.  
  130.         'last test?
  131.         minorArc xop1, yop1, r1, rAngle(xop1, yop1, xq4, yq4), rAngle(xop1, yop1, xn1, yn1), outline
  132.  
  133.  
  134.         'outer om1 to outer outer main
  135.         intersect2Circles xom1, yom1, r, xi, yi, r, xp5, yp5, xp8, yp8
  136.         'inner om1 to inner main
  137.         intersect2Circles xom1, yom1, r1, xi, yi, r1, xq5, yq5, xq6, yq6
  138.         'outer om1to inner main
  139.         intersect2Circles xom1, yom1, r, xi, yi, r1, xp6, yp6, xp7, yp7
  140.  
  141.         minorArc xom1, yom1, r, rAngle(xom1, yom1, xp5, yp5), rAngle(xom1, yom1, xp7, yp7), outline
  142.         minorArc xom1, yom1, r1, rAngle(xom1, yom1, xq5, yq5), rAngle(xom1, yom1, xq6, yq6), outline
  143.  
  144.     NEXT
  145.  
  146.     IF fill THEN
  147.         DIM px, py, midR
  148.         midR = (r + r1) / 2 + .5
  149.         FOR nHex = 1 TO 6
  150.             'circles with origins in main circle
  151.             'main inner ring to draw up
  152.             xi = xc + knotR * COS(nHex * hex - hd2)
  153.             yi = yc + knotR * SIN(nHex * hex - hd2)
  154.  
  155.             '4 paint points
  156.             px = xi + midR * COS(nHex * hex + .1 * pi)
  157.             py = yi + midR * SIN(nHex * hex + .1 * pi)
  158.             'CIRCLE (px, py), 1, fill
  159.             PAINT (px, py), fill, outline
  160.  
  161.             px = xi + midR * COS(nHex * hex + .7 * pi)
  162.             py = yi + midR * SIN(nHex * hex + .7 * pi)
  163.             'CIRCLE (px, py), 1, fill
  164.             PAINT (px, py), fill, outline
  165.  
  166.             px = xi + midR * COS(nHex * hex + 1.3 * pi)
  167.             py = yi + midR * SIN(nHex * hex + 1.3 * pi)
  168.             'CIRCLE (px, py), 1, fill
  169.             PAINT (px, py), fill, outline
  170.  
  171.             px = xi + midR * COS(nHex * hex + 1.7 * pi)
  172.             py = yi + midR * SIN(nHex * hex + 1.7 * pi)
  173.             'CIRCLE (px, py), 1, fill
  174.             PAINT (px, py), fill, outline
  175.  
  176.         NEXT
  177.     END IF
  178.  
  179. 'given a circles origin and point on the circumference return the arc measure of that point
  180. FUNCTION rAngle (coX, coY, circumX, circumY)
  181.     rAngle = _ATAN2(circumY - coY, circumX - coX)
  182.     IF rAngle < 0 THEN rAngle = rAngle + _PI(2)
  183.  
  184. 'given two arc angles I want the one that draws the smaller arc drawn
  185. SUB minorArc (x, y, r, ra1, ra2, c AS _UNSIGNED LONG)
  186.     DIM raStart, raStop
  187.  
  188.     'which has smaller arc measure
  189.     IF ra1 < ra2 THEN
  190.         IF ra2 - ra1 < _PI THEN raStart = ra1: raStop = ra2 ELSE raStart = ra2: raStop = ra1
  191.     ELSE
  192.         IF ra1 - ra2 < _PI THEN raStart = ra2: raStop = ra1 ELSE raStart = ra1: raStop = ra2
  193.     END IF
  194.     arc x, y, r, raStart, raStop, c
  195.  
  196. SUB intersect2Circles (x1, y1, r1, x2, y2, r2, ix1, iy1, ix2, iy2)
  197.     'x1, y1 origin of circle 1 with radius r1
  198.     'x2, y2 origin of circle 2 with radius r2
  199.     'ix1, iy1 is the first point of intersect
  200.     'ix2, iy2 is the 2nd point of intersect
  201.     'if ix1 = ix2 = iy1 = iy2 = 0 then no points returned
  202.  
  203.     DIM d, a, h, Px, Py, offset, rang1, rang2
  204.     d = distance(x1, y1, x2, y2) 'distance between two origins
  205.     IF r1 + r2 < d THEN
  206.         'PRINT "The circles are too far apart to intersect.": END
  207.         'some signal ???    if ix1 = ix2 = iy1 = iy2 = 0 then no points returned
  208.         ix1 = 0: ix2 = 0: iy1 = 0: iy2 = 0
  209.         EXIT SUB
  210.     END IF
  211.     IF (d < r1 AND r2 + d < r1) OR (d < r2 AND r1 + d < r2) THEN ' no intersect
  212.         ix1 = 0: ix2 = 0: iy1 = 0: iy2 = 0
  213.         EXIT SUB
  214.     END IF
  215.     'results
  216.     a = (r1 ^ 2 - r2 ^ 2 + d ^ 2) / (2 * d)
  217.     Px = x1 + a * (x2 - x1) / d
  218.     Py = y1 + a * (y2 - y1) / d
  219.     h = (r1 ^ 2 - a ^ 2) ^ .5
  220.     ix1 = INT(Px - h * (y2 - y1) / d)
  221.     iy1 = INT(Py + h * (x2 - x1) / d)
  222.     ix2 = INT(Px + h * (y2 - y1) / d)
  223.     iy2 = INT(Py - h * (x2 - x1) / d)
  224.  
  225.     ''getting the order of points matched to varaible labels
  226.     offset = rAngle(xc, yc, x1, y1)
  227.     rang1 = rAngle(x1, y1, ix1, iy1) - offset
  228.     IF rang1 < 0 THEN rang1 = rang1 + 2 * pi
  229.     rang2 = rAngle(x1, y1, ix2, iy2) - offset
  230.     IF rang2 < 0 THEN rang2 = rang2 + 2 * pi
  231.     IF rang2 < rang1 THEN SWAP ix1, ix2: SWAP iy1, iy2
  232.  
  233.  
  234. SUB arc (x, y, r, raStart, raStop, c AS _UNSIGNED LONG)
  235.     'x, y origin, r = radius, c = color
  236.  
  237.     'raStart is first angle clockwise from due East = 0 degrees
  238.     ' arc will start drawing there and clockwise until raStop angle reached
  239.  
  240.     DIM al, a
  241.     IF raStop < raStart THEN
  242.         arc x, y, r, raStart, _PI(2), c
  243.         arc x, y, r, 0, raStop, c
  244.     ELSE
  245.         ' modified to easier way suggested by Steve
  246.         'Why was the line method not good? I forgot.
  247.         al = _PI * r * r * (raStop - raStart) / _PI(2)
  248.         FOR a = raStart TO raStop STEP 1 / al
  249.             PSET (x + r * COS(a), y + r * SIN(a)), c
  250.         NEXT
  251.     END IF
  252.  
  253. FUNCTION rrnd (n1, n2) 'return real number between
  254.     rrnd = (n2 - n1) * RND + n1
  255.  
  256. FUNCTION distance (x1, y1, x2, y2)
  257.     distance = ((x1 - x2) ^ 2 + (y1 - y2) ^ 2) ^ .5
  258.  
  259.  


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #12 on: July 12, 2019, 02:43:13 am »
OK here is an easy way. Drawing the basic shape of knot and then drawing in "bridges" to show the overpass/underpass is probably the way human artists might draw the design:
Code: QB64: [Select]
  1. _TITLE "Celtic Knot 2" ' B+ developed in JB, translated to QB64 2019-07-11
  2. ' Instead of worrying about 2 circles (or arcs of them) for one ring, draw one circle with really wide pen!
  3. ' Draw shape twice with Outline color then Fill color (smaller width) then lay "Bridges"
  4. ' over sections for underpass/overpass. Thanks to tsh73 for demo of this method with another Celtic Knot.
  5.  
  6. CONST xmax = 720, ymax = 720, pi = 3.14159265, xc = xmax / 2, yc = ymax / 2
  7. SCREEN _NEWIMAGE(xmax, ymax, 32)
  8. _SCREENMOVE 100, 20
  9. COLOR , &HFF888888: CLS
  10. DIM r
  11. r = 350
  12. knot2 xc, yc, r, 30, &HFFFFFF00, &HFF008800
  13. CIRCLE (xc, yc), r
  14.  
  15. 'for best results: 50+ (pixels) and up for knotR to see details
  16. 'max thickness for knotR (impreceise overall radius) is about 10%
  17. SUB knot2 (x, y, knotR, thick, outlineC AS _UNSIGNED LONG, fillC AS _UNSIGNED LONG)
  18.     DIM hCenterX(6), hCenterY(6), hCX(6), hCY(6)
  19.     DIM w, hexAngle, h, hexD2, PD96, tD2
  20.     hexAngle = pi / 3: hexD2 = hexAngle / 2: PD96 = pi / 96 '<<<< all angles are refined to 96 parts of semicircle
  21.     w = knotR / 15: tD2 = thick / 2
  22.     FOR h = 1 TO 6
  23.         hCenterX(h) = x + 8 * w * COS(h * hexAngle + pi / 6)
  24.         hCenterY(h) = y + 8 * w * SIN(h * hexAngle + pi / 6)
  25.         hCX(h) = x + 14 * w * COS(h * hexAngle)
  26.         hCY(h) = y + 14 * w * SIN(h * hexAngle)
  27.     NEXT
  28.     FOR h = 1 TO 6
  29.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + pi / 6 + PD96 * 7, h * hexAngle + pi / 6 + PD96 * 185, tD2, outlineC
  30.         penArc hCX(h), hCY(h), 6 * w, h * hexAngle + PD96 * 55, h * hexAngle + PD96 * 137, tD2, outlineC
  31.     NEXT
  32.     FOR h = 1 TO 6
  33.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + pi / 6 + PD96 * 7, h * hexAngle + pi / 6 + PD96 * 185, tD2 - 1, fillC
  34.         penArc hCX(h), hCY(h), 6 * w, h * hexAngle + PD96 * 55, h * hexAngle + PD96 * 137, tD2 - 1, fillC
  35.     NEXT
  36.     'bridges
  37.     FOR h = 1 TO 6
  38.         'boarder color arc 7
  39.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + PD96 * 51, h * hexAngle + PD96 * 58, tD2, outlineC
  40.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + PD96 * 102, h * hexAngle + PD96 * 109, tD2, outlineC
  41.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + PD96 * 148, h * hexAngle + PD96 * 155, tD2, outlineC
  42.         penArc hCX(h), hCY(h), 6 * w, h * hexAngle + PD96 * 83, h * hexAngle + PD96 * 90, tD2, outlineC
  43.  
  44.         'fill color arc 2 before 3 after
  45.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + PD96 * 49, h * hexAngle + PD96 * 61, tD2 - 1, fillC
  46.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + PD96 * 99, h * hexAngle + PD96 * 111, tD2 - 1, fillC
  47.         penArc hCenterX(h), hCenterY(h), 6 * w, h * hexAngle + PD96 * 145, h * hexAngle + PD96 * 158, tD2 - 1, fillC
  48.         penArc hCX(h), hCY(h), 6 * w, h * hexAngle + PD96 * 80, h * hexAngle + PD96 * 92, tD2 - 1, fillC
  49.     NEXT
  50.  
  51. SUB penArc (x, y, r, raStart, raStop, penWidth, c AS _UNSIGNED LONG)
  52.     'x, y origin, r = radius, c = color
  53.     'raStart is first angle clockwise from due East = 0 degrees
  54.     ' arc will start drawing there and clockwise until raStop angle reached
  55.     DIM aStep, a
  56.     IF raStop < raStart THEN
  57.         penArc x, y, r, raStart, pi * 2, penWidth, c
  58.         penArc x, y, r, 0, raStop, penWidth, c
  59.     ELSE
  60.         aStep = 1 / (pi * r * 2)
  61.         FOR a = raStart TO raStop STEP aStep
  62.             fcirc x + r * COS(a), y + r * SIN(a), penWidth, c
  63.         NEXT
  64.     END IF
  65.  
  66. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  67.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  68.     DIM X AS INTEGER, Y AS INTEGER
  69.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  70.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  71.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  72.     WHILE X > Y
  73.         RadiusError = RadiusError + Y * 2 + 1
  74.         IF RadiusError >= 0 THEN
  75.             IF X <> Y + 1 THEN
  76.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  77.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  78.             END IF
  79.             X = X - 1
  80.             RadiusError = RadiusError - X * 2
  81.         END IF
  82.         Y = Y + 1
  83.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  84.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  85.     WEND
  86.  
  87.  

You still eyeball in the 'bridges" but you don't have to be pixel perfect and you dont PAINT. Problem with thickness > 10% of knot radius is that the bridges start to run into other overlapping or "underlapping" (yeah Pete, a new word in my vocabulary!) rings.
« Last Edit: July 12, 2019, 02:48:52 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Pattern Challenge 2
« Reply #13 on: July 12, 2019, 04:33:59 pm »
To show how effective this method is, I've drawn a Celtic Knot that has no straight lines nor circular arcs, just a single set of fancy sin/cos equations for x, y coordinates:

Code: QB64: [Select]
  1. _TITLE "Celtic Knot 3" ' B+ 2019-07-12
  2. ' To demo Celtic Knot mastery, attempt another one!
  3.  
  4. CONST xmax = 720, ymax = 720, pi = 3.14159265
  5. SCREEN _NEWIMAGE(xmax, ymax, 32)
  6. _SCREENMOVE 100, 20
  7.  
  8. DIM rr, w$
  9. FOR rr = 30 TO 350 STEP 20
  10.     CLS
  11.     Knot3 xmax / 2, ymax / 2, rr, .12 * rr, &HFFFFFFFF, &HFFFF000088
  12.     CIRCLE (xmax / 2, ymax / 2), rr, &HFFFFFF00
  13.     INPUT "OK ..."; w$
  14.  
  15. 'KnotR tested OK from 30 to 350, thick 1 to 13% knotR, at thick = 1 and 2 just see fillC.
  16. SUB Knot3 (xc, yc, knotR, thick, borderC AS _UNSIGNED LONG, fillC AS _UNSIGNED LONG)
  17.     DIM p, r, s, t, br, fr, x, y
  18.     CONST pm2d3 = pi * 2 / 3 '  all crucial points are 1/3 circle symmetric
  19.     r = knotR / 2.6: p = 35 * pi * r: s = 2 * pi / p
  20.     br = thick / 2 ' border radius
  21.     fr = br - 2 ' fill radius
  22.  
  23.     'outline whole design
  24.     FOR t = 0 TO 2 * _PI STEP s
  25.         x = xc + r * (COS(t) + COS(4 * t) / .7 + SIN(2 * t) / 12)
  26.         y = yc + r * (SIN(t) + SIN(4 * t) / .7 + COS(2 * t) / 12)
  27.         'PSET (x, y)
  28.         fcirc x, y, br, borderC
  29.         'code to help me find where in the 0 to 2*PI points are
  30.         'IF t = 0 THEN fcirc x, y, 3, &HFF0000FF
  31.         'IF ABS(t - pi) < .0025 THEN fcirc x, y, 3, &HFF000066
  32.     NEXT
  33.     'fill in design, same as above only smaller circle fills
  34.     FOR t = 0 TO 2 * _PI STEP s
  35.         x = xc + r * (COS(t) + COS(4 * t) / .7 + SIN(2 * t) / 12)
  36.         y = yc + r * (SIN(t) + SIN(4 * t) / .7 + COS(2 * t) / 12)
  37.         'PSET (x, y)
  38.         fcirc x, y, fr, fillC
  39.     NEXT
  40.     'over bridges  borders, locate over the top passes and draw circles over the over pass
  41.     FOR t = 0 TO 2 * _PI STEP s
  42.         x = xc + r * (COS(t) + COS(4 * t) / .7 + SIN(2 * t) / 12)
  43.         y = yc + r * (SIN(t) + SIN(4 * t) / .7 + COS(2 * t) / 12)
  44.  
  45.         IF ABS(t - pi * 51 / 384) < .11 THEN fcirc x, y, br, borderC
  46.         IF ABS(t - pi * 51 / 384 - pm2d3) < .11 THEN fcirc x, y, br, borderC
  47.         IF ABS(t - pi * 51 / 384 - 2 * pm2d3) < .11 THEN fcirc x, y, br, borderC
  48.  
  49.         IF ABS(t - pi * 111 / 384) < .11 THEN fcirc x, y, br, borderC
  50.         IF ABS(t - pi * 111 / 384 - pm2d3) < .11 THEN fcirc x, y, br, borderC
  51.         IF ABS(t - pi * 111 / 384 - 2 * pm2d3) < .11 THEN fcirc x, y, br, borderC
  52.  
  53.  
  54.         IF ABS(t - pi * 424 / 384) < .11 THEN fcirc x, y, br, borderC
  55.         IF ABS(t - pi * 424 / 384 - pm2d3) < .11 THEN fcirc x, y, br, borderC
  56.         IF ABS(t - pi * 424 / 384 + 1 * pm2d3) < .11 THEN fcirc x, y, br, borderC
  57.  
  58.         IF ABS(t - pi * 680 / 384) < .11 THEN fcirc x, y, br, borderC
  59.         IF ABS(t - pi * 680 / 384 + 2 * pm2d3) < .11 THEN fcirc x, y, br, borderC
  60.         IF ABS(t - pi * 680 / 384 + 1 * pm2d3) < .11 THEN fcirc x, y, br, borderC
  61.     NEXT
  62.     'over bridges fills , now draw farther up and down the bridge work with the fill color
  63.     FOR t = 0 TO 2 * _PI STEP s
  64.         x = xc + r * (COS(t) + COS(4 * t) / .7 + SIN(2 * t) / 12)
  65.         y = yc + r * (SIN(t) + SIN(4 * t) / .7 + COS(2 * t) / 12)
  66.  
  67.         IF ABS(t - pi * 51 / 384) < .14 THEN fcirc x, y, fr, fillC
  68.         IF ABS(t - pi * 51 / 384 - pm2d3) < .14 THEN fcirc x, y, fr, fillC
  69.         IF ABS(t - pi * 51 / 384 - 2 * pm2d3) < .14 THEN fcirc x, y, fr, fillC
  70.  
  71.         IF ABS(t - pi * 111 / 384) < .14 THEN fcirc x, y, fr, fillC
  72.         IF ABS(t - pi * 111 / 384 - pm2d3) < .14 THEN fcirc x, y, fr, fillC
  73.         IF ABS(t - pi * 111 / 384 - 2 * pm2d3) < .14 THEN fcirc x, y, fr, fillC
  74.  
  75.         IF ABS(t - pi * 424 / 384) < .14 THEN fcirc x, y, fr, fillC
  76.         IF ABS(t - pi * 424 / 384 - pm2d3) < .14 THEN fcirc x, y, fr, fillC
  77.         IF ABS(t - pi * 424 / 384 + 1 * pm2d3) < .14 THEN fcirc x, y, fr, fillC
  78.  
  79.         IF ABS(t - pi * 680 / 384) < .14 THEN fcirc x, y, fr, fillC
  80.         IF ABS(t - pi * 680 / 384 + 2 * pm2d3) < .14 THEN fcirc x, y, fr, fillC
  81.         IF ABS(t - pi * 680 / 384 + 1 * pm2d3) < .14 THEN fcirc x, y, fr, fillC
  82.     NEXT
  83.  
  84. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  85.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  86.     DIM X AS INTEGER, Y AS INTEGER
  87.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  88.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  89.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  90.     WHILE X > Y
  91.         RadiusError = RadiusError + Y * 2 + 1
  92.         IF RadiusError >= 0 THEN
  93.             IF X <> Y + 1 THEN
  94.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  95.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  96.             END IF
  97.             X = X - 1
  98.             RadiusError = RadiusError - X * 2
  99.         END IF
  100.         Y = Y + 1
  101.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  102.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  103.     WEND
  104.  
  105.  
« Last Edit: July 12, 2019, 06:03:31 pm by bplus »

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
Re: Pattern Challenge 2
« Reply #14 on: July 14, 2019, 07:28:58 am »
Wonderful Bplus! some very beautiful knots there....
Here are some 3D knots...
Code: QB64: [Select]
  1. 'http://paulbourke.net/geometry/knots/
  2. _TITLE "3D Knot [Press space for next knot]"
  3.  
  4. SCREEN _NEWIMAGE(700, 700, 32)
  5.  
  6. TYPE vec3
  7.     x AS SINGLE
  8.     y AS SINGLE
  9.     z AS SINGLE
  10.     SUB gluLookAt (BYVAL eyeX#, BYVAL eyeY#, BYVAL eyeZ#, BYVAL centerX#, BYVAL centerY#, BYVAL centerZ#, BYVAL upX#, BYVAL upY#, BYVAL upZ#)
  11.  
  12. DIM SHARED glAllow AS _BYTE, knot_type, ma
  13. knot_type = 1
  14. glAllow = -1
  15.  
  16.     k& = _KEYHIT
  17.     IF k& = ASC(" ") THEN
  18.         knot_type = knot_type + 1
  19.         ma = 0
  20.         IF knot_type > 7 THEN knot_type = 1
  21.     END IF
  22.     _LIMIT 60
  23.  
  24. SUB _GL ()
  25.     STATIC glInit, clock
  26.     ' static r, pos, theta, phi, beta
  27.  
  28.     IF NOT glAllow THEN EXIT SUB
  29.  
  30.     IF NOT glInit THEN
  31.         glInit = -1
  32.         aspect# = _WIDTH / _HEIGHT
  33.         _glViewport 0, 0, _WIDTH, _HEIGHT
  34.     END IF
  35.    
  36.     _glEnable _GL_DEPTH_TEST
  37.     _glDepthMask _GL_TRUE
  38.    
  39.     _glMatrixMode _GL_PROJECTION
  40.     _gluPerspective 45.0, aspect#, 1.0, 100.0
  41.    
  42.     _glMatrixMode _GL_MODELVIEW
  43.     ' gluLookAt 0,0,-1,0,0,0,0,1,0
  44.    
  45.     _glColor3f 1, 1, 1
  46.     _glTranslatef 0, 0, 0
  47.     _glRotatef clock * 90, 0, 1, 0
  48.     _glLineWidth 10.0
  49.    
  50.     SELECT CASE knot_type
  51.         CASE 7
  52.             _glBegin _GL_LINE_STRIP
  53.             FOR beta = 0 TO ma STEP .005
  54.                 r = .3 + .6 * SIN(6 * beta)
  55.                 theta = 2 * beta
  56.                 phi = _PI(.6) * SIN(12 * beta)
  57.                 x = r * COS(phi) * COS(theta)
  58.                 y = r * COS(phi) * SIN(theta)
  59.                 z = r * SIN(phi)
  60.                 _glColor3f map(x, -1, 1, 0, 1), map(y, -1, 1, 0, 1), map(z, -1, 1, 0, 1)
  61.                 _glVertex3f x, y, z
  62.             NEXT
  63.             _glEnd
  64.             IF ma <= _PI THEN ma = ma + .005
  65.         CASE 6
  66.             _glBegin _GL_LINE_STRIP
  67.             FOR beta = 0 TO ma STEP .005
  68.                 r = 1.2 * 0.6 * SIN(_PI(.5) * 6 * beta)
  69.                 theta = 4 * beta
  70.                 phi = _PI(.2) * SIN(6 * beta)
  71.                 x = r * COS(phi) * COS(theta)
  72.                 y = r * COS(phi) * SIN(theta)
  73.                 z = r * SIN(phi)
  74.                 _glColor3f map(x, -1, 1, 0, 1), map(y, -1, 1, 0, 1), map(z, -1, 1, 0, 1)
  75.                 _glVertex3f x, y, z
  76.             NEXT
  77.             _glEnd
  78.             IF ma <= _PI(2) THEN ma = ma + .005
  79.         CASE 5
  80.             k = 1
  81.             _glBegin _GL_LINE_STRIP
  82.             FOR u = 0 TO ma STEP .005
  83.                 x = COS(u) * (2 - COS(2 * u / (2 * k + 1))) / 5
  84.                 y = SIN(u) * (2 - COS(2 * u / (2 * k + 1))) / 5
  85.                 z = -SIN(2 * u / (2 * k + 1)) / 5
  86.                 _glColor3f map(x, -1, 1, 0, 1), map(y, -1, 1, 0, 1), map(z, -1, 1, 0, 1)
  87.                 _glVertex3f x, y, z
  88.             NEXT
  89.             _glEnd
  90.             IF ma < _PI(4 * k + 2) THEN ma = ma + .045
  91.         CASE 4
  92.             k = 2
  93.             _glBegin _GL_LINE_STRIP
  94.             FOR u = 0 TO ma STEP .005
  95.                 x = COS(u) * (2 - COS(2 * u / (2 * k + 1))) / 5
  96.                 y = SIN(u) * (2 - COS(2 * u / (2 * k + 1))) / 5
  97.                 z = -SIN(2 * u / (2 * k + 1)) / 5
  98.                 _glColor3f map(x, -1, 1, 0, 1), map(y, -1, 1, 0, 1), map(z, -1, 1, 0, 1)
  99.                 _glVertex3f x, y, z
  100.             NEXT
  101.             _glEnd
  102.             IF ma < _PI(4 * k + 2) THEN ma = ma + .045
  103.         CASE 3
  104.             k = 3
  105.             _glBegin _GL_LINE_STRIP
  106.             FOR u = 0 TO ma STEP .005
  107.                 x = COS(u) * (2 - COS(2 * u / (2 * k + 1))) / 5
  108.                 y = SIN(u) * (2 - COS(2 * u / (2 * k + 1))) / 5
  109.                 z = -SIN(2 * u / (2 * k + 1)) / 5
  110.                 _glColor3f map(x, -1, 1, 0, 1), map(y, -1, 1, 0, 1), map(z, -1, 1, 0, 1)
  111.                 _glVertex3f x, y, z
  112.             NEXT
  113.             _glEnd
  114.             IF ma < _PI(4 * k + 2) THEN ma = ma + .045
  115.         CASE 2
  116.             _glBegin _GL_LINE_STRIP
  117.             FOR u = 0 TO ma STEP .005
  118.                 x = (41 * COS(u) - 18 * SIN(u) - 83 * COS(2 * u) - 83 * SIN(2 * u) - 11 * COS(3 * u) + 27 * SIN(3 * u)) / 200
  119.                 y = (36 * COS(u) + 27 * SIN(u) - 113 * COS(2 * u) + 30 * SIN(2 * u) + 11 * COS(3 * u) - 27 * SIN(3 * u)) / 200
  120.                 z = (45 * SIN(u) - 30 * COS(2 * u) + 113 * SIN(2 * u) - 11 * COS(3 * u) + 27 * SIN(3 * u)) / 200
  121.                 _glColor3f map(x, -1, 1, 0, 1), map(y, -1, 1, 0, 1), map(z, -1, 1, 0, 1)
  122.                 _glVertex3f x, y, z
  123.             NEXT
  124.             _glEnd
  125.             IF ma < _PI(2) THEN ma = ma + .005
  126.         CASE 1
  127.             _glBegin _GL_LINE_STRIP
  128.             FOR u = 0 TO ma STEP .005
  129.                 x = (-22 * COS(u) - 128 * SIN(u) - 44 * COS(3 * u) - 78 * SIN(3 * u)) / 200
  130.                 y = (-10 * COS(2 * u) - 27 * SIN(2 * u) + 38 * COS(4 * u) + 46 * SIN(4 * u)) / 200
  131.                 z = (70 * COS(3 * u) - 40 * SIN(3 * u)) / 200
  132.                 _glColor3f map(x, -1, 1, 0, 1), map(y, -1, 1, 0, 1), map(z, -1, 1, 0, 1)
  133.                 _glVertex3f x, y, z
  134.             NEXT
  135.             _glEnd
  136.             IF ma < _PI(2) THEN ma = ma + .01
  137.     END SELECT
  138.     _glFlush
  139.    
  140.     clock = clock + .01
  141.  
  142. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  143.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  144.  
  145.  
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials