header

Simulation of Spirograph Toy

//---------------------------------------------------------
// Spirograph
//
// Simulate the spirograph toy.
//
// D. Searls
// Asbury College
// Feb 2010
//---------------------------------------------------------

#include<graphics.h>
#include<iostream>
#include<cmath>
#include "worldType.h"
using namespace std;

const int MAXSIZE = 10;
const double PI = 3.14159265358979;

//---------------------------------------------------------
// GCD
//
// Return the greatest common divisor of i and j.
//
// In parameters: i, j
//---------------------------------------------------------
int GCD(int i, int j)
{
    if (j == 0)
    {
        return i;
    }
    else
    {
        return GCD(j, i % j);
    }
}

//---------------------------------------------------------
// drawEpitrochoid
//
// Draw the specified epitrochoid in the specifed world.
//
// In parameter: w, color, radius1, radius2, radius3
//---------------------------------------------------------
void drawEpitrochoid(worldType w, int color, int radius1, int radius2, int radius3)
{
    double r1 = double(radius1);
    double r2 = double(radius2);
    double r3 = double(radius3);
    int oldColor = getcolor();
    setcolor(color);
    int n = 360 * radius2 / GCD(abs(radius1), abs(radius2));
    double degree = PI / 180.0;
    double theta, phi;
    
    w.moveTo(r1 + r2 - r3, 0.0);
             
    for (int i = 0; i < n - 1; i++)
    {
        theta = double(i) * degree;
        phi = (r1 + r2) / r2 * theta;
        w.lineTo((r1 + r2) * cos(theta) - r3 * cos(phi),
                 (r1 + r2) * sin(theta) - r3 * sin(phi));
    }
    w.lineTo(r1 + r2 - r3, 0.0);
        
    setcolor(oldColor);
}

//---------------------------------------------------------
// drawHypotrochoid
//
// Draw the specified hypotrochoid in the specifed world.
//
// In parameter: w,  color, radius1, radius2, radius3
//---------------------------------------------------------
void drawHypotrochoid(worldType w, int color, int radius1, int radius2, int radius3)
{
    double r1 = double(radius1);
    double r2 = double(radius2);
    double r3 = double(radius3);
    int oldColor = getcolor();
    setcolor(color);
    int n = 360 * radius2 / GCD(abs(radius1), abs(radius2));
    double degree = PI / 180.0;
    double theta, phi;
    
    w.moveTo(r1 - r2 + r3, 0.0);
             
    for (int i = 0; i < n - 1; i++)
    {
        theta = double(i) * degree;
        phi = (r1 - r2) / r2 * theta;
        w.lineTo((r1 - r2) * cos(theta) + r3 * cos(phi),
                 (r1 - r2) * sin(theta) - r3 * sin(phi));
    }
    w.lineTo(r1 - r2 + r3, 0.0);
        
    setcolor(oldColor);
}
//*********************************************************
//                    M A I N   D R I V E R
//*********************************************************
int main()
{
    int size;
    int r1, r2, r3;
    
    if (getmaxwidth() > getmaxheight())
    {
        size = getmaxheight();
    }
    else
    {
        size = getmaxwidth();
    }
    size = size - 50;
    
    worldType w(601, 601, 0,0,
                -100.0, -100.0, 100.0, 100.0, "Spirograph");
    
    cout << "             SPIROGRAPH\n\n";
    cout << "When asked to enter a radius or distance\n";
    cout << "enter integer values.\n\n";
    cout << "The world coordinates extend from -100 to\n";
    cout << "100 in both directions.\n";
    
    do
    {
        cout << "\nEnter radius of stationary circle (0 to exit): ";
        cin >> r1;
        if (r1 > 0)
        {
            cout << "Enter radius of rolling circle: ";
            cin >> r2;
            cout << "Enter distance from center to pen: ";
            cin >> r3;
            cleardevice();
            drawEpitrochoid(w, LIGHTRED, r1, r2, r3);
            drawHypotrochoid(w, LIGHTBLUE, r1, r2, r3);
        }
    }while (r1 > 0);
    
    closegraph();            
    return 0;
}