------------------------------------------------------------------------------
MC logo
Shape Implementations
[^] Code Examples
------------------------------------------------------------------------------
<<Shape Classes shape.cc Compound Shape Class>>
#include <math.h>
#include "shape.h"

// Draw the rectangle by drawing its lines. */
void Rectangle::draw(Drawable &d) {
        d.line(origx, origy, origx + width, origy);
        d.line(origx + width, origy, origx + width, origy + height);
        d.line(origx + width, origy + height, origx, origy + height);
        d.line(origx, origy + height, origx, origy);
}

// This constructs an ellipse.  It mostly remembers the parameters it 
// needs to run draw.
Ellipse::Ellipse(int sx, int sy, int width, int height): 
                                        Shape(sx + width / 2, sy + height /2)
{
        // Major and minor axis, as they are known.
        a = width/2;
        b = height/2;

        // Determine type and set parameters.
        skinny = width < height;
        if(skinny)
        {
                // Swap the width and height, so we'll compute as if
                // fat, but we'll transpose each point when we plot it.
                int tmp = a;
                a = b;
                b = tmp;
        }

        // Might as well do these things once, since our ellipse does
        // not change shape.
        asqr = a*a;
        bsqr = b*b;
        bsqr_over_asqr = bsqr/asqr;
        asqr_over_bsqr = asqr/bsqr;
}

// Plot a point of the ellipse.  The point is in the first quadrant, and
// is plotted in all four.  Also, if the ellipse is skinny, the point is
// transposed, since draw always draws a wide ellipse.
void Ellipse::plot(Drawable &d, int x, int y)
{
        if(skinny) 
        {
                int tmp = x;
                x = y;
                y = tmp;
        }

        d.set(x, y);
        d.set(-x, y);
        d.set(-x, -y);
        d.set(x, -y);
}

// Draw the ellipse.
void Ellipse::draw(Drawable &d)
{
        // Create an offset drawable that will let us draw around the
        // origin.
        OffsetDrawable od(d, origx, origy);

        // Plot the points.  This loop plots in the first quadrant, and assumes
        // a wide ellipse.  It relies on plot to transpose for a skinny
        // ellipse, and plot all four quadrants.  It uses increasing x
        // values, which will produce non-decreasing y values.

        // We plot the first part by moving x and computing y.  We end this
        // part when the change in y per x step becomes more than one.  In the
        // next part, we generate points by stepping y and computing x values.
        int x = 0, y = b;
        int next_x = 0, next_y = b;
        for(next_x = 1; next_x <= a; ++next_x)
        {
                plot(od, x, y);
                next_y = (int)rint(sqrt(bsqr - bsqr_over_asqr*next_x*next_x));
                if(y - next_y > 1) break;
                x = next_x;
                y = next_y;
        }
        while(y > 0)
        {
                plot(od, x, y);
                --y;
                x = (int)rint(sqrt(asqr - asqr_over_bsqr*y*y));
        }
        plot(od, x, y);
}
<<Shape Classes Compound Shape Class>>