Skip to main content
Commonmark migration
Source Link

#BBC Basic, 8 polygons: 3,4,5,6,8,10,12,15 sides (also 60 sides)#

BBC Basic, 8 polygons: 3,4,5,6,8,10,12,15 sides (also 60 sides)

#BBC Basic, 8 polygons: 3,4,5,6,8,10,12,15 sides (also 60 sides)#

BBC Basic, 8 polygons: 3,4,5,6,8,10,12,15 sides (also 60 sides)

Bounty Ended with 100 reputation awarded by Martin Ender
added 2058 characters in body
Source Link
Level River St
  • 26.7k
  • 4
  • 37
  • 105

#BBC Basic, 8 polygons: 3,4,5,6,8,10,12,15 sides (currently half ofalso 60 sides) 5 polygons##

OK so I have a bug, but I thought I'd post what I have to show interest.Download emulator at http://www.bbcbasic.co.uk/bbcwin/download.html

The program does aI decided not to include 16 sides, simply because my pre-construction (per the first image) before asking for any user inputwas getting rather cluttered. This is sufficient to define at least 2 points on the main circle which correspond to adjacent vertices ofmore circles and a 3,4,6,8 or 12 sided figureline would be needed. The points are stored in a set of 99-element arrays, in which elements 0-59 are set aside for the circumference (thisBTW 17 sides is mainly for clarityvery complicated indeed, the octagon and 16-gon do not fit perfectly into 60 points so some flexibility is needed for themwould perhaps go best as a separate program.)

The user inputs the number of sides required, andI got more return for adding 2 circles to my original construction to make the time beingpentagon, a number correspondingas this also gave me access to the position in the array of the first of the two points (this will be automated10,15 and 60 sides.)

