Het rollende cirkel probleem


Download programma
Download Delphi(7) project

Onlangs ontving ik onderstaand probleem:



Voordat je verder leest stel ik voor eerst zelf een antwoord te geven.

Theorie

We kunnen de omtrek van cirkel B uitstrekken en cirkel A over deze rechte lijn rollen.



Dan zien we 3 omwentelingen.
Voor wie in de wiskunde geïnteresseerd is:



De beweging van het rode punt is gegeven door een parameter functie :
x en y zijn beide afhankelijk van de draaihoek α.
Echter, klopt dit nog als cirkel A over B rolt?
Verrassend antwoord: nee.
Bekijk wat meetkunde hierna:



Cirkel A heeft vier omwentelingen nodig om geheel over de buitenzijde van B te rollen.
Ter illustratie van dit verschijnsel heb ik een Delphi programmaatje geschreven.
Een paar opties zijn toegevoegd:
    - buiten- of binnenkant van cirkel B
    - Diameter ratios 1:1 , 1:2 , 1:3 , 1 : 4
De theorie van A als binnencirkel laat ik aan de lezer.

Programma




Selecteer de diameter ratio.
Klik op het plaatje linksboven om A aan de buiten- of binnenkant van B te plaatsen.
Druk op GO om cirkel A over B te rollen..

Programma beschrijving

Tekenen gebeurt in bitmap map.
Map wordt gekopieerd naar paintbox1 op het main form om zichtbaar te worden.
De afbeelding wordt 100x per seconde bijgewerkt.
Het label links onder toont het percentage van de tijd die de processor nodig heeft.
Zie het tweede plaatje hiervoor.
Hoek α start op 0 en hoogt per stap op met 0.005 radialen.
Een hele omwenteling kost 2π/0.005 = 1250 stappen.
Bij honderd stappen per seconde is de omloopstijd 12.5 seconden.
Voor een nieuw plaatje is nodig:
    - wissen van de bitmap
    - cirkel B tekenen met de markeringen die overeenkomen met de spaken van cirkel A.
    - cirkel A tekenen met de spaken.
    - map naar de paintbox kopiëren: form1.paintbox1.canvas.draw(0,0,map)
Constanten and variabelen
type Tmode = (modeIn,modeOut);
     Tradius = record
                rad1 : word;   //radius of circle B
                rad2 : word;   //radius of circle A
                xamp  : byte;  //rotation angle magnifier (=4 if ratio is 1:3)
               end;

Const pi2 = 2*pi;
      pi04 = pi/4;
      radOut : array[0..3] of Tradius =         //outer circle mode radius
               ((rad1:100 ;rad2:100 ;xamp:2),   //1:1
                (rad1:150 ;rad2: 75 ;xamp:3 ),  //1:2
                (rad1:180 ;rad2: 60 ;xamp:4 ),  //1:3
                (rad1:200 ;rad2: 50 ;xamp:5));  //1:4
      radIn  : array[0..3] of Tradius =         //inner circle mode radius    
               ((rad1:300 ;rad2:300 ;xamp:0),
                (rad1:300 ;rad2:150 ;xamp:1),
                (rad1:300 ;rad2:100 ;xamp:2),
                (rad1:300 ;rad2: 75 ;xamp:3));
var map : Tbitmap;
    cx,cy : word;     //center of circle B, measured in pixels
    sx,sy : word;     //center of circle A (satellite)
    radius1,radius2 : word; //radius of circles B and A, preset from constants array
    angle : double;   //rotation angle of circle A center around B center
    amp : byte;       //rotating angle magnifier, preset from constants array  
    GOflag : boolean; //control rolling 
    mode : Tmode = modeOut; //out- or inside circle A
    ModeEntered : boolean;  //for mode button enter / leave control  
    frotation : double;     //circle A rotation in floating point format
    rotations : byte;       //number of rotations of circle A
Procedure GOproc controleert het rollen.
procedure GOproc;
var t1,t2 : Int64;
begin
 repeat
  t1 := getCPUticks;  //start CPU time
  paintmap;           //repaint image and copy to paintbox1
  t2 := getCPUticks;  //stop CPU time
  form1.proctimelabel.caption := formatfloat('0.#',proctime(t2-t1)*0.01);//% of 10msec.
  repeat
   application.processmessages;  //GOflag may be cleared by GObutton release
   t2 := getCPUticks;
  until proctime(t2-t1) > 10000;  //wait for 10 milliseconds since t1
  if angle >= pi2 then angle := angle - pi2;
  angle := angle + 0.005;
  incRotation(0.005);            //rotation increment for small circle A
  GOflag := GOflag and (angle <= pi2);   
 until GOflag = false;
end;
Opmerking: GObutton is een TLabel component.
Die ziet er uit als een button door het tekeken van een rechthoek eromheen op het canvas van het form.
OnEnter, OnLeave, OnMouseDown en OnmouseUp events veranderen de rechthoek.

Ik toon hier niet de procedures voor het tekenwerk.
Voor details verwijs ik naar de source code.

Conclusie

De antwoorden (zie eerste figuur) zijn incompleet.
Antwoord (F) -none of the above- of (F) 4 ontbreekt.
Dit was eens vraag 17 van de SAT (Scholastic Aptitude Test) voor high school studenten.
Slechts enkele studenten merkten de fout op.

Ik betwijfel of de maker van deze opgave zelf de fout wel in de gaten had.