dolt: the drawableObject Library

Wes Huang and Kris Beevers

Rensselaer Polytechnic Institute
Algorithmic Robotics Laboratory

12 September 2002


This document provides information and documentation on the drawableObject Library (dolt), a simple, portable, and representation-independent 2D graphics library which can draw graphics to the screen as well as generate postscript output.

Table of Contents

1. Introduction

2. Installation

3. Structure

4. Base Classes

5. Drawable Objects

6. Color

7. Output

8. Geometric Representations

9. Example Program

10. Errata/Todo

11. Release History


1. Introduction

This document describes the drawableObject Library (dolt) and discusses its interfaces and usage information. dolt was designed for use in Rensselaer Polytechnic Institute's Algorithmic Robotics Laboratory, specifically as a tool for creating small simulations and for generating figures and demonstrations.

dolt makes use of the GLUT OpenGL graphics library and requires the library to be installed. Optionally, it can also be used in conjunction with the Computational Geometry Algorithms Library (CGAL), though CGAL is not required for use of dolt.

Because dolt was created quickly and for specific purposes, there are likely some problems (e.g. bugs, design flaws, etc.) that haven't presented themselves to us. As such, dolt is to be considered a still-developing project.

1.1 Contributors

This document and dolt were written by Dr. Wes Huang (whuang@cs.rpi.edu) and Kris Beevers (beevek@cs.rpi.edu).

1.2 Feedback

Because dolt is a project in ongoing development, any feedback (comments, bug reports/fixes, etc.) is welcomed. Send it to dolt@cs.rpi.edu.

Before sending bug reports or suggestions, please read this entire document (especially the Errata/Todo Section) and send detailed information about the problem.

1.3 Distribution Policy

dolt and this document are Copyright (c) 2002 Rensselaer Polytechnic Institute. dolt may be distributed in accordance with the terms set forth under the GNU General Public license. A copy of this license should be included in the dolt package; it can also be viewed at http://www.gnu.org/licenses/gpl.txt.


2. Installation

dolt has been installed and tested in versions of Unix, Linux, and in Microsoft Windows 9x/NT/2k/XP. In its default configuration it requires only the OpenGL Utility Toolkit (GLUT) library. It can also be compiled with the Computational Geometry Algorithms Library (CGAL).

2.1 Downloading

The source for dolt is currently available only as a gzipped tar file: No precompiled versions of dolt are currently available. Here is the previous version:

2.2 Compilation

2.2.1 Unix

To install in Unix, first unpack the installation as follows:
	$ gunzip dolt-0.95.tar.gz | tar -xf -
Depending on your system, it may be necessary to edit the Makefile for dolt. Make sure the paths for GLUT and (if necessary) CGAL includes are correct. You may also wish to change the default installation directory for dolt. Once this is done, simply run:
	$ make
	$ make cgal     # optional, only if you are using CGAL support
	$ make install

2.2.2 Microsoft Windows

To install in Windows, first unzip the package. Compilation of dolt has only been tested with Microsoft Visual Studio; if you don't have Visual Studio and are unable to compile the software with another compiler, please send us a note. Our ability to help you may be limited, however.

In the win32 subdirectory of the unzipped package is a .dsw (workspace) file. Open this in Visual Studio and compile the 'dolt' project. This should produce the file dolt.lib. Move this file to your Visual Studio library directory. If you wish to compile a version of dolt with CGAL support, do the same for the project called 'dolt_cgal' (which will produce dolt-cgal.lib). Finally, move the files in include to your Visual Studio include directory, in a subdirectory called dolt.

2.3 Writing Programs

If you are using CGAL and wish to use the CGAL-capable version of dolt, you should define the preprocessor flag 'USE_CGAL' when compiling your programs. If you do not, the built-in geometric representations will be used instead.

2.3.1 Unix

Programs that make use of dolt must link with the library and have access to the necessary header files. Assuming you installed dolt into a path that your compiler and linker know about, you should be able to provide the -ldolt (or -ldolt-cgal with CGAL support) compiler flag, and should be able to include dolt header files in your code like so: #include <dolt/graphics.h> . Additionally, because dolt makes use of GLUT (and optionally CGAL), you will need to take any necessary steps to compile with these libraries. It may be necessary for you to specify the library and include directories manually if you did not install to common include/lib directories, i.e.:
	$ g++ program.cc -I/path/to/dolt/include -L/path/to/dolt/lib \
	 -ldolt -lglut -lGL -lGLU -lX11

2.3.2 Microsoft Windows

