Title: Michener
1Micheners Algorithm
- An efficient scheme for drawing circles (and
filling circular disks) on a raster graphics
display
2Scan conversion
- Geometric objects possess implicit parameters
- Example A circle has a center and a radius
- Its equation is (x xc)2 (y - yc)2 R2
- x and y are from the continuum of real numbers
- CRT display is a discrete 2D array of pixels
- So drawing a circle requires a conversion, from
something continuous into something discrete - In computer graphics its called scan conversion
- Imperfections unavoidable, but to be minimized
3Graphics Animations
- Fast drawing is essential for animations
- Some guidelines for speed
- eliminate all redundant computations
- prefer integer arithmetic to floating-point
- prefer add and subtract to multiply or divide
- Famous example Michener Algorithm
- We can use it later with our pong game
4Eight-fold symmetry
(x, y)
(-x, y)
(y, x)
(-y, x)
(y, -x)
(-y, -x)
(-x, -y)
(x, -y)
5Compute only one octant
6Subroutine draw_octant_points
- Arguments int x, y, xcent, ycent, color
- draw_pixel( xcent x, ycent y, color )
- draw_pixel( xcent y, ycent x, color )
- draw_pixel( xcent - x, ycent y, color )
- draw_pixel( xcent - y, ycent x, color )
- draw_pixel( xcent x, ycent - y, color )
- draw_pixel( xcent y, ycent - x, color )
- draw_pixel( xcent - x, ycent - y, color )
- draw_pixel( xcent - y, ycent - x, color )
7The best pixel to draw?
Blue pixel too far from center
( E gt 0 )
Red pixel too near the center (
E lt 0 )
Error-term E (x2 y2) R2
8Decision at n-th stage
Pn-1
An ?
yn-1
Bn ?
xn-1
xn
Algorithm compute sum error( An ) error(
Bn ) If ( sum lt 0 ) choose A n otherwise
choose B n.
9Formula sum of error-terms
- Assume circle has radius R, center (0,0)
- error( An) (xn-11)2 (yn-1)2 R2
- error( Bn) (xn-11)2 (yn-1 1)2 R2
- sumn 2(xn-11)2 2(yn-1)2 2(yn-1) 1-2R2
- Now, how is sumn different from sumn1
- If An is chosen at the n-th step?
- If Bn is chosen at the n-th step?
10Difference Equation
- Observe that sumn1 sumn 4xn-1 6
2(yn2 yn-12) 2(yn yn-1) - When An is selected at n-th stage
- we will have yn yn-1
- thus sumn1 sumn 4xn-1 6
- When Bn is selected at n-th stage
- we will have yn yn-1 - 1
- thus sumn1 sumn 4(xn-1 yn-1) 10
11Algorithm initialization
- We start with the point P0 (x0,y0), where x0
0 and y0 R - In this case A1 (1, R) and B1 (1, R-1)
- So the initial sum-of-errors term will be
- sum1 error(A1) error(B1)
- (12 R2) R2 (12 R22R1) R2
- 3 2R
12Micheners Algorithm
- int x 0, y R, sum 3 2R
- while ( x lt y )
-
- draw_octant_points( x, y, xc, yc, color )
- if ( sum lt 0 ) sum 4x 6
- else sum 4(x - y) 10 --y
- x
-
13Reference
- Francis S. Hill, jr., Computer Graphics,
Macmillan (1990), pp. 433-435. - NOTE Micheners circle-drawing method owes its
inspiration to a famous algorithm for efficient
line-drawing, devised in 1965 by J. E. Bresenham
(see the IBM Systems Journal, vol 4, pp. 305-311).
14Circle fill also exploits symmetry
(x, y)
(-x, y)
(y, x)
(-y, x)
(y, -x)
(-y, -x)
(-x, -y)
(x, -y)
15Subroutine draw_segments
- Arguments int x, y, xc, yc, color
- draw_horiz( xc x, xc x, yc y, color )
- draw_horiz( xc x, xc x, yc - y, color )
- draw_horiz( xc y, xc y, yc x, color )
- draw_horiz( xc y, xc y, yc - x, color )
16draw_horiz( int xlo, xhi, y, color )
- Clipping to screen boundaries
- If (( y lt ymin )( y gt ymax )) return
- if ( xlo lt xmin ) xlo xmin
- if ( xhi gt xmax ) xhi xmax
- Drawing the horizontal segment
- for (x xlo x lt xhi x)
- draw_pixel( x, y, color )
17Demo-program
- Try the michener.cpp demo
- It uses VESA graphics-mode 0x4101
- Screen resolution is 640x480
- Color depth is 8 bits-per-pixel (8bpp)
- SVGAs Linear Frame Buffer is enabled
18In-Class Exercise
- Modify the michener.cpp demo
- Use the standard rand() function
- Draw lots of color-filled circles
- Stop if user hits ltESCAPEgt key
- NOTE For the latter feature, we need to discuss
setting up the terminal keyboard so it uses a
non-canonical input-mode
19The tty interface
- tty is an acronyn for TeleTYpe terminal
- Such devices have a keyboard and screen
- Behavior emulates technology from 1950s
- Usually a tty operates in canonical mode
- Each user-keystroke is echoed to screen
- Some editing is allowed (e.g., backspace)
- The keyboard-input is internally buffered
- The ltENTERgt-key signals an end-of-line
- Programs receive input one-line-at-a-time
20tty customization
- Sometimes canonical mode isnt suitable (an
example animated computer games) - The terminals behavior can be modified!
- UNIX provides a convenient interface
- include lttermios.hgt
- struct termios tty
- int tcgetattr( int fd, struct termios tty )
- int tcsetattr( int fd, int flag, struct termios
tty )
21How does the tty work?
application
User space
tty_driver c_lflag
Kernel space
input handling c_iflag c_cc
output handling c_oflag
SOFTWARE
struct tty c_iflag c_oflag
c_cflag c_lflag c_line
c_cc
terminal_driver c_cflag
TeleTYpe display device
HARDWARE
22The c_lflag field
- This field is just an array of flag bits
- Individual bits have symbolic names
- Names conform to a POSIX standard
- Linux names match other UNIXs names
- Though actual symbol values may differ
- Your C/C program should use
- include lttermios.hgt
- for portability to other UNIX environments
23ICANON and ECHO
- Normally the c_lflag field has these set
- They can be cleared using bitwise
logic tty.c_lflag ECHO // inhibit
echo tty.c_lflag ICANON // no buffering
24The c_cc array
- struct termios objects include an array
- The array-indices have symbolic names
- Symbol-names are standardized in UNIX
- Array entries are tty operating parameters
- Two useful ones for our purposes are
- tty.c_cc VMIN and tty.c_cc VTIME
25How to setup raw terminal-mode
- Step 1 Use tcgetattr() to get a copy of the
current ttys struct termios settings - Step 2 Make a working copy of that object
- Step 3 Modify its flags and control-codes
- Step 4 Use tcsetattr() to install changes
- Step 5 Perform desired raw mode input
- Step 6 Use tcsetattr() to restore the terminal
to its original default settings
26raw mode needs four changes
- tty.c_cc VMIN 1
- so the read() function will return as soon as
at least one new input-character is available - tty.c_cc VTIME 0
- so there will be no time-delay after each new key
pressed until the read() function returns - tty.c_lflag ECHO // no echoing
- tty.c_lflag ICANON // no buffering
27Demo program rawtty.cpp
- This program may soon prove useful
- It shows the keyboard scancode values
- It demonstrates noncanonical tty mode
- It clears the ISIG bit (in c_lflags field)
- This prevents ltCONTROLgt-C from being used to
abort the program the user must quit by
hitting the ltESCAPEgt-key so default
terminal-settings will get reinstalled
28In-class Exercise
- Use the Linux tty interface-functions to
reprogram your terminal for raw input - Draw ramdom color-filled circles -- until your
user hits the ltESCAPEgt key - Algorithm int done 0 do
- draw_next_circle( x, y, r, color )
- int inch 0
- read( 0, inch, 4 )
- if ( inch 0x1B ) done 1
- while ( !done )