/* CartesianSystem.doc declares class CartesianSystem, * Carnegie-Mellon University Graphics library.

/* CartesianSystem.doc declares class CartesianSystem,
* a class for graphical display using the
* Carnegie-Mellon University Graphics library.
*
* Copyright Joel Adams, July 2001, All rights reserved.
*
* Note: many methods have an int parameter to define the drawing color,
*
and the valid colors are defined in CMUgraphics' file
127Graphics.h:
*
RED, GREEN, BLUE, YELLOW, PINK, PURPLE, BROWN, AQUA,
*
WHITE, BLACK, DKGREY, LTBLUE, ALMOND, LTGREY, TAN, DKGREEN
*/
#ifndef CARTESIAN_SYSTEM
#define CARTESIAN_SYSTEM
#include "Graphics.h"
#include "127Graphics.h"
#include <iomanip>
#include <cassert>
using namespace std;
// CMU Graphics library headers
//
window + ops
//
Colors
// setprecision()
// assert()
const int AXIS_MARGIN
= 16,
window edge
AXIS_GAP
= 50,
DEFAULT_PRECISION = 3;
// pixels btwn axis endpoints and
typedef double FunctionOfX(double);
drawFunction() draws
// the kind of function
// pixels between axis hash-marks
// #decimal digits on axis labels
class CartesianSystem : public window
{
public:
/* default constructor
* receive: axisVisible, a bool value.
* POST: a CartesianSystem has been constructed and displayed,
*
with its axis showing if and only if axisVisible == true.
*/
CartesianSystem(bool axisVisible = true);
/* explicit-value constructor
* receive: minX, minY, maxX, maxY, all doubles;
*
axisVisible, a bool value.
* PRE: minX < maxX && minY < maxY.
* POST: a CartesianSystem has been constructed and displayed,
*
with lower-left corner (minX, minY),
*
with upper-right corner (maxX, maxY), and
*
with its axis showing if and only if axisVisible == true.
*/
CartesianSystem(double minX, double minY,
double maxX, double maxY,
bool axisVisible = true);
/* clear the screen
* receive: bgColor, the new background color;
*
axisVisible, a bool.
* POST: the screen has been cleared;
*
and the axis redrawn if and only if axisVisible == true.
*/
void clear(int bgColor = WHITE, bool axisVisible = true);
/* utility for drawing the axis
* receive: axisColor, an int;
*
penSize, an int.
* POST: The CartesianSystem's axis has been drawn using axisColor.
*/
void drawAxis(int axisColor = BLACK, int penSize = 1);
/* drawing pen-width
* receive: width, a
* POST: the drawing
*/
void setPenWidth(int
mutator
positive int
pen-width has been set to width.
width);
/* drawing font mutator
* receive: size, style, and family, all ints;
* PRE: size is a valid point-size
*
&& style is one of:
*
{0 = plain, 1 = bold, 2 = italic, 4 = underline, 8 =
outline,
*
9 = shadow} (these can be added to achieve cumulative
effects)
*
&& family is a defined font family, e.g.:
*
{0 = chicago, 1 = applfont, 2 = newYork, 3 = geneva, 4 =
monaco,
*
5 = venice, 6 = london, 7 = athens, 8 = sanFran, 9 =
toronto,
*
11 = cairo, 12 = losAngeles, 20 = times, 21 = helvetica,
*
22 = courier, 23 = symbol, 24 = mobile}.
* POST: the drawing font's point-size == size &&
*
its style == style && its family == family.
*/
void setFont(int size, int style, int family);
/* draw a line
* receive x0, y0, x1, y1, all doubles defining 2 CartesianSystem
coordinates;
*
aColor, a color from 127Graphics.h in CMUgraphics.
* POST: a line colored aColor has been drawn from (x0, y0) to (x1,
y1).
* To draw using a window coordinate, use window::DrawLine() in CMU
Graphics.h
*/
void drawLine(double x0, double y0, double x1, double y1, int aColor =
BLACK);
/* make a pixel with a given color
* receive x, y, doubles defining a CartesianSystem coordinate;
*
aColor, the color it is to be.
* POST: a pixel colored aColor has been drawn at (x, y).
* To color a pixel using a window coordinate, use window::DrawPixel() in
* CMU Graphics.h
*/
void drawPixel(double x, double y, int aColor = BLACK);
/* draw a rectangle with a given color
* receive x0, y0, x1, y1, all doubles defining 2 CartesianSystem
coordinates;
*
aColor, the color the rectangle is to be;
*
dsStyle, the style of the circle: {NONE, FILLED, FRAME,
INVERTED};
*
and iWidth and iHeight, two ints that define the rounded-ness
of
*
corners.
* POST: a rectangle colored aColor has been drawn from (x0, y0) to
(x1, y1);
*
with style as specified by dsStyle, iWidth, and iHeight.
* To draw a rectangle using a window coordinate, use
window::DrawRectangle()
* in CMU Graphics.h
*/
void drawRectangle(double x0, double y0, double x1, double y1,
int color = BLACK, drawstyle dsStyle = FILLED,
int iWidth = 0, int iHeight = 0);
/* draw a circle with a given color
* receive x, y, doubles defining a CartesianSystem coordinate;
*
itsRadius, a double defining a length in the
CartesianSystem space;
*
aColor, the color the circle is to be; and
*
dsStyle, the style of the circle: {NONE, FILLED, FRAME,
INVERTED}.
* POST: a circle colored aColor has been drawn at (x, y) with radius
*
itsRadius, and styled as specified by dsStyle.
* To draw a circle using a window coordinate, use
window::DrawCircle() in
* CMU Graphics.h
*/
void drawCircle(double x, double y, double itsRadius,
int color = BLACK, drawstyle dsStyle = FILLED);
/* draw an ellipse with a given color
* receive x0, y0, x1, y1, all doubles defining 2 CartesianSystem
coordinates;
*
aColor, the color the ellipse is to be;
*
dsStyle, the style of the ellipse: {NONE, FILLED, FRAME,
INVERTED}.
* POST: an ellipse colored aColor has been drawn in the box defined
*
by (x0, y0) to (x1, y1); with style as specified by dsStyle.
* To draw an ellipse using a window coordinate, use
window::DrawEllipse() in
* CMU Graphics.h
*/
void drawEllipse(double x0, double y0, double x1, double y1,
int aColor = BLACK, drawstyle dsStyle = FILLED);
/* draw an arc with a given color
* receive x, y, doubles defining a CartesianSystem coordinate;
*
itsRadius, a double defining a length in the
CartesianSystem space;
*
startAtDegrees, an int defining the angle at which drawing
starts
*
(e.g., 0 == 12-o'clock; 90 == 3 o'clock, 180 == 6 o'clock,
...);
*
arcDegrees, an int defining the number of degrees the arc
should *
*
span;
*
aColor, the color the arc is to be; and
*
dsStyle, the style of the arc: {NONE, FILLED, FRAME,
INVERTED}.
* POST: an arc colored aColor has been drawn at (x, y) with radius
itsRadius
*
and starting at angle startAtDegrees, encompassing
arcDegrees;
*
and styled as specified by dsStyle.
* To draw an arc using a window coordinate, use window::DrawArc() in
*
CMU Graphics.h
*/
void drawArc(double x, double y, double itsRadius,
int startAtDegrees, int arcDegrees,
int aColor = BLACK, drawstyle dsStyle = FRAME);
/* draw a string with a given color
* receive x, y, doubles defining a CartesianSystem coordinate;
*
aString, the string to be displayed; and
*
aColor, the color the circle is to be.
* POST: aString has been drawn at (x, y) colored aColor,
* To draw a string using a window coordinate, use
window::DrawString() in CMU
* Graphics.h
*/
void drawString(double x, double y, const string& aString, int aColor
= BLACK);
/* draw a number with a given color
* receive x, y, doubles defining a CartesianSystem coordinate;
*
aNumber, the number to be displayed; and
*
aColor, the color the number is to be.
* POST: aNumber has been drawn at (x, y) colored aColor,
* To draw an integer using a window coordinate, use
window::DrawInteger() in
*
CMU Graphics.h
*/
void drawNumber(double x, double y, double aNumber, int color =
BLACK);
/* draw a function's graph
* receive: aFunction, a function mapping x -> y &&
*
aColor, the color the function is to be.
* POST: aFunction has been deen graphed colored aColor.
*/
void drawFunction(FunctionOfX aFunction, int color = BLACK);
/* block until the mouse-button is pressed.
* POST: The user has clicked the mouse
*/
void waitForMouseClick();
/* block until the mouse-button is pressed; return its coordinates.
* receive x, y, double variables;
*
column, row int variables.
* POST: The user has clicked the mouse &&
*
its CartesianSystem coordinates are in (x, y) &&
*
its window coordinates are in (column, row)
* To just get the window coordinate, use window::WaitMouseClick() in
CMU
*
Graphics.h
*/
void waitForMouseClick(double& x, double& y, int& column, int& row);
/* return the current coordinates of the mouse.
* receive x, y, double variables;
*
column, row int variables.
* POST: the mouse's CartesianSystem coordinates are in (x, y) &&
*
its window coordinates are in (column, row)
* To just get the window coordinates, use window::GetMouseCoord() in
CMU
*
Graphics.h
*/
void getMousePosition(double& x, double& y, int& column, int& row);
/* return the key the user pressed (without blocking)
* receive: aKey, a char variable.
* POST: The user pressed a key and aKey == that key.
* This method just calls window::GetKeyPress() from CMU Graphics.h
*/
void getKeyPress(char& aKey);
// minimum and maximum x- and y-value accessors;
// these retrieve the end-points of the axis.
double minX() const;
double minY() const;
double maxX() const;
double maxY() const;
/* the amount x changes when we move 1 pixel
* return: the number of x values corresponding to 1 column.
*/
double deltaX() const;
/* the amount y changes when we move 1 pixel
* return: the number of y values corresponding to 1 row.
*/
double deltaY() const;
/* map a CartesianSystem x-value into a window column value
* receive: x, a CartesianSystem x-value.
* return: the window column-value corresponding to x.
*/
int xToColumn(double x) const;
/* map a CartesianSystem y-value into a window row value
* receive: y, a CartesianSystem y-value.
* return: the window row-value corresponding to y.
*/
int yToRow(double y) const;
/* map a window column value into a CartesianSystem x-value
* receive: column, a window column number.
* return: the CartesianSystem x-value corresponding to column.
*/
double columnToX(int column) const;
/* map a window row value into a CartesianSystem y-value
* receive: row, a window row number.
* return: the CartesianSystem y-value corresponding to row.
*/
double rowToY(int row) const;
/* map a CartesianSystem distance into a window distance
* receive: distance, a length in CartesianSystem units
* return: the equivalent distance in raw pixels.
*/
int distanceToPixels(double distance) const;
/* get the window width in pixels
* return: the number of columns in the window.
*/
int getWidthInPixels();
/* get the window height in pixels
* return: the number of rows in the window.
*/
int getHeightInPixels();
private:
/* utility method used by constructors
* receive: minX, minY, maxX, maxY, all doubles defining the
CartesianSystem;
*
and axisVisible, a bool indicating whether the axis is to
be drawn.
* POST: minX, minY, maxX, maxY have been stored in xMin, yMin, xMax,
yMax, and
*
the axis has been drawn if and only if axisVisible == true.
*/
void initialize(double minX, double minY,
double maxX, double maxY,
bool axisVisible);
/* utility to initialize attributes dependent on the window size
* PRE: the width and height of the window are set
* POST: all window size-dependent instance variables have been set
*/
void setSizeDependentAttributes();
double xMin, yMin,
xMax, yMax,
myColumnsPerX, myRowsPerY,
xInterval, yInterval,
myXRange, myYRange;
int
myRows, myColumns,
myLastRow,
myDecimalDigits;
bool
myAxisVisible;
(false)?
};
//
//
//
//
//
//
//
//
//
our lower-left corner
our upper-right corner
mapping variables
distance btwn axis hash-marks
range of each dimension
# of USEABLE rows, columns
index of last row
precision for axis labels
draw axis (true) or not
inline CartesianSystem::CartesianSystem(bool axisVisible)
{
initialize(-4.0, -2.0, 4.0, 2.0, axisVisible);
// some default
settings
}
inline CartesianSystem::CartesianSystem(double minX, double minY,
double maxX, double maxY,
bool axisVisible)
{
initialize(minX, minY, maxX, maxY, axisVisible);
}
inline void CartesianSystem::setPenWidth(int width)
{
assert(width > 0);
SetPen(width);
}
inline void CartesianSystem::setFont(int size, int style, int family)
{
SetFont(size, style, family);
}
inline void CartesianSystem::drawLine(double x0, double y0, double x1,
double y1,
int aColor)
{
SetBrush(aColor);
DrawLine(xToColumn(x0), yToRow(y0), xToColumn(x1), yToRow(y1));
}
inline void CartesianSystem::drawPixel(double x, double y, int aColor)
{
SetBrush(aColor);
DrawPixel(xToColumn(x), yToRow(y));
}
inline void CartesianSystem::drawRectangle(double x0, double y0,
double x1, double y1,
int aColor, drawstyle
dsStyle,
int iWidth, int iHeight)
{
SetBrush(aColor);
DrawRectangle(xToColumn(x0), yToRow(y0), xToColumn(x1), yToRow(y1),
dsStyle, iWidth, iHeight);
}
inline int CartesianSystem::distanceToPixels(double distance) const
{
return int(distance * abs(xToColumn(1) - xToColumn(0))); // an ugly
hack
}
inline void CartesianSystem::drawCircle(double x, double y, double
radius,
int aColor, drawstyle dsStyle)
{
SetBrush(aColor);
DrawCircle(xToColumn(x), yToRow(y),
distanceToPixels(radius),
dsStyle);
}
inline void CartesianSystem::drawEllipse(double x0, double y0,
double x1, double y1,
int aColor, drawstyle dsStyle)
{
SetBrush(aColor);
DrawEllipse(xToColumn(x0), yToRow(y0), xToColumn(x1), yToRow(y1),
dsStyle);
}
inline void CartesianSystem::drawString(double x, double y,
const string& aString, int
aColor)
{
SetBrush(aColor);
DrawString(xToColumn(x), yToRow(y), aString.data());
}
inline void CartesianSystem::drawArc(double x, double y, double radius,
int startAtDegrees, int arcDegrees,
int aColor, drawstyle dsStyle)
{
SetBrush(aColor);
DrawArc(xToColumn(x), yToRow(y), distanceToPixels(radius),
startAtDegrees, arcDegrees, dsStyle);
}
inline int CartesianSystem::getWidthInPixels()
{
return GetWidth();
}
inline int CartesianSystem::getHeightInPixels()
{
return GetHeight();
}
inline void CartesianSystem::waitForMouseClick()
{
int column, row;
WaitMouseClick(column, row);
}
inline void CartesianSystem::waitForMouseClick(double& x, double& y,
int& column, int& row)
{
WaitMouseClick(column, row);
x = columnToX(column);
y = rowToY(row);
}
inline void CartesianSystem::getMousePosition(double& x, double& y,
int& column, int& row)
{
GetMouseCoord(column, row);
x = columnToX(column);
y = rowToY(row);
}
inline void CartesianSystem::getKeyPress(char& key)
{
GetKeyPress(key);
}
inline int CartesianSystem::xToColumn(double x) const
{
return AXIS_MARGIN + std::round((x-xMin) * myColumns / myXRange);
}
inline int CartesianSystem::yToRow(double y) const
{
return AXIS_MARGIN + myLastRow - std::round((y - yMin) * myRows /
myYRange);
}
inline double CartesianSystem::columnToX(int column) const
{
return xMin + (column - AXIS_MARGIN) * myXRange / myColumns;
}
inline double CartesianSystem::rowToY(int row) const
{
return yMin - (row - AXIS_MARGIN - myLastRow) * myYRange / myRows;
}
inline double CartesianSystem::deltaX() const
{
return myXRange / myColumns;
}
inline double CartesianSystem::deltaY() const
{
return myYRange / myRows;
}
inline double CartesianSystem::minX() const
{
return xMin;
}
inline double CartesianSystem::minY() const
{
return yMin;
}
inline double CartesianSystem::maxX() const
{
return xMax;
}
inline double CartesianSystem::maxY() const
{
return yMax;
}
#endif