Assuming you followed the installation instructions above, compiling programs that make use of dolt in Windows (using MS Visual Studio) requires only that you specify that the program be linked with the necessary libraries (dolt.lib or dolt-cgal.lib, glut.lib and cgal.lib if you linked dolt with CGAL when you compiled it), and that you include the proper header files (i.e. #include <dolt/graphics.h>.


3. Structure

dolt provides a number of interface classes and functions for operations including:

3.1 Class Heirarchy

Drawable Object Base Classes
ClassInherits
drawableObject--
drawableLineObjectdrawableObject
drawableEnclosedObjectdrawableLineObject

Drawable Geometric Objects
ClassInherits
drawablePointdrawableObject, Point
drawableSegmentdrawableLineObject, Segment
drawableLineStripdrawableLineObject, lineStrip
drawablePolygondrawableEnclosedObject, Polygon
drawableEllipsedrawableEnclosedObject, Ellipse
drawableCircledrawableEnclosedObject, Circle
drawableRectangledrawableEnclosedObject, Rectangle
drawableSquaredrawableEnclosedObject, Square
drawableArcdrawableLineObject, Arc
drawableWedgedrawableEnclosedObject, Arc
drawableTextdrawableObject
drawableImagedrawableObject

Standalone Objects
ClassInherits
Color--
Graphics--
psFile--

Geometric Representations (either built-in or from CGAL)
ClassInherits
Bbox--
Point--
Segment--
lineStrip--
Polygon--
Ellipse--
Circle--
Rectangle--
SquareRectangle
ArcCircle


4. Base Classes

dolt makes significant use of inheritance. All classes derived from the following base classes inherit several important properties. Derive your own objects from these if you find a need for drawing new types of objects that aren't among those provided by dolt. It is recommended that you look at drawable.h and drawable.cpp in the source distribution for examples before doing so.

4.1 drawableObject

Header: Declared in drawable.h

This is the base class for all objects capable of being rendered (to screen or to Postscript) by dolt. It stores information common to all "drawable objects," specifically color information, and provides a default color for all objects to use. It is an abstract class and cannot be instantiated by itself. drawableObject provides the following public functions:

static inline void setDefaultObjectColor( const Color &c )
     Functionality: Sets the (global) default object color for all objects. Note that this affects only newly created objects; previously created objects will retain the former default color that was assigned them when they were created.

Arguments:

  • c: the new default color
Example:
	drawableObject::setDefaultColor( Color(1.0,0.0,0.0) );

inline void setColor( const Color &c )
     Functionality: Sets the color of the object.

Arguments:

  • c: the new object color
Example:
drawablePoint p(0.0,1.0);
p.setColor( Color(1.0,0.0,0.0) );

inline void setAlpha( float a )
     Functionality: Sets the alpha component of the color for the object.

Arguments:

  • a: the new alpha value
Example:
drawablePoint p(0.0,1.0);
p.setAlpha( 0.5 ); // 50% transparent

inline const Color & getColor() const
     Functionality: Get the color of the object.

Arguments: None

Example:

drawablePoint p(0.0,1.0);
Color c = p.getColor();

virtual void drawGL( const Graphics &out ) const
     Functionality: An abstract function that must be implemented by all objects derived from drawableObject. Renders the object to the output device described by out using OpenGL. Note that in general, the user does not need to directly call this function to render the object, as this is taken care of internally.

Arguments:

  • out: the output device to render to
virtual void drawPS( const Graphics &out, psFile &ps,
	const Bbox &bounds, const double &scale ) const
     Functionality: An abstract function that must be implemented by all objects derived from drawableObject. Renders the object to the Postscript file described by ps using the scene from out, the page bounding box bounds and the scaling factor scale. Note that in general, the user does not need to directly call this function to render the object, as this is taken care of internally.

Arguments:

  • out: the Graphics object containing the world information
  • ps: the Postscript file to render to
  • bounds: the bounding box on the Postscript page into which graphics may be rendered
  • scale: the scaling factor (from world to page) to use in scaling locations and distances

4.2 drawableLineObject

Header: Declared in drawable.h

drawableLineObject, derived from drawableObject , should be used to represent any objects that consist only of "line art" (e.g. that are not filled in any way). It stores information about line width and dash patterns (stippling), and a global default line width. An accessory to drawableLineObject is the lineStyle type for describing dash patterns. See the setLineStyle function for more information on this. The drawableLineObject class cannot be directly instantiated; only classes derived from it that provide drawGL and drawPS functions can be instantiated.

drawableLineObject( lineStyle style = SOLID, float lineWidth = defaultWidth )
     Functionality: Constructor; sets style (dash pattern) of line and width of line.

Arguments:

  • style: a lineStyle pattern describing the dash pattern to use for the lined object (see setLineStyle)
  • width: set width (in pixels) of the lined object
static inline void setDefaultLineWidth( float width )
     Functionality: Sets the (global) default line width for all lined objects. Note that this affects only newly created objects; previously created objects will retain the line width that was assigned them when they were created.

Arguments:

  • width: the new default line width
Example:
	drawableLineObject::setDefaultLineWidth( 1.0 ); // 1 pixel wide

inline void setLineStyle( lineStyle style )
     Functionality: Sets the dash pattern for the object. A dash pattern is defined by the 16-bit lineStyle type. An on bit specifies that a pixel at that bit's offset should be opaque, while an off bit specifies that the pixel should be transparent. The pattern is repeated over the entire line. Default values are defined. They are SOLID (0xffff), DASHED (0xff00) and DOTTED (0xcccc).

Arguments:

  • style: the new line style to use
Example:
	drawableSegment s( Point(0.0,0.0), Point(1.0,1.0) );
	s.setLineStyle( DASHED ); // 1111111100000000
	s.setLineStyle( 0x0101 ); // 0000000100000001

inline void setLineWidth( float width )
     Functionality: Sets the width of the object (in pixels).

Arguments:

  • width: the new width to use
Example:
	drawableSegment s( Point(0.0,0.0), Point(1.0,1.0) );
	s.setLineWidth( 3.0 ); // 3 pixels wide

inline lineStyle getLineStyle() const
     Functionality: Get the line style of the object.

Arguments: None

Example:

drawableSegment s( Point(0.0,0.0), Point(1.0,1.0) );
lineStyle ls = p.getLineStyle();

inline float getLineWidth() const
     Functionality: Get the line width of the object.

Arguments: None

Example:

drawableSegment s( Point(0.0,0.0), Point(1.0,1.0) );
float w = p.getLineWidth();

4.3 drawableEnclosedObject

Header: Declared in drawable.h

drawableEnclosedObject, derived from drawableLineObject, should be used to represent any objects that are filled in some way (e.g. polygons, circles, etc.) and that might have a border. It stores information about whether or not the object should be filled, whether its border should be drawn, the color of the border, and a global default border width. The drawableEnclosedObject class cannot be directly instantiated; only classes derived from it that provide drawGL and drawPS functions can be instantiated. Note: to set the border width of the enclosed object, the setLineWidth member of the parent class ( drawableLineObject) can be called.

drawableEnclosedObject( bool filled = true,
	lineStyle style = SOLID, float lineWidth = defaultWidth )
     Functionality: Constructor; sets flag indicating whether or not the object is filled, and sets style (dash pattern) of border and width of border.

Arguments:

  • filled: set flag indicating whether or not the object is filled
  • style: a lineStyle pattern describing the dash pattern to use for the border of the object (see drawableLineObject)
  • width: set width (in pixels) of the border of the object
static inline void setDefaultBorderColor( const Color &c )
     Functionality: Sets the (global) default border color for all enclosed objects. Note that this affects only newly created objects; previously created objects will retain the border color that was assigned them when they were created.

Arguments:

  • c: the new default border color
Example:
	Color red(1.0,0.0,0.0);
	drawableEnclosedObject::setDefaultBorderColor( red );

static inline void setDefaultLineWidth( float width )
     Functionality: Sets the (global) default border width (in pixels) for all enclosed objects. Note that this affects only newly created objects; previously created objects will retain the border width that was assigned them when they were created.

Arguments:

  • width: the new default border width
Example:
	drawableEnclosedObject::setDefaultLineWidth( 2.0 ); // 2 pixels

inline void setFilled( bool filled )
     Functionality: Sets the flag indicating whether or not the object should be filled (with the color associated with the object).

Arguments:

  • filled: the new value for the flag (true indicates the object will be filled, false indicates it will not)
Example:
	drawablePolygon p;
	p.setFilled( false );

inline void setBorderColor( const Color &c )
     Functionality: Sets the border color for the object.

Arguments:

  • c: the new border color for the object
Example:
	drawablePolygon p;
	p.setBorderColor( Color(1.0,0.0,0.0) );

inline bool getFilled() const
     Functionality: Get the fill flag for the object.

Arguments: None

Example:

	drawablePolygon p;
	bool filled = p.getFilled();

inline const Color & getBorderColor() const
     Functionality: Get the border color of the object.

Arguments: None

Example:

	drawablePolygon p;
	Color c = p.getBorderColor();


5. Drawable Objects

Header: Declared in drawable.h

The most important functionality of dolt (and its purpose) is to render 2-dimensional geometric objects to the screen. This is accomplished by providing a set of "drawable" versions of the geometric objects discussed above. The drawable versions inherit methods from both drawableObject and their geometric representation, and thus provide the public interfaces of both. For example, a drawablePoint stores information both about the location of a point and about its color. See the Class Heirarchy for information about which drawable objects inherit what.

The following drawable objects are provided:

Of these, only drawableText and drawableImage do not map to a geometric counterpart. The rest of the objects are in most cases interchangeable with their geometry-only versions, i.e.:
	void foo( const Point &point ) { ... }
	void bar( const drawablePoint &dpoint ) { ... }

	Point p(1.0,1.0);
	drawablePoint q(p);

	foo( p ); // ok
	foo( q ); // ok
	foo( drawablePoint(8.0,8.0) ); // ok
	bar( q ); // ok
	bar( p ); // ok
	bar( Point(0.0,0.0) ); // ok

One exception is drawablePolygon, which extends Polygon to allow for holes in the polygon. To insert a hole in a drawablePolygon, use drawablePolygon::addHole; note also that a drawablePolygon can be nonconvex:

void addHole( const Polygon &hole )
     Functionality: Add a 'hole' in a polygonal object. Note that if the hole is not fully in the interior of the object, the drawing behavior of the drawablePolygon is undefined. The even-odd winding rule is used in determining which portions of the overall polygon are inside (and will be filled).

Arguments:

  • hole: a polygon describing the hole to be made inside of this drawablePolygon
Example:
	drawablePolygon poly; // create a nonconvex polygon
	poly.push_back( Point(1.0,1.0) );
	poly.push_back( Point(5.0,4.0) );
	poly.push_back( Point(9.0,1.0) );
	poly.push_back( Point(6.0,5.0) );
	poly.push_back( Point(9.0,9.0) );
	poly.push_back( Point(5.0,6.0) );
	poly.push_back( Point(1.0,9.0) );
	poly.push_back( Point(4.0,5.0) );
	
	Polygon hole; // add a square hole in the middle
	hole.push_back( Point(4.5,4.5) );
	hole.push_back( Point(5.5,4.5) );
	hole.push_back( Point(5.5,5.5) );
	hole.push_back( Point(4.5,5.5) );
	poly.addHole( hole );

5.1 drawableText

Header: Declared in drawable.h

drawableText is meant to be a (very) simple text-drawing interface that makes use of system-available fonts. It is cross-platform compatible for Win32 and *nix, though the user may have to handle the cross- platform case using preprocessor commands if this compatibility is desired because of the differences in font-naming conventions across platforms.

drawableText( const Point &location, const char *text = "",
    int points = 12, const char *postscriptFont = "Palatino-Roman",
	const char *screenFont = DEFAULTFONT );
     Functionality: Constructor; set world coordinate location for bottom left of text, string to draw, point size and fonts for both Postscript and screen output. Note that in Unix the point size specified is ignored for screen output and that specified as part of the font string is used instead. DEFAULTFONT is defined to be "Arial" in Win32 and "-adobe-helvetica-medium-r-normal--12-*-*-*-p-*-iso8859-1" in other operating environments.

Arguments:

  • location: the location of the bottom left corner of the text to be drawn (in world coordinates)
  • text: the string to be drawn
  • points: the point size of the font; ignored for screen output in Unix
  • postscriptFont: the font face to be used for Postscript output
  • screenFont: the font face to be used onscreen; must be a valid font description for the platform in use
Example:
	#ifdef _WIN32
		drawableText txt(Point(1.0,1.0),"Test",12,"Helvetica","Helvetica");
	#else
		drawableText txt(Point(1.0,1.0),"Test",12,"Helvetica",
			"-adobe-helvetica-medium-r-normal--12-*-*-*-p-*-iso8859-1");
	#endif

5.2 drawableImage

Header: Declared in drawable.h

drawableImage provides an interface for sampled image (bitmap) drawing, loading, saving and manipulation within the drawableObject framework. It can perform its functionality for images with one byte per pixel (grayscale) or three bytes per pixel (RGB). Images are mapped to world coordinates with a bounding box, and thus can be stretched or compressed to fit within the bounding box. Individual pixels or the entire color buffer can be manipulated.

Image drawing to screen is done via a raster operation, which is slower than texture mapping but allows for the use of images of arbitrary size (OpenGL textures must be 2^n x 2^n pixels).

Note that the image is stored as a single buffer of increasing x and y pixel coordinates. The image coordinate frame origin is at the lower left of the image.

drawableImage()
drawableImage( const Bbox &worldLocation )
drawableImage( const Bbox &worldLocation, unsigned int w,
  unsigned int h, bytespp bytes = BPP3 );
drawableImage( const drawableImage &i );
     Functionality: Constructors; if specified, sets world bounding box for image and pixel width, height and bytes per pixel. The copy constructor duplicates the color buffer of an image in memory, so use it with caution. If width and height of the image are specified, an empty color buffer of that size is created; this functionality should not be used if an image will be loaded from file, as loading causes any current color buffer to be destroyed.

Arguments:

  • worldLocation: a bounding box specifying the mapping of the image into world coordinates
  • w: the width of the image, in pixels
  • h: the height of the image, in pixels
  • bytes: the number of bytes per pixel; must be in the drawableImage::bytespp enumeration, i.e. BPP1 or BPP3
  • i: another drawableImage to copy
Example:
	drawableImage img; // no color buffer created
	drawableImage img2( Bbox(0.0,0.0,10.0,10.0) ); // no color buffer created
	drawableImage img3( Bbox(0.0,0.0,10.0,10.0), 100, 100, BPP3 ); // color buffer created
	drawableImage img4( img3 ); // copies color buffer of img3

inline void setWorldLocation( const Bbox &worldLocation )
     Functionality: Set the bounding box specifying the region occupied by the image in world space.

Arguments:

  • worldLocation: a bounding box specifying the mapping of the image into world coordinates
Example:
	drawableImage img;
	img.setWorldLocation( Bbox(0.0,0.0,10.0,10.0) );

inline unsigned int getWidth() const
inline unsigned int getHeight() const
     Functionality: Get width or height, respectively, in pixels of the image.

Arguments: None

Example:

	drawableImage img( Bbox(), 640, 480 );
	unsigned int w = img.getWidth(); // 640
	unsigned int h = img.getHeight(); // 480

inline unsigned char * getBuffer()
     Functionality: Access the color buffer of the image directly.

Arguments: None

Example:

	drawableImage img( Bbox(), 640, 480 );
	unsigned char *buf = img.getBuffer();

void setPixel( unsigned int x, unsigned int y, const unsigned char *col )
const unsigned char * const getPixel( unsigned int x, unsigned int y ) const
     Functionality: Set or retrieve the value of the pixel in the image at (x, y). Note that the value at the retrieved pointer to the pixel cannot be modified.

Arguments:

  • x: x-coordinate of the pixel to set or retrieve
  • y: y-coordinate of the pixel to set or retrieve
  • col: pointer to an array of type unsigned char that is of size 1 for an image with 1 byte per pixel and 3 for an image with 3 bytes per pixel. The value will be copied directly into the color buffer
Example:
	drawableImage img( Bbox(), 640, 480, BPP1 );
	unsigned char pix;
	pix = *img.getPixel( 10, 10 );
	pix = 0xf0;
	img.setPixel( 10, 10, &pix );
	drawableImage img2( Bbox(), 640, 480, BPP3 );
	unsigned char pix2[3], *pix3;
	pix3 = img.getPixel( 10, 10 );
	pix2[0] = pix2[1] = 0xff;
	pix2[2] = 0x00;
	img.setPixel( 10, 10, pix2 ); // set to yellow

bool loadPPM( const char *filename )
     Functionality: Load a PPM file into the drawableImage object; this will destroy any existing image information. Any properly formatted ASCII- or binary-formatted PPM image can be loaded. Note that ASCII images inherently load much more slowly than binary images.

Arguments:

  • filename: the file name of a PPM image to load
Example:
	drawableImage img( Bbox(0.0,0.0,10.0,10.0) );
	if( !img.loadPPM( "test.ppm" ) )
		cout << "Error loading test.ppm" << endl;

bool savePPM( const char *filename, bool binaryFile = true ) const
     Functionality: Save the color buffer of the drawableImage to a PPM file (in either ASCII or binary format).

Arguments:

  • filename: the file name of the output image
  • binaryFile: flag indicating whether or not to save the image in binary PPM format (true for binary, false for ASCII)
Example:
	drawableImage img( Bbox(0.0,0.0,10.0,10.0), 200, 200, BPP3 );
	... // perform operations on the image color buffer
	if( !img.savePPM( "out.ppm", true ) )
		cout << "Error saving out.ppm" << endl;


6. Color

Header: Declared in color.h

Color provides an interface for all color assignment and use within dolt. It stores red, green, blue and alpha (transparency) values for colors. Additionally, it provides functionality for mapping names (strings) to color values. Note: the default value (if one is never assigned) for a color is white (1.0,1.0,1.0). Also, color names should not begin with any of the digit characters (0-9) or the period character (though this is not enforced).

Color( float r = 1.0, float g = 1.0, float b = 1.0, float a = 1.0 )
     Functionality: Constructor; assigns RGBA values to color and defaults to white if none are specified.

Arguments:

  • r: red component of color
  • g: green component of color
  • b: blue component of color
  • a: alpha (transparency) component of color
Example:
	Color red(1.0,0.0,0.0);
	Color yellow(1.0,1.0,0.0);
	Color transparent(1.0,0.0,0.0,0.5); // 50% transparent

Color( const char *name )
     Functionality: Constructor; assigns color values based on a name if the name exists in the global color map, or the default color if the name does not exist.

Arguments:

  • name: name of color
Example:
	Color red("red");

inline void setRGB( float r, float g, float b )
     Functionality: Set the rgb values of the color.

Arguments:

  • r: red component of color
  • g: green component of color
  • b: blue component of color
Example:
	Color c;
	c.setRGB( 1.0, 0.0, 0.0 );

inline void setAlpha( float a )
     Functionality: Set the alpha transparency of the color.

Arguments:

  • a: alpha (transparency) component of color
Example:
	Color c("red");
	c.setAlpha( 0.5 ); // 50% transparent
	c.setAlpha( 0.0 ); // completely transparent
	c.setAlpha( 1.0 ); // completely opaque

inline float r() const
inline float g() const
inline float b() const
inline float a() const
     Functionality: Retreive the red, green, blue or alpha components (respectively) of the color.

Arguments: None

Example:

	Color c("red");
	c.r(); // returns 1.0
	c.g(); // returns 0.0

void nameColor( const char *name )
     Functionality: Map the color to a name in the global color map. The name can then be used in the initialization of future Color objects. If the name already exists in the color map, it is replaced. Color names should not begin with a digit (0-9) or a period. A large number of default colors are placed in the map at program startup; some of the more commonly used ones are as follows:
  • "white": 1.0, 1.0, 1.0
  • "gray75": 0.75, 0.75. 0.75
  • "gray50": 0.5, 0.5, 0.5
  • "gray25": 0.25, 0.25, 0.25
  • "black": 0.0, 0.0, 0.0
  • "red": 1.0, 0.0, 0.0
  • "green": 0.0, 1.0, 0.0
  • "blue": 0.0, 0.0, 1.0
  • "yellow": 1.0, 1.0, 0.0
  • "magenta": 1.0, 0.0, 1.0
  • "cyan": 0.0, 1.0, 1.0
For the rest of the color definitions, see color.cpp.

Arguments:

  • name: a name for the object's color
Example:
	Color c(1.0,0.0,0.0);
	c.nameColor( "red" );
	Color x("red"); // x == c


7. Output

Header: Declared in graphics.h

The Graphics class provides two important types of functionality. It stores scene information (i.e. all objects to be drawn in any rendering context), and if necessary renders to the screen (using GLUT).

Following are the initializers for the Graphics class:

Graphics()
     Functionality: Constructor; create a scene with a default world boundary.

Arguments: None

Graphics( const Bbox &world )
     Functionality: Constructor; create a scene with the world boundary specified in world; world coordinates will be automatically mapped to any rendering context.

Arguments:

  • world: the world bounding box for the scene
Example:
	Graphics g( Bbox(0.0,0.0,10.0,10.0) );

inline void setWorldBounds( const Bbox &world )
     Functionality: Set the world boundary of the scene.

Arguments:

  • world: the world bounding box for the scene
Example:
	Graphics g;
	g.setWorldBounds( Bbox(0.0,0.0,5.0,5.0) );

7.1 Scenes

Each instance of the Graphics class stores information about a single scene. This information is in the form of a list of lists of drawableObjects. The rationale behind this structure is that it provides a simple method for grouping objects so that, for example, all objects of a certain "class" can be removed from the scene at once.

In order to add objects to a scene, one must first create an objectList -- which is simply a std::list<drawableObject *> and can be treated as such. So, for example, to create a list of Points to draw to the screen, one could do the following:

	Point a(0.0,0.0);
	Point b(1.0,1.0);
	Point c(2.0,2.0);
	objectList objects;
	objects.push_back( &a );
	objects.push_back( &b );
	objects.push_back( &c );

The list is now ready to be inserted into the scene. This can be done with the addObjectList function (objecLists can be removed with the counterpart delObjectList function).

void addObjectList( const objectList &olist )
     Functionality: Add a list of objects to the scene.

Arguments:

  • olist: an objectList to add to the list of lists describing the scene
Example:
	g.addObjectList( objects );

void delObjectList( const objectList &olist )
     Functionality: Delete the list of objects at the address of olist from the scene, if such a list exists.

Arguments:

  • olist: the objectList (previously inserted into the scene) to remove
Example:
	g.addObjectList( objects );
	g.delObjectList( objects );

One (current) limitation of the Graphics class is that it is only able to render one scene at a time (i.e., dolt is unable to render to multiple simultaneous windows). However, your program can creates multiple scenes and switch between. The first scene to be created is the default current scene.
static void setCurrentScene( Graphics &g )
     Functionality: Sets a global pointer to the currently rendering scene. All screen and Postscript output will be from this scene.

Arguments:

  • g: the Graphics object containing the scene to set active.
Example:
	Graphics g1;
	Graphics g2;
	// g1 is the currently rendering scene
	Graphics::setCurrentScene( g2 );
	// g2 is the currently rendering scene

7.2 Event Handlers

If rendering is currently taking place onscreen, it is possible to capture keyboard and mouse events and to specify a function to run during idle time.

void setKeyboardHandler( void (*kb)( unsigned char key ) )
     Functionality: Set the handler for incoming keyboard events to a user-defined function.

Arguments:

  • kb: a pointer to a function that takes an unsigned char argument indicating the ASCII code of the key that was pressed
Example:
	void kb( unsigned char key )
	{
		cout << key << " was pressed!" << endl;
	}
	...
	g.setKeyboardHandler( kb );

void setMouseHandler( void (*mouse)( int button, int state, int x, int y ) )
     Functionality: Set the handler for incoming mouse click events to be a user-defined function

Arguments:

  • mouse: a pointer to a function that takes the arguments above; the same as the GLUT glutMouseFunc callback. See the GLUT documentation for further information
Example:
	void mouse( int button, int state, int x, int y ) { ... }
	...
	g.setMouseHandler( mouse );

void setMotionHandler( void (*motion)( int x, int y ) )
     Functionality: Set the handler for incoming mouse motion events to be a user-defined function.

Arguments:

  • motion: a pointer to a function that takes the arguments above; the same as the GLUT glutPassiveMotionFunc callback. See the GLUT documentation for further information
Example:
	void motion( int x, int y ) { ... }
	...
	g.setMotionHandler( motion );

void setIdleFunction( void (*idle)( void ) )
     Functionality: Set a pointer to a user-defined function that is called when dolt (and GLUT) are idle.

Arguments:

  • idle: a pointer to a function that takes the arguments above; the same as the GLUT glutIdleFunc callback. See the GLUT documentation for further information
Example:
	void motion( int x, int y ) { ... }
	...
	g.setMotionHandler( motion );

void printControlKeyBindings() const
     Functionality: Print (to STDOUT) a list of the default control (zoom/pan) key bindings for dolt.

Arguments: None

Example:

	cout << "Keyboard Commands:" << endl;
	g.printControlKeyBindings();

There are default handlers for keyboard and mouse events. By default, pressing 'q' exits the program.

Also, a built-in handler for special keyboard events exists, and is used for the control of zooming and panning of the scene. The built in controls are as follows:

7.3 Zooming, Panning and Point-mapping

Zooming and panning can also be controlled through the Graphics class interface.

void zoom( float newZoom = 1.0 )
     Functionality: Zoom in or out of the scene. The argument is the percentage of the original size of the scene to zoom to. In other words, a zoom of 1.0 (100%) restores the scene to its original size, with the world bounding box exactly fitting the output window. A zoom of 0.5 (50%) displays the scene at 50% of its original size, etc. Note that zooming is relative to the center of the current view.

Arguments:

  • percentZoom: percent of the original scene size to zoom to
Example:
	g.zoom(); // original size
	g.zoom( 0.25 ); // 1/4 original size

void pan( float panX, float panY )
     Functionality: Pan over the scene. Pans panX percent of the x-dimension of the scene, and panY percent of the y-dimension of the scene relative to the current scene location (not the original).

Arguments:

  • panX: percent of the scene's x dimension to pan in the x direction
  • panY: percent of the scene's y dimension to pan in the y direction
Example:
	g.pan( 0.05, 0.0 ); // move right 5% of scene x dimension
	g.pan( -0.1, -0.1 ); // move down and left

Functionality is also provided for mapping points from the current scene's world coordinates and zoom/pan to some other world's coordinates.
double findScale( const Bbox &newBounds ) const
     Functionality: Find the scaling factor between the world bounding box and newBounds

Arguments:

  • newBounds: the world boundary for the destination world
Example:
	g.setWorldBounds( Bbox(0.0,0.0,10.0,10.0) );
	Bbox newWorld(0.0,0.0,5.0,5.0);
	double scale = g.findScale( newWorld );

Point mapPoint( const Bbox &bounds, const double &scale,
	const Point &p ) const
     Functionality: Find the point within the world bounded by bounds that is mapped to from the current scene, given a factor by which to scale distances and the point in the current scene to map.

Arguments:

  • bounds: the world boundary for the destination world
  • scale: a scaling factor for distances between the two worlds
  • p: the point in the current scene to map
Example:
	g.setWorldBounds( Bbox(0.0,0.0,10.0,10.0) );
	Bbox newWorld(0.0,0.0,5.0,5.0);
	double scale = g.findScale( newWorld );
	Point q = g.mapPoint( newWorld, scale, Point(1.0,1.0) );

void pixelsPerMeter( float &ppmx, float &ppmy ) const
     Functionality: Returns the ratio of pixels (on-screen) to world units ('meters'), taking into account current zoom, in ppmx and ppmy.

Arguments:

  • ppmx: variable into which pixels per meter on the x-axis will be returned
  • ppmy: variable into which pixels per meter on the y-axis will be returned
Example:
	// for a window of width 640 and height 480 with no zoom
	g.setWorldBounds( Bbox(0.0,0.0,10.0,10.0) );
	g.pixelsPerMeter( ppmx, ppmy );
	// ppmx == 64, ppmy = 48

7.4 GL Output

Drawing a scene to the screen using OpenGL is very simple. Before beginning rendering, GLUT output must be initialized with the initGL function. Following this, calling the runEventLoop function begins the rendering to the screen. Be advised that runEventLoop will never return!

void initGL( int *argc, char **argv,
	const char *name = 0,
	int winWidth = 750, int winHeight = 0,
	int winPosX = 100, int winPosY = 100 )
     Functionality: Initialize OpenGL output and create a window. Note: you might find it useful to use a similar ratio in your window width and height as the same ratio in your world bounding box.

Arguments:

  • argc: a pointer to the program's argc variable for GLUT initialization
  • argv: the program's argv variable for GLUT initialization
  • name: a title for the window
  • winWidth: the width (in pixels) of the window
  • winHeight: the height (in pixels) of the window
  • winPosX: x coordinate of the position on screen at which the window should be created
  • winPosY: y coordinate of the position on screen at which the window should be created
Example:
	Graphics g;
	g.initGL( &argc, argv, "example", 640, 480 );

static void runEventLoop()
     Functionality: Run the main OpenGL event-handling loop. This function will never return.

Arguments: None

Example:

	Graphics g;
	... // set up scene
	g.initGL( &argc, argv, "example", 640, 480 );
	g.runEventLoop();

void setBackgroundColor( const Color &c )
     Functionality: Set the background color of the current rendering context (default is white).

Arguments:

  • c: background color
Example:
	Graphics g;
	g.setBackgroundColor( Color("black") );

inline int getPixWidth() const
inline int getPixHeight() const
     Functionality: Get the width and height, respectively (in pixels) of the window for the Graphics object.

Arguments: None

Example:

	int w = g.getPixWidth();
	int h = g.getPixHeight();

7.5 Requesting Non-GL (Instantaneous) Output

Scenes created with the Graphics class can be outputted to non-screen contexts (not in real time).

7.5.1 Postscript Output

Header: Declared in postscript.h

To set up Postscript output, you must first create a psFile output file. A psFile should be initialized as follows:

	psFile p( "filename.ps" );
Note that no copy constructor exists for psFile; it is derived from ofstream, which also provides no copy constructor. This means that the following is illegal:
	void foo( const psFile &file ) { ... }

	foo( psFile( "filename.ps" ) ); // illegal
	psFile out( "filename.ps" );
	foo( out ); // ok
To render the scene to a Postscript file, use the writePS function.
void writePS( psFile &out,
	const Bbox &bounds = Bbox(0.5,0.5,8.0,10.5) ) const
     Functionality: Write the scene to a Postscript file, using the bounding box described by bounds to position the scene on the page.

Arguments:

  • out: the psFile to write to
  • bounds: the bounding box on the page in which to position the scene
Example:
	Graphics g;
	... // set up scene
	psFile out( "filename.ps" );
	g.writePS( out, Bbox(0.5,0.5,8.0,7.5) );

7.5.2 Screenshots

Screenshots are as simple as calling a member function of the Graphics object whose screen should be saved. They are written in binary PPM format.

bool writePPM( const char *filename ) const
     Functionality: Write the screen pixels (directly from the framebuffer) to the specified file in binary PPM format. Returns false on failure, true on success.

Arguments:

  • filename: the output filename (for clarity, it is recommended that the filename have the '.ppm' extension)
Example:
	Graphics g;
	... // set up scene
	g.writePPM( "screenshot.ppm" );


8. Geometric Representations

Header: Declared in geometry.h

dolt provides a number of geometric objects with interfaces that emulate those of their counterparts in CGAL, and also provides several objects not avaliable with CGAL. As a general rule, all of the accessor functions provided by the CGAL counterparts are implemented, but none of the other functionality exists. As such, the built-in geometric objects are not well-suited to applications that need to do anything with them besides draw.

In order for the provided objects to provide exactly the same interface as CGAL, a number of CGAL typedefs exist (see geometry.h) that create 2-dimensional CGAL types. These should be used when possible if CGAL is being used because the drawable* classes in drawable.h derive from them in order to work with both CGAL and the built-in geometric objects.

8.1 CGAL Objects

The list of built-in objects that possess CGAL counterparts, and the functions they provide, is: For in-depth documentation of these geometric objects, see that provided by CGAL: http://www.cgal.org/Manual/doc_html.

Additionally, several objects not provided by CGAL are available (though primarily only for drawing) with dolt.

8.2 Ellipse

Ellipses are represented by a center position, a major and minor radius, and an orientation (in radians).
Ellipse( const Point &p, const double &orient,
	const double &majorRadius, const double &minorRadius )
     Functionality: Constructor; initialize the ellipse's center, orientation, major radius and minor radius.

Arguments:

  • p: center point of the ellipse
  • orient: orientation (in radians) of the ellipse
  • majorRadius: major radius of the ellipse
  • minorRadius: minor radius of the ellipse
Example:
	// ellipse centered at origin, rotated 90 degrees,
	//  with a major radius of 3 and a minor radius of
	//  1.5
	Ellipse e( Point(0.0,0.0), M_PI / 2.0, 3.0, 1.5 );

inline void setPos( const Point &p )
inline void setOrientation( const double &o )
inline void setMajorRadius( const double &r )
inline void setMinorRadius( const double &r )
inline Point getPos() const
inline double getOrientation() const
inline double getMajorRadius() const
inline double getMinorRadius() const
     Functionality: Set or retrieve the values associated with the ellipse

Example:

	Ellipse e( Point(0.0,0.0), M_PI / 2.0, 3.0, 1.5 );
	e.setOrientation( 0.0 );
	double orient = e.getOrientation(); // 0.0

8.3 lineStrip

A lineStrip is simply a series of Points. It is derived directly from std::vector<Point>, and thus provides the same interface.

Example:

	// create an upside-down 'v'
	lineStrip s;
	s.push_back( Point(0.0,0.0) );
	s.push_back( Point(1.0,1.0) );
	s.push_back( Point(2.0,0.0) );

8.4 Rectangle

A Rectangle stores the lower left and upper right corners of a rectangle.
Rectangle( const Point ¢er, const double &width,
	const double &height )
     Functionality: Constructor; create a rectangle given a center point, a width (x axis) and a height (y axis).

Arguments:

  • center: center point of the rectangle
  • width: width (x length) of the rectangle
  • height: height (y length) of the rectangle
Example:
	// rectangle centered at origin with width 3 and
	//  height 1.5
	Rectangle r( 0.0, 3.0, 1.5 );

Rectangle( const Point &lowerLeft, const Point &upperRight )
     Functionality: Constructor; create a rectangle given the lower left and upper right corners

Arguments:

  • lowerLeft: lower left corner of the rectangle
  • upperRight: upper right corner of the rectangle
Example:
	Rectangle r( Point(0.0,0.0), Point(3.0,2.0) );

inline Point getMinPoint()
inline Point getMaxPoint()
     Functionality: Retrieve the minimum and maximum points of the rectangle (respectively)

Example:

	Rectangle r( Point(0.0,0.0), Point(3.0,2.0) );
	Point p = r.getMinPoint(); // (0.0, 0.0)

8.5 Square

Square is derived from Rectangle, and thus provides the same accessors.
Square( const Point &lowerLeft, const double &sideLen )
     Functionality: Constructor; create a square given the lower left corner and the length of the square's sides

Arguments:

  • lowerLeft: lower left corner of the square
  • sideLen: length of the square's sides
Example:
	Square s( Point(0.0,0.0), 3.0 );

8.6 Arc

Arc is derived from Circle, and thus provides the same accessors as Circle in addition to its own. Only circular arcs may be represented.
Arc( const Point ¢er, const double &squaredRad,
	const double &minAngle, const double &maxAngle )
     Functionality: Constructor; create a circular arc given a center, squared radius, minimum and maximum angle (on the circle) of the arc.

Arguments:

  • center: the center of the arc's representative circle
  • squaredRad: the squared radius of the arc's representative circle
  • minAngle: the angle (in radians) at which to start the arc; note that angular distance is in the counterclockwise direction (from the x axis)
  • maxAngle: the angle (in radians) at which to end the arc
Example:
	// an arc through 90 degrees
	Arc a( Point(0.0,0.0), 1.0, 0.0, M_PI / 2.0 );

inline double getMinAngle() const
inline double getMaxAngle() const
     Functionality: Retrieve the minimum and maximum angles of the arc (respectively)

Example:

	Arc a( Point(0.0,0.0), 1.0, 0.0, M_PI / 2.0 );
	double x = a.getMinAngle(); // x == 0.0


9. Example Program

The following example program demonstrates a number of the features of dolt.

//
// Test program for dolt
// Creates a variety of drawableObjects and displays them,
//  and demonstrates keyboard handling and multiple scenes
//

#include 	// for screen output
#include 	// for postscript output
#include 		// for M_PI
#ifndef M_PI
  #define M_PI 3.1415926535897932384626433832
#endif

Graphics g, g2;

// keyboard handler for primary scene
void gkeyboard( unsigned char key )
{
  switch( key ) {
  case 'q':
    exit( 0 );  // quit
  case 's':
    Graphics::setCurrentScene( g2 );  // switch scenes
    break;
  case 'p':
    {
      psFile f("test.ps");  // open postscript file
      g.writePS( f );       // write postscript file
    }
    break;
  }
}

// keyboard handler for secondary scene
void g2keyboard( unsigned char key )
{
  switch( key ) {
  case 'q':
    exit( 0 );
  case 's':
    Graphics::setCurrentScene( g );
    break;
  case 'p':
    {
      psFile f("test.ps");
      g2.writePS( f );
    }
    break;
  }
}

int main( int argc, char **argv )
{
  // initialize screen output for both scenes
  g.initGL( &argc, argv, "Test", 640, 640 );
  g2.initGL( &argc, argv, "Test 2", 480, 480 );
  
  // register keyboard callbacks for both scenes
  g.setKeyboardHandler( gkeyboard );
  g2.setKeyboardHandler( g2keyboard );

  // create a drawable point object at (2,2) with a
  //  diameter of 8
  drawablePoint p(2.0,2.0,8.0);

  // create a drawable line segment from (1,1) to (9,1)
  //  with a custom dash pattern
  drawableSegment s( Point(1.0,1.0),Point(9.0,1.0), 0xfcfc );
  // make the segment red
  s.setColor( Color(1.0, 0, 0) );
  
  // create a line strip (a series of vertices)
  drawableLineStrip ls;
  ls.setColor( Color(0, 1.0, 0) ); // green
  ls.push_back( Point(3.0,3.0) );  // first point
  ls.push_back( Point(4.0,3.5) );  // second point
  ls.push_back( Point(3.0,4.0) );  // third point
  
  // create a polygon (solid border, filled, border width of 3)
  drawablePolygon o(SOLID,true,3.0f);
  o.setColor( Color(0, 0, 1.0) ); // blue filling
  o.push_back( Point(7.0,7.0) );  // first point
  o.push_back( Point(9.0,9.0) );  // second point
  o.push_back( Point(9.5,7.0) );  // third point
  o.push_back( Point(8.0,6.5) );  // fourth point

  // create an ellipse centered at (2,8), with an orientation
  //  of -1.2 radians, a major radius of 2.0 and a minor radius
  //  of 1.0
  drawableEllipse e( Point(2.0,8.0),-1.2,2.0,1.0 );
  e.setColor( Color(1.0, 1.0, 0) ); // yellow

  // create a circle centered at (8,2) with a radius of 1.5, a
  //  dashed border, filled, with a border width of 3
  drawableCircle c( Point(8.0,2.0),1.5,DASHED,true,3.0f );
  // set the circle's color to cyan, 50% transparent
  c.setColor( Color(0, 1.0, 1.0, 0.5) );

  // create a rectangle with a lower left corner at (5,5) and an
  //  upper right corner at (7,7), with a solid border, filled,
  //  and a border width of 5
  drawableRectangle r(Point(5.0,5.0),Point(7.0,7.0),SOLID,true,5.0f);
  // set the filling color to 50% gray
  r.setColor( Color("gray50") );
  // set the border color to red
  r.setBorderColor( Color("red") );

  // create a square with a lower left corner at (5.75,5.75)
  //  with a side length of 0.5, a dotted border, filled, and a
  //  border width of 3
  drawableSquare q(Point(5.75,5.75),0.5,DOTTED,true,3.0f);
  q.setColor( Color(0.0,1.0,1.0) ); // cyan

  // create an arc centered at (5,8.5), with a squared radius of
  //  1.0, arcing (counterclockwise) from PI/2 to PI
  drawableArc a(Point(5.0,8.5),1.0,M_PI / 2.0,M_PI,SOLID,3.0f);
  a.setColor( "green" );

  // create a wedge centered at (5,8.5) with a squared radius of
  //  1.0, arcing (counterclockwise) from PI to 2PI
  drawableWedge w(Point(5.0,8.5),1.0,M_PI,M_PI * 2.0,SOLID,true,2.0f);
  w.setColor( "magenta" );

  // some text
#ifdef _WIN32
  drawableText t(Point(3.0,3.0),"Some Text",24,"Palatino-Roman","Helvetica");
#else
  drawableText t(Point(3.0,3.0),"Some Text",24,"Palatino-Roman",
    "-adobe-helvetica-medium-r-normal--24-*-*-*-p-*-iso8859-1");
#endif
  t.setColor( "blue" );

  // create a new objectList so that we can add all of the
  //  objects to the first scene
  objectList olist;
  olist.push_back( &p );  // add point
  olist.push_back( &s );  // add line segment
  olist.push_back( &ls ); // add line strip
  olist.push_back( &o );  // add polygon
  olist.push_back( &e );  // add ellipse
  olist.push_back( &c );  // add circle
  olist.push_back( &r );  // add rectangle
  olist.push_back( &q );  // add square
  olist.push_back( &a );  // add arc
  olist.push_back( &w );  // add wedge
  olist.push_back( &t );  // add text
  g.addObjectList( olist );  // add the objectList to the scene

  // create a new objectList to add objects to the second scene
  objectList olist2;
  olist2.push_back( &r ); // add rectangle
  g2.addObjectList( olist2 ); // add the objectList to the scene

  // run the main event loop, drawing everything on the screen
  g.runEventLoop();
  return 0;
};


10. Errata/Todo


11. Release History


Copyright (c) 2002 Rensselaer Polytechnic Institute