Computer Graphics: The Clearwin+ Graphics Region
Computer Graphics: The Clearwin+ Graphics Region
Computer Graphics
The ClearWin+ Graphics Region
Graphical User Interfaces are a big improvement over text-based applications. However, GUIs allow much more than just simple components and text they open up the possibility for the more general computer graphics. For instance, an engineering application may need to draw a stress-strain graph, or a piece of CAD software may need to plot lines, circles, curves, and surfaces. ClearWin+ allows the programmer to have complete control over drawing within a particular graphics region. Here is a very simple example of a line draw in a graphics region:
This example was produced by the following code (see drawing1.cpp on WebCT):
#pragma windows 500000,500000 #include <windows.h> #include <dbos/graphics.h> int handle; int main() { int width=500; int height=300; winio("%gr[grey]&", width, height); winio("%ca[Simple drawing]&") ; winio("\t%`bt[Done]&"); winio("%lw", &handle); draw_line(10,10,490,290,12); }
Lets look at the various new features. Firstly, weve included a pre-processor command (#pragma windows 500000,500000) which simply instructs the compiler to not bother producing the DOS text-based command window as well as the ClearWin+ windows. Dont worry about what it means, just use it!
10
The initial colour of the graphics window can be specified in the square brackets (see Appendix A), and the width and height of the graphics region are specified as additional arguments. There is one slight complication with ClearWin+ windows after they are defined, they wait until the windows closes before executing any subsequent lines of code. In our program this would cause a problem because the drawing command (for the line) happens after the window is defined. To overcome this, you can specify that you want ClearWin+ to leave the window open with %lw command, so that program execution will continue without waiting for the window to be closed. To ensure that you can keep track of the window, ClearWin+ provides you with a handle (for closing or updating the window as required):
winio("%lw", &handle); // note the & to pass the address
Its often necessary to have the handle declared as a global variable if you need to access it in any callback functions, as they cant take arguments. The final line of the example, draw_line(10,10,490,290,12) draws a straight line between the pair of points, (10,10) and (490,290), the co-ordinates being specified in pixel units. Note the coordinate system used is screen coordinates, which is NOT the same as Cartesian coordinates (y is inverted)! The final parameter, 12, defines the colour in which the line is drawn; again, see Appendix A. A slightly improved version of this program is provided under the name drawing2.cpp.
Screen Coordinates
All co-ordinates used in conjunction with drawing functions are screen coordinates that are specified in pixel units. A pixel is the smallest element that can be displayed on the screen; it is one of the dots from which the screen is constructed. Typical SVGA screens measure 1024 x 768 pixels, but larger screens are often 1280 x 960. The windows top left pixel is defined to occupy position (0, 0), the x direction runs horizontally left-to-right and the y direction runs vertically downward, top to bottom. If you attempt to draw an object that runs outside its window, ClearWin+ will omit the excess portions, an operation known as clipping.
11
Graphical Functions
Preamble
Following normal practice when discussing C/C++ libraries, the graphics functions will be presented in terms of their prototypes. Recall that type information is not used when the function is called: it is provided so that you can declare the variables that you feed into the function in the appropriate manner. For example, consider the draw_line function. The prototype is:
void draw_line(const short& x1, const short& y1, const short& x2, const short& y2, const short& colour);
The previous example involved the short data type, which is a kind of int the technical difference is that a short is usually consumes only two bytes of memory compared with an ints four. In the case of inputs to a function, C will automatically convert the variables or constants that you provide into the type it expects. For example, if a const short is expected but you provide an int, C++ will make the appropriate conversion on your behalf (given that it is possible). Note that type conversion will generally not be performed on variables that are used for outputs: you must program the correct types to begin with. You can invoke a type conversion explicitly by use of the C cast mechanism. Suppose x is a float and n is an int, then the following statement would force n to take the truncated (rounded down) value of x:
n = int(x);
As the example illustrates, one type of variable may be cast into another by wrapping it in round brackets and prefixing it with the new, desired type name (i.e. int, float, etc). See last semesters notes for more details.
12
Clears the active window to its default background colour and set the text cursor to the home position, (0,0).
void clear_screen_area(const short& x1, const short& y1, const short& x2, const short& y2, const short& col);
Paint the rectangle defined by the top left hand corner (x1, y1) and the bottom right hand corner (x2, y2) with colour col, thus erasing any previous contents. See Appendix A for a list of standard colours.
void draw_line(const short& x1, const short& y1, const short& x2, const short& y2, const short& col);
Draw a straight line from (x1, y1) to (x2, y2) using colour number col. The line is drawn using the current line style and thickness. Also see functions set_line_style and set_line_width.
void polyline(const short x[], const short y[], const short& n, const short& col); x and y are arrays of screen co-ordinates (Note: they must be shorts) that define a sequence of n points. This function draws a sequence of lines to connect consecutive pairs of points, each line being drawn in colour number col, using the current line style and thickness. Also see functions set_line_style and set_line_width. See demo program polyline.cpp and polyline2.cpp for examples of the use
of this function.
void rectangle(const short& x1, const short& y1, const short& x2, const short& y2, const int& col);
Draws the rectangle with top left hand corner (x1, y1) and bottom right hand corner (x2, y2) using colour col, using the current line style and thickness. Also see functions set_line_style and set_line_width. Note: If a line thickness greater than 1 is used, the rectangle is drawn with a solid line irrespective of the line style setting.
void fill_rectangle(const short& x1, const short& y1, const short& x2, const short& y2, const int& col);
As above except that the interior of the rectangle is also filled with colour number col.
void ellipse(const short& xc, const short& yc, const short& a, const short& b, const int& col);
Draws the ellipse with center (xc, yc), horizontal semi-axis a and vertical semi-axis b using colour col and the current line style and thickness. Also see set_line_style and set_line_width. Note: If a line thickness greater than 1 is used, the ellipse is drawn with a solid line irrespective of the line style setting.
13
void fill_ellipse(const short& xc, const short& yc, const short& a, const short& b, const int& col);
As above except that the interior of the ellipse is also filled with colour number col.
void create_polygon(const short x[], const short y[], const short& n, short& handle, short& errcode); x and y are arrays of screen co-ordinates (Note: they must be shorts) that define a sequence of n points. This function constructs a data structure to represent the closed
polygon formed by consecutive pairs of points but draws no graphics at this stage. handle is a handle by which the data structure may be accessed by other polygon manipulation functions, later in the program. errcode is a code that reports any faults encountered when the data structure is being constructed. errcode values associated with this and other polygon functions have the following meanings: 0 1 2 Operation was successful. Insufficient memory was available to create the polygon. Invalid handle: the specified polygon is not present.
Frees the memory associated with the given polygon and disassociates its handle. errcode reports any faults encountered during this operation.
void fill_polygon(const short& handle, const short& col, short& errcode);
Given a handle to a previously defined polygon, this function fills it with colour number col. errcode reports any faults encountered during this operation.
void combine_polygons(const short handles[], const short& n, short& newhandle, short& errcode);
Assuming the first n elements of array handles contains handles to existing polygons, this function combines them to make a new, complex polygon. The original polygons are left unchanged. newhandle is a handle to the new object and errcode reports any faults encountered during this operation.
void move_polygon(const short& handle, const short& dx, const short& dy, short& errcode);
Shifts the polygon with the given handle through a displacement (dx, dy). errcode reports any faults encountered during this operation.
void draw_text(const char* str, const short& x, const short& y, const int& col);
Starting from pixel position (x, y), draws the text string specified in string str using colour number col. See polyline.cpp and other demo programs for examples of this function
14
void set_text_attribute(const short& font, const float& size, const float& rot, const float& ital);
Sets the characteristics of the font used by draw_text in terms of its size, orientation and whether it is drawn in italics. Font is the number of the font to be used (the default is zero, see Appendix C for a list of available fonts), size is the scale factor that defines its size (the default font has unit size), rot is the angle, in degrees, at which text is rotated anti-clockwise relative to the horizontal (the default is zero) and ital is the angle, in degrees, through which the font is sheared to produce an italic effect (the default is zero).
True Colour
It is possible to make the graphics window support true colour, that is to use ANY colour instead of the 16 defined in Appendix A. To achieve this, you need to specify that the graphics window support true colour:
winio("%gr[rgb_colours, grey]&", 257, 257);
An example of this is provided: TrueColour.cpp. This example uses a function written by the author to convert from a HSL (Hue, Saturation and Luminance) colour model to a RGB (Red, Green, Blue) model dont worry about how this works. When you specify that you want to use true colour, you have millions of colours at your disposal, each represented by a discrete number. To ascertain what this number Peter Lockyer, 2006 15
is for a given set of RGB values, call the RGB(int R, int G, int B) function it takes three ints to represent the three colour channels, each in the range 0 255.
Mouse Input
Most commercial applications have interactive graphics regions i.e. the user can use the mouse to click and drag items. ClearWin+ provides a way to call a callback function whenever some mouse activity occurs within a graphics region. Specify %gr[full_mouse_input]. When inside the callback function, you need to know what the current mouse position and status is which can be found by calling the clearwin_info() function. A very simple drawing package (see picture above) can be created using just a few lines of code, see MouseInput.cpp.
16
Exercises
1. Create a ClearWin+ window with a graphics region (600 x 400 pixels). Add 3 buttons Draw Rectangle, Draw Circle, and Quit. The first two buttons should be linked to callback functions that draw either a rectangle or circle respectively. When pressed, they should produce a pop up window asking for width (height if a rectangle) and x,y position of mid-point. The callback should draw the desired shape to the screen. The colour scheme is left to you.
2. Add two more buttons, with callbacks, to the previous example. One should clear the screen, the other change the current drawing colour. The way you implement this is up to you however, radio buttons provide an easy-to-use interface. The radio buttons (%rb) must be linked together using the gang control (%ga). See LotsOfFeatures.cpp.
3. Often, engineering software needs to plot graphs. Write a program that plots a sine curve over one period, i.e. 0 2 radians. Note that you will need to calculate an x and a y scaling factor, and perhaps consider defining a border.
17
Symbolic name
BLACK BLUE GREEN CYAN RED MAGENTA BROWN WHITE GREY INT_BLUE INT_GREEN INT_CYAN INT_RED INT_MAGENTA YELLOW INT_WHITE BLACK
Description
Black: The default background colour Blue Green Cyan Red Magenta Brown White: The default text colour Dark Grey Light blue Light green Light cyan Light red Light magenta Yellow Intense white Black: The drawing screen border colour
Note: It is recommended that colours 0 and 16 should be used only for their stated purposes. Colours 1 to 15 may be used for general drawing. A symbolic name may be used in place of a number when specifying the col colour argument in a drawing command, but it must be typed exactly as shown above. Also Note: These colours will not work if using %gr[RGB_COLOURS]. Use the int col = RGB(int R, int G, int B) function to determine the colour index.
Description
Solid line. Dashed line. Dotted line. Alternating dashes and dots. Alternating dashes and double dots. Pen draws an invisible line. Used to remove the border that is normally drawn round a filled figure. Dimensions of the figure are reduce so that it fits entirely within the bounding rectangle, taking into account the width of the drawing pen.
Note: Use the set_line_style function provided in the windows.h library to apply the above. PS_SOLID is the default. In most cases, non-default styles are only applied to a line of unit width.
18
Appendix C Fonts
Font No.
101 102 103 104 105 106 107 108 109 110 111 112 113 114
Description
Simplex Roman Duplex Roman Simplex Greek Complex Roman Complex Italic Triplex Roman Triplex Italic Simplex Script Complex Script Complex Greek Complex Cyrillic Gothic English Gothic German Gothic Italian
Style
Sans serif Sans serif Sans serif Seriffed Seriffed Seriffed Seriffed Script Script Seriffed Seriffed Gothic Gothic Gothic
Weight
Standard Bold Standard Standard Standard Bold Bold Standard Bold Standard Standard Standard Standard Standard
19