The program then loops through the process of drawing a circle centred on the second point that passes throug the first, and calculating the new intersection in order to walk its way round the main circle. The construction circles are drawn in blue, and the required polygon is drawn in red. Some unneccesary blue construction lines are drawn as well by default, but they can be suppressed. These lines actually form a star with a polygon at the centre, so alternatively they could be considered the required output (OP's opinion on that please.)

  GCOL 7                               :REM light grey
  z=999                                :REM width of display (in positive and negative direction)
  e=1                                  :REM enable automatic drawing of line through intersections of 2 circles
  DIM m(99),c(99),p(99),q(99),r(99)    :REM array dimensioning for lines and points
  REM lines have a gradient m and y-intercept c. Points have coordinates (p,q) and may be associated with a circle of radius r.

  REM PRECONSTRUCTION

  ORIGIN 500,500
  p(60)=0:q(60)=0                      :REM P60=centre of main circle
  p(15)=240:q(15)=70                   :REM P15=intersection main circle & horiz line
  t=FNr(60,15)                         :REM draw main circle, set radius, SQR(240^2+70^2)=250 units (125 pixels)
  t=FNl(1,60,15)                       :REM L1=horizontal through main circle
  t=FNc(15,45,1,60,-1)                 :REM define P45 as other intersection of main cir and horiz line. overwrite P15 with itself.

  t=FNr(15,45):t=FNr(45,15)            :REM draw 2 large circles to prepare to bisect L1
  t=FNc(61,62,2,45,15)                 :REM bisect L1, forming line L2 and two new points
  t=FNc(30,0,2,60,-1)                  :REM define points P0 and P30 on the crossings of L2 and main circle
  t=FNr(30,60):t=FNc(40,20,3,60,30)    :REM draw circles at P30, and line L3 through intersections with main circle, to define 2 more points
  t=FNr(15,60):t=FNc(25,5,4,60,15)     :REM draw circles at P15, and line L4 through intersections with main circle, to define 2 more points
  t=FNx(63,3,4):t=FNl(5,63,60)         :REM draw L5 at 45 degrees
  t=FNc(64,53,5,60,-1)                 :REM define where L5 cuts the main circle

  e=0                                  :REM disable automatic line drawing through intersections of 2 circles
  GCOL 11                              :REM change to light yellow for the 5 sided preconstruction
  t=FNx(65,1,4):t=FNr(65,0)            :REM draw a circle of radius sqrt(5) at intersection of L1 and L4
  t=FNc(66,67,1,65,-1)                 :REM find point of intersection of this circle with L1
  t=FNr(0,67)                          :REM draw a circle centred at point 0 through that intersection
  t=FNc(36,24,6,60,0)                  :REM find the intersections of this circle with the main circle


  REM USER INPUT AND POLYGON DRAWING

  INPUT d
  g=ASC(MID$("  @@XT u X @  T",d))-64  :REM sides,first point: 3,0; 4,0; 5,24; 6,20; 8,53; 10,24; 12,0; 15,20
  IF d=60 THEN g=24                    :REM bonus polygon 60, first point 24
  FORf=0TOd
    GCOL12                             :REM blue
    h=(g+60DIVd)MOD60                  :REM from array index for first point, calculate array index for second point
    t=FNr(h,g)                         :REM draw circle centred on second point through first point
    t=FNc((h+60DIVd)MOD60,99,99,60,h)  :REM calculate the position of the other intersection of circle with main circle. Assign to new point.
    GCOL9                              :REM red
    LINEp(g),q(g),p(h),q(h)            :REM draw the side
    g=h                                :REM advance through the array
  NEXT

  END

  REM FUNCTIONS

  REM line through a and b
  DEFFNl(n,a,b)
  m(n)=(q(a)-q(b))/(p(a)-p(b))
  c(n)=q(a)-m(n)*p(a)
  LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z
  =n

  REM radius of circle at point a passing through point b
  DEFFNr(a,b)
  r(a)=SQR((p(a)-p(b))^2+(q(a)-q(b))^2)
  CIRCLEp(a),q(a),r(a)
  =a

  REM intersection of 2 lines: ma*x+ca=mb*x+cb so (ma-mb)x=cb-ca
  DEFFNx(n,a,b)
  p(n)=(c(b)-c(a))/(m(a)-m(b))
  q(n)=m(a)*p(n)+c(a)
  =n

  REM intersection of 2 circles a&b (if b>-1.) The first step is calculating the line through the intersections
  REM if b < 0 the first part of the function is ignored, and the function moves directly to calculating intersection of circle and line.
  REM inspiration from http://math.stackexchange.com/a/256123/137034

  DEFFNc(i,j,n,a,b)
  IF b>-1 c(n)=((r(a)^2-r(b)^2)-(p(a)^2-p(b)^2)-(q(a)^2-q(b)^2))/2/(q(b)-q(a)):m(n)=(p(a)-p(b))/(q(b)-q(a)):IF e LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z

  REM intersection of circle and line
  REM (mx+ c-q)^2+(x-p)^2=r^2
  REM (m^2+1)x^2 + 2*(m*(c-q)-p)x + (c-q)^2+p^2-r^2=0
  REM quadratic formula for ux^2+vx+w=0 is x=-v/2u +/- SQR(v^2-4*u*w)/2u or x= v/2u +/- SQR((v/2u)^2 - w/u)

  u=m(n)^2+1
  v=-(m(n)*(c(n)-q(a))-p(a))/u               :REM here v corresponds to v/2u in the formula above
  w=SQR(v^2-((c(n)-q(a))^2+p(a)^2-r(a)^2)/u)


  s=SGN(c(n)+m(n)*v-q(a)):IF s=0 THEN s=1    :REM sign of s depends whether midpoint between 2 points to be found is above centre of circle a
  p(i)=v+s*w:q(i)=m(n)*p(i)+c(n)             :REM find point that is clockwise respect to a
  p(j)=v-s*w:q(j)=m(n)*p(j)+c(n)             :REM find point that is anticlockwise respect to a
  =n

There are of course 2 intersections betweenThe program does a pre-construction before asking for any given pairuser input. This is sufficient to define at least 2 points on the main circle which correspond to adjacent vertices of overlapping circlesa 3, and4,5,6,8,10,12,15 or 60 sided figure. The points are stored in ordera set of 99-element arrays, in which elements 0-59 are set aside for equally spaced points around the loop to work correctlycircumference. This is mainly for clarity, the function which calculates the intersections must return these in a consistent orderoctagon does not fit perfectly into 60 points so some flexibility is needed there (supposed to be anticlockwise intersection then clockwise intersection as viewed from the centre ofand also for the first named circle16-gon if it were included.) There is a bug in the code that calculates the order of these two points insideThe image looks like the functionimage below, thereforein white and grey, with only half the polygon is displayedtwo circles in yellow being exclusively dedicated to shapes with multiples of 5 sides. My first attemptSee http://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Inscribed_in_a_Circle_240px.gif for my preferred pentagon drawing method. The jaunty angle is to fix this produced a division by zero erroravoid vertical lines, so I will review it again later this weekendas the program cannot handle infinite gradients.

Once the bug is fixed, it should be reasonably simple to add the preconstructions required for the shapes with numbers of sides divisible by 5 (only 2 more circles and 2 more points are required.)enter image description here

enter image description here The user inputs a number d for the number of sides required. The program looks up in the array the index of the first of the two points (the next one is 60/d away in a clockwise direction.)

  z=999                             :REM width of display (in positive and negative direction)
  DIM m(99),c(99),p(99),q(99),r(99) :REM array declaration for lines and points
  REM lines have a gradient m and y-intercept c. Points have coordinates (p,q) and may be associated with a circle of radius r.

  ORIGIN 500,500
  p(60)=0:q(60)=0                   :REM P60=centre of main circle
  p(15)=240:q(15)=70                :REM P15=intersection main circle & horiz line
  t=FNr(60,15)                      :REM draw main circle, set radius, SQR(240^2+70^2)=250 units (125 pixels)
  t=FNl(1,60,15)                    :REM L1=horizontal through main circle
  t=FNc(15,45,1,60,-1)              :REM define P45 as other intersection of main cir and horiz line. overwrite P15 with itself.
  t=FNr(15,45):t=FNr(45,15)         :REM draw 2 large circles to prepare to bisect L1
  t=FNc(61,62,2,45,15)              :REM bisect L1, forming line L2 and two new points
  t=FNc(0,30,2,60,-1)               :REM define points P0 and P30 on the crossings of L2 and main circle
  t=FNr(30,60):t=FNc(20,40,3,60,30) :REM draw circles at P30, and line L3 through intersections with main circle, to define 2 more points
  t=FNr(15,60):t=FNc(5,25,4,60,15)  :REM draw circles at P15, and line L4 through intersections with main circle, to define 2 more points
  t=FNx(63,3,4):t=FNl(5,63,60)      :REM draw L5 at 45 degrees
  t=FNc(53,64,5,60,-1)              :REM define where L5 cuts the main circle


  INPUT d,g
  FORf=0TOd
    GCOL12
    h=(g+60DIVd)MOD60
    t=FNr(h,g)
    t=FNc(99,(h+60DIVd)MOD60,99,60,h)
    GCOL9
    LINEp(g),q(g),p(h),q(h)
    g=h
  NEXT



  END

  REM line through a and b
  DEFFNl(n,a,b)
  m(n)=(q(a)-q(b))/(p(a)-p(b))
  c(n)=q(a)-m(n)*p(a)
  LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z
  =n

  REM radius of circle at point a passing through point b
  DEFFNr(a,b)
  r(a)=SQR((p(a)-p(b))^2+(q(a)-q(b))^2)
  CIRCLEp(a),q(a),r(a)
  =a

  REM intersection of 2 lines: ma*x+ca=mb*x+cb so (ma-mb)x=cb-ca
  DEFFNx(n,a,b)
  p(n)=(c(b)-c(a))/(m(a)-m(b))
  q(n)=m(a)*p(n)+c(a)
  =n

  REM intersection of 2 circles a&b (if b>-1.) The first step is calculating the line through the intersections
  DEFFNc(i,j,n,a,b)
  IF b>-1 c(n)=((r(a)^2-r(b)^2)-(p(a)^2-p(b)^2)-(q(a)^2-q(b)^2))/2/(q(b)-q(a)):m(n)=(p(a)-p(b))/(q(b)-q(a)):LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z

  REM intersection of line and circle (if b < 0 the first part of the function is ignored.)
  REM inspiration from http://math.stackexchange.com/a/256123/137034
  REM (mx+ c-q)^2+(x-p)^2=r^2
  REM (m^2+1)x^2 + 2*(m*(c-q)-p)x + (c-q)^2+p^2-r^2=0
  REM quadratic formula for ux^2+vx+w=0 is x=-v/2u +/- SQR(v^2-4*u*w)/2u or x= v/2u +/- SQR((v/2u)^2 - w/u)

  u=m(n)^2+1
  v=-(m(n)*(c(n)-q(a))-p(a))/u               :REM here v corresponds to v/2u in the formula above
  w=SQR(v^2-((c(n)-q(a))^2+p(a)^2-r(a)^2)/u)


  s=SGN(m(n)+c(n)*p(a)-q(a))                 :REM BUG HERE!
  p(i)=v+s*w:q(i)=m(n)*p(i)+c(n)
  p(j)=v-s*w:q(j)=m(n)*p(j)+c(n)
  =n

The program then loops through the process of drawing a circle centred on the second point that passes throug the first, and calculating the new intersection in order to walk its way round the main circle. The construction circles are drawn in blue, and the required polygon is drawn in red. The final images look like this.

I'm quite pleased with them. BBC Basic performs the calculations accurately enough. However its apparent (particularly with 15 and 60 sides) that BBC Basic tends to draw circles with a slightly smaller radius than it should.

enter image description here

#BBC Basic, (currently half of) 5 polygons#

OK so I have a bug, but I thought I'd post what I have to show interest.

The program does a pre-construction (per the first image) before asking for any user input. This is sufficient to define at least 2 points on the main circle which correspond to adjacent vertices of a 3,4,6,8 or 12 sided figure. The points are stored in a set of 99-element arrays, in which elements 0-59 are set aside for the circumference (this is mainly for clarity, the octagon and 16-gon do not fit perfectly into 60 points so some flexibility is needed for them.)

The user inputs the number of sides required, and for the time being, a number corresponding to the position in the array of the first of the two points (this will be automated.)

The program then loops through the process of drawing a circle centred on the second point that passes throug the first, and calculating the new intersection in order to walk its way round the main circle. The construction circles are drawn in blue, and the required polygon is drawn in red. Some unneccesary blue construction lines are drawn as well by default, but they can be suppressed. These lines actually form a star with a polygon at the centre, so alternatively they could be considered the required output (OP's opinion on that please.)

There are of course 2 intersections between any given pair of overlapping circles, and in order for the loop to work correctly, the function which calculates the intersections must return these in a consistent order (supposed to be anticlockwise intersection then clockwise intersection as viewed from the centre of the first named circle.) There is a bug in the code that calculates the order of these two points inside the function, therefore only half the polygon is displayed. My first attempt to fix this produced a division by zero error, so I will review it again later this weekend.

Once the bug is fixed, it should be reasonably simple to add the preconstructions required for the shapes with numbers of sides divisible by 5 (only 2 more circles and 2 more points are required.)

enter image description here

  z=999                             :REM width of display (in positive and negative direction)
  DIM m(99),c(99),p(99),q(99),r(99) :REM array declaration for lines and points
  REM lines have a gradient m and y-intercept c. Points have coordinates (p,q) and may be associated with a circle of radius r.

  ORIGIN 500,500
  p(60)=0:q(60)=0                   :REM P60=centre of main circle
  p(15)=240:q(15)=70                :REM P15=intersection main circle & horiz line
  t=FNr(60,15)                      :REM draw main circle, set radius, SQR(240^2+70^2)=250 units (125 pixels)
  t=FNl(1,60,15)                    :REM L1=horizontal through main circle
  t=FNc(15,45,1,60,-1)              :REM define P45 as other intersection of main cir and horiz line. overwrite P15 with itself.
  t=FNr(15,45):t=FNr(45,15)         :REM draw 2 large circles to prepare to bisect L1
  t=FNc(61,62,2,45,15)              :REM bisect L1, forming line L2 and two new points
  t=FNc(0,30,2,60,-1)               :REM define points P0 and P30 on the crossings of L2 and main circle
  t=FNr(30,60):t=FNc(20,40,3,60,30) :REM draw circles at P30, and line L3 through intersections with main circle, to define 2 more points
  t=FNr(15,60):t=FNc(5,25,4,60,15)  :REM draw circles at P15, and line L4 through intersections with main circle, to define 2 more points
  t=FNx(63,3,4):t=FNl(5,63,60)      :REM draw L5 at 45 degrees
  t=FNc(53,64,5,60,-1)              :REM define where L5 cuts the main circle


  INPUT d,g
  FORf=0TOd
    GCOL12
    h=(g+60DIVd)MOD60
    t=FNr(h,g)
    t=FNc(99,(h+60DIVd)MOD60,99,60,h)
    GCOL9
    LINEp(g),q(g),p(h),q(h)
    g=h
  NEXT



  END

  REM line through a and b
  DEFFNl(n,a,b)
  m(n)=(q(a)-q(b))/(p(a)-p(b))
  c(n)=q(a)-m(n)*p(a)
  LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z
  =n

  REM radius of circle at point a passing through point b
  DEFFNr(a,b)
  r(a)=SQR((p(a)-p(b))^2+(q(a)-q(b))^2)
  CIRCLEp(a),q(a),r(a)
  =a

  REM intersection of 2 lines: ma*x+ca=mb*x+cb so (ma-mb)x=cb-ca
  DEFFNx(n,a,b)
  p(n)=(c(b)-c(a))/(m(a)-m(b))
  q(n)=m(a)*p(n)+c(a)
  =n

  REM intersection of 2 circles a&b (if b>-1.) The first step is calculating the line through the intersections
  DEFFNc(i,j,n,a,b)
  IF b>-1 c(n)=((r(a)^2-r(b)^2)-(p(a)^2-p(b)^2)-(q(a)^2-q(b)^2))/2/(q(b)-q(a)):m(n)=(p(a)-p(b))/(q(b)-q(a)):LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z

  REM intersection of line and circle (if b < 0 the first part of the function is ignored.)
  REM inspiration from http://math.stackexchange.com/a/256123/137034
  REM (mx+ c-q)^2+(x-p)^2=r^2
  REM (m^2+1)x^2 + 2*(m*(c-q)-p)x + (c-q)^2+p^2-r^2=0
  REM quadratic formula for ux^2+vx+w=0 is x=-v/2u +/- SQR(v^2-4*u*w)/2u or x= v/2u +/- SQR((v/2u)^2 - w/u)

  u=m(n)^2+1
  v=-(m(n)*(c(n)-q(a))-p(a))/u               :REM here v corresponds to v/2u in the formula above
  w=SQR(v^2-((c(n)-q(a))^2+p(a)^2-r(a)^2)/u)


  s=SGN(m(n)+c(n)*p(a)-q(a))                 :REM BUG HERE!
  p(i)=v+s*w:q(i)=m(n)*p(i)+c(n)
  p(j)=v-s*w:q(j)=m(n)*p(j)+c(n)
  =n

#BBC Basic, 8 polygons: 3,4,5,6,8,10,12,15 sides (also 60 sides)#

Download emulator at http://www.bbcbasic.co.uk/bbcwin/download.html

I decided not to include 16 sides, simply because my pre-construction was getting rather cluttered. 2 more circles and a line would be needed. BTW 17 sides is very complicated indeed, and would perhaps go best as a separate program.

I got more return for adding 2 circles to my original construction to make the pentagon, as this also gave me access to 10,15 and 60 sides.

  GCOL 7                               :REM light grey
  z=999                                :REM width of display (in positive and negative direction)
  e=1                                  :REM enable automatic drawing of line through intersections of 2 circles
  DIM m(99),c(99),p(99),q(99),r(99)    :REM array dimensioning for lines and points
  REM lines have a gradient m and y-intercept c. Points have coordinates (p,q) and may be associated with a circle of radius r.

  REM PRECONSTRUCTION

  ORIGIN 500,500
  p(60)=0:q(60)=0                      :REM P60=centre of main circle
  p(15)=240:q(15)=70                   :REM P15=intersection main circle & horiz line
  t=FNr(60,15)                         :REM draw main circle, set radius, SQR(240^2+70^2)=250 units (125 pixels)
  t=FNl(1,60,15)                       :REM L1=horizontal through main circle
  t=FNc(15,45,1,60,-1)                 :REM define P45 as other intersection of main cir and horiz line. overwrite P15 with itself.

  t=FNr(15,45):t=FNr(45,15)            :REM draw 2 large circles to prepare to bisect L1
  t=FNc(61,62,2,45,15)                 :REM bisect L1, forming line L2 and two new points
  t=FNc(30,0,2,60,-1)                  :REM define points P0 and P30 on the crossings of L2 and main circle
  t=FNr(30,60):t=FNc(40,20,3,60,30)    :REM draw circles at P30, and line L3 through intersections with main circle, to define 2 more points
  t=FNr(15,60):t=FNc(25,5,4,60,15)     :REM draw circles at P15, and line L4 through intersections with main circle, to define 2 more points
  t=FNx(63,3,4):t=FNl(5,63,60)         :REM draw L5 at 45 degrees
  t=FNc(64,53,5,60,-1)                 :REM define where L5 cuts the main circle

  e=0                                  :REM disable automatic line drawing through intersections of 2 circles
  GCOL 11                              :REM change to light yellow for the 5 sided preconstruction
  t=FNx(65,1,4):t=FNr(65,0)            :REM draw a circle of radius sqrt(5) at intersection of L1 and L4
  t=FNc(66,67,1,65,-1)                 :REM find point of intersection of this circle with L1
  t=FNr(0,67)                          :REM draw a circle centred at point 0 through that intersection
  t=FNc(36,24,6,60,0)                  :REM find the intersections of this circle with the main circle


  REM USER INPUT AND POLYGON DRAWING

  INPUT d
  g=ASC(MID$("  @@XT u X @  T",d))-64  :REM sides,first point: 3,0; 4,0; 5,24; 6,20; 8,53; 10,24; 12,0; 15,20
  IF d=60 THEN g=24                    :REM bonus polygon 60, first point 24
  FORf=0TOd
    GCOL12                             :REM blue
    h=(g+60DIVd)MOD60                  :REM from array index for first point, calculate array index for second point
    t=FNr(h,g)                         :REM draw circle centred on second point through first point
    t=FNc((h+60DIVd)MOD60,99,99,60,h)  :REM calculate the position of the other intersection of circle with main circle. Assign to new point.
    GCOL9                              :REM red
    LINEp(g),q(g),p(h),q(h)            :REM draw the side
    g=h                                :REM advance through the array
  NEXT

  END

  REM FUNCTIONS

  REM line through a and b
  DEFFNl(n,a,b)
  m(n)=(q(a)-q(b))/(p(a)-p(b))
  c(n)=q(a)-m(n)*p(a)
  LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z
  =n

  REM radius of circle at point a passing through point b
  DEFFNr(a,b)
  r(a)=SQR((p(a)-p(b))^2+(q(a)-q(b))^2)
  CIRCLEp(a),q(a),r(a)
  =a

  REM intersection of 2 lines: ma*x+ca=mb*x+cb so (ma-mb)x=cb-ca
  DEFFNx(n,a,b)
  p(n)=(c(b)-c(a))/(m(a)-m(b))
  q(n)=m(a)*p(n)+c(a)
  =n

  REM intersection of 2 circles a&b (if b>-1.) The first step is calculating the line through the intersections
  REM if b < 0 the first part of the function is ignored, and the function moves directly to calculating intersection of circle and line.
  REM inspiration from http://math.stackexchange.com/a/256123/137034

  DEFFNc(i,j,n,a,b)
  IF b>-1 c(n)=((r(a)^2-r(b)^2)-(p(a)^2-p(b)^2)-(q(a)^2-q(b)^2))/2/(q(b)-q(a)):m(n)=(p(a)-p(b))/(q(b)-q(a)):IF e LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z

  REM intersection of circle and line
  REM (mx+ c-q)^2+(x-p)^2=r^2
  REM (m^2+1)x^2 + 2*(m*(c-q)-p)x + (c-q)^2+p^2-r^2=0
  REM quadratic formula for ux^2+vx+w=0 is x=-v/2u +/- SQR(v^2-4*u*w)/2u or x= v/2u +/- SQR((v/2u)^2 - w/u)

  u=m(n)^2+1
  v=-(m(n)*(c(n)-q(a))-p(a))/u               :REM here v corresponds to v/2u in the formula above
  w=SQR(v^2-((c(n)-q(a))^2+p(a)^2-r(a)^2)/u)


  s=SGN(c(n)+m(n)*v-q(a)):IF s=0 THEN s=1    :REM sign of s depends whether midpoint between 2 points to be found is above centre of circle a
  p(i)=v+s*w:q(i)=m(n)*p(i)+c(n)             :REM find point that is clockwise respect to a
  p(j)=v-s*w:q(j)=m(n)*p(j)+c(n)             :REM find point that is anticlockwise respect to a
  =n

The program does a pre-construction before asking for any user input. This is sufficient to define at least 2 points on the main circle which correspond to adjacent vertices of a 3,4,5,6,8,10,12,15 or 60 sided figure. The points are stored in a set of 99-element arrays, in which elements 0-59 are set aside for equally spaced points around the circumference. This is mainly for clarity, the octagon does not fit perfectly into 60 points so some flexibility is needed there (and also for the 16-gon if it were included.) The image looks like the image below, in white and grey, with only the two circles in yellow being exclusively dedicated to shapes with multiples of 5 sides. See http://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Inscribed_in_a_Circle_240px.gif for my preferred pentagon drawing method. The jaunty angle is to avoid vertical lines, as the program cannot handle infinite gradients.

enter image description here

The user inputs a number d for the number of sides required. The program looks up in the array the index of the first of the two points (the next one is 60/d away in a clockwise direction.)

The program then loops through the process of drawing a circle centred on the second point that passes throug the first, and calculating the new intersection in order to walk its way round the main circle. The construction circles are drawn in blue, and the required polygon is drawn in red. The final images look like this.

I'm quite pleased with them. BBC Basic performs the calculations accurately enough. However its apparent (particularly with 15 and 60 sides) that BBC Basic tends to draw circles with a slightly smaller radius than it should.

enter image description here

Source Link
Level River St
  • 26.7k
  • 4
  • 37
  • 105

#BBC Basic, (currently half of) 5 polygons#

OK so I have a bug, but I thought I'd post what I have to show interest.

The program does a pre-construction (per the first image) before asking for any user input. This is sufficient to define at least 2 points on the main circle which correspond to adjacent vertices of a 3,4,6,8 or 12 sided figure. The points are stored in a set of 99-element arrays, in which elements 0-59 are set aside for the circumference (this is mainly for clarity, the octagon and 16-gon do not fit perfectly into 60 points so some flexibility is needed for them.)

The user inputs the number of sides required, and for the time being, a number corresponding to the position in the array of the first of the two points (this will be automated.)

The program then loops through the process of drawing a circle centred on the second point that passes throug the first, and calculating the new intersection in order to walk its way round the main circle. The construction circles are drawn in blue, and the required polygon is drawn in red. Some unneccesary blue construction lines are drawn as well by default, but they can be suppressed. These lines actually form a star with a polygon at the centre, so alternatively they could be considered the required output (OP's opinion on that please.)

There are of course 2 intersections between any given pair of overlapping circles, and in order for the loop to work correctly, the function which calculates the intersections must return these in a consistent order (supposed to be anticlockwise intersection then clockwise intersection as viewed from the centre of the first named circle.) There is a bug in the code that calculates the order of these two points inside the function, therefore only half the polygon is displayed. My first attempt to fix this produced a division by zero error, so I will review it again later this weekend.

Once the bug is fixed, it should be reasonably simple to add the preconstructions required for the shapes with numbers of sides divisible by 5 (only 2 more circles and 2 more points are required.)

enter image description here

  z=999                             :REM width of display (in positive and negative direction)
  DIM m(99),c(99),p(99),q(99),r(99) :REM array declaration for lines and points
  REM lines have a gradient m and y-intercept c. Points have coordinates (p,q) and may be associated with a circle of radius r.

  ORIGIN 500,500
  p(60)=0:q(60)=0                   :REM P60=centre of main circle
  p(15)=240:q(15)=70                :REM P15=intersection main circle & horiz line
  t=FNr(60,15)                      :REM draw main circle, set radius, SQR(240^2+70^2)=250 units (125 pixels)
  t=FNl(1,60,15)                    :REM L1=horizontal through main circle
  t=FNc(15,45,1,60,-1)              :REM define P45 as other intersection of main cir and horiz line. overwrite P15 with itself.
  t=FNr(15,45):t=FNr(45,15)         :REM draw 2 large circles to prepare to bisect L1
  t=FNc(61,62,2,45,15)              :REM bisect L1, forming line L2 and two new points
  t=FNc(0,30,2,60,-1)               :REM define points P0 and P30 on the crossings of L2 and main circle
  t=FNr(30,60):t=FNc(20,40,3,60,30) :REM draw circles at P30, and line L3 through intersections with main circle, to define 2 more points
  t=FNr(15,60):t=FNc(5,25,4,60,15)  :REM draw circles at P15, and line L4 through intersections with main circle, to define 2 more points
  t=FNx(63,3,4):t=FNl(5,63,60)      :REM draw L5 at 45 degrees
  t=FNc(53,64,5,60,-1)              :REM define where L5 cuts the main circle


  INPUT d,g
  FORf=0TOd
    GCOL12
    h=(g+60DIVd)MOD60
    t=FNr(h,g)
    t=FNc(99,(h+60DIVd)MOD60,99,60,h)
    GCOL9
    LINEp(g),q(g),p(h),q(h)
    g=h
  NEXT



  END

  REM line through a and b
  DEFFNl(n,a,b)
  m(n)=(q(a)-q(b))/(p(a)-p(b))
  c(n)=q(a)-m(n)*p(a)
  LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z
  =n

  REM radius of circle at point a passing through point b
  DEFFNr(a,b)
  r(a)=SQR((p(a)-p(b))^2+(q(a)-q(b))^2)
  CIRCLEp(a),q(a),r(a)
  =a

  REM intersection of 2 lines: ma*x+ca=mb*x+cb so (ma-mb)x=cb-ca
  DEFFNx(n,a,b)
  p(n)=(c(b)-c(a))/(m(a)-m(b))
  q(n)=m(a)*p(n)+c(a)
  =n

  REM intersection of 2 circles a&b (if b>-1.) The first step is calculating the line through the intersections
  DEFFNc(i,j,n,a,b)
  IF b>-1 c(n)=((r(a)^2-r(b)^2)-(p(a)^2-p(b)^2)-(q(a)^2-q(b)^2))/2/(q(b)-q(a)):m(n)=(p(a)-p(b))/(q(b)-q(a)):LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z

  REM intersection of line and circle (if b < 0 the first part of the function is ignored.)
  REM inspiration from http://math.stackexchange.com/a/256123/137034
  REM (mx+ c-q)^2+(x-p)^2=r^2
  REM (m^2+1)x^2 + 2*(m*(c-q)-p)x + (c-q)^2+p^2-r^2=0
  REM quadratic formula for ux^2+vx+w=0 is x=-v/2u +/- SQR(v^2-4*u*w)/2u or x= v/2u +/- SQR((v/2u)^2 - w/u)

  u=m(n)^2+1
  v=-(m(n)*(c(n)-q(a))-p(a))/u               :REM here v corresponds to v/2u in the formula above
  w=SQR(v^2-((c(n)-q(a))^2+p(a)^2-r(a)^2)/u)


  s=SGN(m(n)+c(n)*p(a)-q(a))                 :REM BUG HERE!
  p(i)=v+s*w:q(i)=m(n)*p(i)+c(n)
  p(j)=v-s*w:q(j)=m(n)*p(j)+c(n)
  =n