Java Two Dimensional Graphics with Affine Transforms

advertisement
Java Two Dimensional Graphics
with Affine Transforms
Sasank Upadrasta
Contents
•
•
•
•
•
Introduction to 2D using Java
Drawing Geometric Primitives
What are Affine Transforms
Java Frame Works – affine
References
Introduction to 2D using Java
• Java2D API includes these packages
java.awt
java.awt.image
java.awt.color
java.awt.font
java.awt.geom
java.awt.print
java.awt.renderable
Shapes and Areas
• Shapes - create standard shape objects and draw
them in one method call instead of drawing each
segment with multiple method calls. The shapes
include rectangles and ellipses and also arbitrary
shapes such as the Polygon class. The shape
classes implement the Shape interface and provide a
PathIterator that steps through the segments of the
given shape.
• Areas - combine shapes in different ways to create
new areas.
Strokes and Paint
• Stroke - vary the thickness of a line, produce
arbitrary dot-dash sequences, select how corners
and line ends are shaped, etc.
• Paint - fill the interiors of shapes, as well as outlines,
not just with solid colors but with
– gradients of one color to another, and
– textured patterns of tiled images.
Affine Transformations
• Transformations - affine transformations (i.e. those
geometrical transformations that keep parallel lines
parallel) can take a shape and translate it, rotate it,
shear it, compress or expand it. Multiple
transformations can be compounded together.
Compositing and Clipping
• Compositing - overlay shapes and images
according to several optional rules that take
advantage of the alpha transparency.
• Clipping - to speed up performance, only redraw the
portion of the display that lies within a given outline or
clip. With Java2d one can use arbitrary clip outlines
rather than just rectangles.
Text, Color and Images
• Text - vast array of text rendering capabilities that
range from the basic drawString() method to creating
your own editor from scratch.
• Color - lots of tools to help render colors in a
consistent manner regardless of the device on which
they are displayed.
• Images - use many of the above tools and
techniques that are used with shapes - e.g.
transformations, compositing, clipping etc. - on
images.
Image Filters and Printing
• Image processing - apply image filters edge enhancement, blurring, inversion, etc.
are available.
• Printing - print the graphics display to the
local printer as shown on the monitor.
Draw, then Display
• The typical Java 2D process begins with
method invocations to draw shapes and
strokes on what can be thought of as an offscreen image surface with arbitrarily fine
resolution. A rasterizer converts this offscreen image to a 2D array of pixel or point
values, which can be rendered on a monitor
screen or a printer.
The Graphics class
• The vast majority of uses for the Java 2D API
utilize a small subset of its capabilities
encapsulated in the java.awt.Graphics class.
Most methods of the Graphics class can be
divided into two basic groups:
1. Draw and fill methods, enabling you to render
basic shapes, text, and images
2. Attributes setting methods, which affect how that
drawing and filling appears
• Methods such as setFont and setColor define
how draw and fill methods render.
Drawing method examples
• drawString – For drawing text
g.drawString("Hello", 10, 10);
• drawImage – For drawing images g.drawImage(img,
0, 0, width, height, 0, 0, imageWidth,
imageHeight, null);
• drawLine, drawArc, drawRect, drawOval,
drawPolygon – For drawing geometric shapes
g2.draw(new Line2D.Double(0, 0, 30, 40));
Image scaling
• You can choose one of several methods in
the Graphics class based on whether you
want to render the image at the specified
location in its original size or scale it to fit
inside the given rectangle
Transparency and Fill
• You can fill the transparent areas of the
image with color or keep them transparent
• Fill methods apply to geometric shapes and
include fillArc, fillRect, fillOval, fillPolygon.
2D Coordinates
• Whether you draw a line of text or an image,
remember that in 2D graphics every point is
determined by its x and y coordinates. All of the
draw and fill methods need this information
which determines where the text or image
should be rendered.
Using x,y Coordinates
• For example, to draw a line, an application calls the
following:
java.awt.Graphics.drawLine(int x1, int y1, int
x2, int y2)
In this code (x1, y1) is the start point of the line, and
(x2, y2) is the end point of the line.
• So the code to draw a horizontal line is as follows:
Graphics.drawLine(20, 100, 120, 100);
Weather Painter class
This code draws an image determined by using the
setupWeatherReport() method.
...
origComposite = g2.getComposite();
if (alpha0 != null) g2.setComposite(alpha0);
g2.drawImage(img0, 0, 0, size.width, size.height,
0, 0, img0.getWidth(null), img0.getHeight(null),
null);
if (img1 != null) {
if (alpha1 != null) g2.setComposite(alpha1);
g2.drawImage(img1,0, 0, size.width, size.height,
0, 0, img1.getWidth(null), img1.getHeight(null),
null);
}
...
Weather example
(continued)
The setFont and drawString methods render the
temperature and the weather condition.
...
// Freezing, Cold, Cool, Warm, Hot,
// Blue, Green, Yellow, Orange, Red
Font font = new Font("Serif", Font.PLAIN, 36);
g.setFont(font);
String tempString = feels + " " + temperature+"F";
FontRenderContext frc =
((Graphics2D)g).getFontRenderContext();
...
Weather example
(continued)
• The setFont and drawString methods render the
temperature and the weather condition.
...
g.setColor(textColor);
int xTextTemp = rX-(int)boundsTemp.getX();
int yTextTemp = rY-(int)boundsTemp.getY();
g.drawString(tempString, xTextTemp, yTextTemp);
int xTextCond = rX-(int)boundsCond.getX();
int yTextCond = rY-(int)boundsCond.getY() +
(int)boundsTemp.getHeight(); g.drawString(condStr,
xTextCond, yTextCond);
Introduction to 2D using Java
(contd …)
•
The fillRect method allows you to draw a rectangle filled with the
specified color.
...
Rectangle2D boundsTemp =
font.getStringBounds(tempString, frc);
Rectangle2D boundsCond =
font.getStringBounds(condStr, frc);
int wText = Math.max((int)boundsTemp.getWidth(),
(int)boundsCond.getWidth());
int hText = (int)boundsTemp.getHeight() +
(int)boundsCond.getHeight();
int rX = (size.width-wText)/2;
int rY = (size.height-hText)/2;
g.setColor(Color.LIGHT_GRAY);
g2.fillRect(rX, rY, wText, hText);
...
Geometric Primitives
• The Java 2D™ API provides several classes that
define common geometric objects such as points,
lines, curves, and rectangles. These geometry
classes are part of the java.awt.geom package.
• The PathIterator interface defines methods for
retrieving elements from a path.
Shape Interface
• The Shape interface provides a set of methods for
describing and inspecting geometric path objects.
This interface is implemented by the GeneralPath
class and other geometry classes.
Geometric Primitives
• All examples represented in this section create
geometries by using java.awt.geom and then render
them by using the Graphics2D class. To begin you
obtain a Graphics2D object, for example by casting
the Graphics parameter of the paint() method.
public void paint (Graphics g) {
Graphics2D g2 = (Graphics2D) g;
...
}
Point
• The Point class creates a point representing
a location in (x,y) coordinate space. The
subclasses Point2D.Float and
Point2D.Double provide correspondingly float
and double precision for storing the
coordinates of the point.
//Create Point2D.Double
Point2D.Double point = new Point2D.Double(x,
y);
Point Locations
• To create a point with the coordinates 0,0 you use the
defaultconstructor, Point2D.Double() .
You can use the setLocation method to set the
position of the point as follows:
setLocation(double x, double y) – To set the
location of the point- defining coordinates as double
values
Set Location
• setLocation(Point2D p) – To set the location of the
point using the coordinates of another point.
Also, the Point2D class has methods to calculate the
distance between the current point and a point with
given coordinates, or the distance between two
points.
Line
• The Line2D class represents a line segment in (x, y)
coordinate space. The Line2D.Float and
Line2D.Double subclasses specify lines in float and
double precision. For example:
// draw Line2D.Double
g2.draw(new Line2D.Double(x1, y1, x2, y2));
Set Line methods
• This class includes several setLine() methods to
define the endpoints of the line.
Alternatively, the endpoints of the line could be
specified by using the constructor for the
Line2D.Float class as follows:
– Line2D.Float(float X1, float Y1, float X2,
float Y2)
– Line2D.Float(Point2D p1, Point2D p2)
• Use the Stroke object in the Graphics2D class to
define the stroke for the line path.
Ellipse
• The Ellipse2d class represents an ellipse defined by
a bounding rectangle. The Ellipse2D.Float and
Ellipse2D.Double subclasses specify an ellipse in
float and double precision. Ellipse is fully defined by
a location, a width and a height. For example:
// draw Ellipse2D.Double
g2.draw(new Ellipse2D.Double(x, y, rectwidth,
rectheight));
Rectangle
• Classes that specify primitives represented in the
following example extend the RectangularShape
class, which implements the Shape interface and adds
a few methods of its own.
These methods enables you to get information about
a shape’s location and size, to examine the center
point of a rectangle, and to set the bounds of the
shape.
Rectangle
• The Rectangle2D class represents a
rectangle defined by a location (x, y) and
dimension (w x h). The Rectangle2D.Float
and Rectangle2D.Double subclasses specify
a rectangle in float and double precision. For
example:
// draw Rectangle2D.Double
g2.draw(new Rectangle2D.Double(x, y, rectwidth,
rectheight));
Rounded Rectangle
• The RoundRectangle2D class represents a rectangle
with rounded corners defined by a location (x, y), a
dimension (w x h), and the width and height of the
corner arc. The RoundRectangle2D.Float and
RoundRectangle2D.Double subclasses specify a
round rectangle in float and double precision.
Specifying Rounded Rectangle
• The rounded rectangle is specified with
following parameters:
–
–
–
–
–
Location
Width
Height
Width of the corner arc
Height of the corner acr
Rounded Rectangle location
• To set the location, size, and arcs of a
RoundRectangle2D object, use the method
setRoundRect(double a, double y, double w,
double h, double arcWidth, double arcHeight).
For example:
// draw RoundRectangle2D.Double
g2.draw(new RoundRectangle2D.Double(x, y,
rectwidth, rectheight, 10, 10));
Drawing Geometric Primitives
(Contd …)
• The example at
http://java.sun.com/docs/books/tutorial/2d/geometry/e
xamples/ShapesDemo2D.java code contains
implementations off all the described geometric
primitives.
• For more information about classes and methods
represented in this section see the
http://java.sun.com/javase/6/docs/api/java/awt/geom/
package-summary.html specification.
What is an Affine Transform?
• The Affine Transform class represents a 2D
Affine transform that performs a linear mapping
from 2D coordinates to other 2D coordinates that
preserves the "straightness" and "parallelness" of
lines. Affine transformations can be constructed
using sequences of translations, scales, flips,
rotations, and shears.
What is affine Transform
(contd…)
• An Affine Transform is a linear transform, so the
transformation can be expressed in the matrix notation of linear
algebra. An arbitrary Affine Transform can be mathematically
expressed by six numbers in a matrix like this:
sx shx tx
shy sy ty
• The symbols or factors sx and sy are scale factors that
accomplish scaling. The factors tx and ty are scale factors that
accomplish translation. The factors shx and shy are scale
factors that accomplish shear.
What is affine Transform
(contd…)
• Your graphics can be transformed in the
following ways before being displayed on the
output device:
Scaling
Translation
Shear
Rotation
(rotation is a combination of scaling and shearing, so there are
not separate rx and ry numbers. )
Scaling
• Scaling is perhaps the easiest of the four types of
transforms to understand. This simply means that if a
point is located at a horizontal coordinate value of x
in user space, it will be located at sx*x in device
space, where sx is a numeric multiplier that can be
either positive or negative.
Translation
 Translation moves the origin of the
coordinate system in device space.
 Another use of translation (in combination
with scaling) is to flip the default positive
direction of the vertical axis so that increasing
positive values go up instead of down, which
is the default.
Shear
• Jonathan Knudsen describes shear in his book
entitled Java 2D Graphics as:
“Take a stack of paper (like you might place in your
laser printer) and draw a picture on the side of the
stack. Then deform the stack so that the side of the
stack on which you drew the picture takes the form of
a parallelogram. Be especially careful to keep the
opposite sides parallel. Then look at your picture. It
will have been subjected to shear in one dimension.”
Affine Transform class
• public class AffineTransform
extends Object
implements Cloneable, Serializable
• The AffineTransform class represents a 2D affine
transform that performs a linear mapping from 2D
coordinates to other 2D coordinates that preserves
the "straightness" and "parallelness" of lines. Affine
transformations can be constructed using sequences
of translations, scales, flips, rotations, and shears.
Affine Transforms as matrix
multiplications
• Such a coordinate transformation can be represented by a
3 row by 3 column matrix with an implied last row of [ 0 0 1
]. This matrix transforms source coordinates (x, y) into
destination coordinates (x', y') by considering them to be a
column vector and multiplying the coordinate vector by the
matrix according to the following process:
[ x']
[ y'] =
[ 1 ]
[
[
[
m00
m10
0
m01
m11
0
m02
m12
1
] [ x ]
[ m00x + m01y + m02 ]
] [ y ] = [ m10x + m11y + m12 ]
] [ 1 ]
[ 1 ]
Rotation
• Rotation is easy to visualize (but the combination of
rotation and shear can be very difficult to
visualize). To visualize rotation, draw a picture on a
piece of paper. Use a single tack to attach it to a
bulletin board. Then rotate the paper a few degrees
around the tack. You will have rotated the picture
around the coordinates of the tack by the specified
number of degrees.
Rotation in Java 2D
• Java 2D works the same way. In the process of
transforming a graphic from user space to device
space, you can cause it to be rotated by a specified
angle around a specified coordinate position.
• However, in Java 2D, the angle must be specified in
radians instead of degrees. If you are unfamiliar with
the use of radian measure to specify an angle, just
remember the following identity:
Radiand and Degrees
• PI radians = 180 degrees
• PI is the numeric value you learned about in
geometry class.
• PI has a value of 3.14159........... However, you don’t
have to remember the value of PI. It is available as a
static final constant in the Math class. You can
access the value as Math.PI.
Dividing PI Radians
• If this sounds confusing, you might also want
to remember the following identities:
• PI/2 = 90 degrees
PI/4 = 45 degrees
PI/8 = 22.5 degrees
PI/16 = 11.25 degrees, etc.
Rotation direction
• Positive angles of rotation proceed in a
clockwise direction. This may be backwards
from what you are accustomed to in various
science and engineering endeavors where
counter-clockwise rotation is often thought of
as the positive direction of rotation.
Java Frame Works - affine
• Java's Abstract Window Toolkit (AWT) provides a
Graphics class with methods for drawing lines, ovals,
rectangles, text, polygons, and other shapes. A
Panel, Frame, or other AWT component draws itself
using the Graphics instance passed to its paint
method. The GUI environment automatically calls this
method whenever the component needs redrawing.
Java Frame Works – affine
• Sun added the Java 2D framework on top of the
original AWT Graphics class, adding many new
features to the Java core API. One important Java2D
feature is known as the affine transformation. It works
by transforming the coordinate system before any
drawing is done on the Graphics object.
JFrame example
• To illustrate this, we'll skew the coordinates with a
shearing transformation and draw some text and
graphics to see how it looks with and without the
transformation. First, let's draw some text, using the
default coordinates, We'll do this in the paint method
of a JFrame:
Example (page 1)
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
public class MyTransform extends JFrame {
public MyTransform(String title) {
super(title);
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setFont(Font.decode("arial-bold-36"));
g2d.drawString("Affinity", 100, 100);
g2d.drawOval(100, 150, 35, 50);
g2d.drawOval(135, 150, 35, 50);
}
Example (page 2)
public static void main(String[] args) {
MyTransform aft = new MyTransform("Affinity");
aft.setSize(300,300);
aft.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
aft.setVisible(true);
}
}
Java affine Frameworks
• In all affine transformations , the change affects the
entire coordinate system and not just individual
objects. We call the methods to apply the transforms
before calling the drawing methods. Let's display the
above text with a shearing transform, This is a
transform where lines are shifted in a new direction
but parallel lines still remain parallel. The call to the
shear method happens before the drawing occurs.
Here is code to perform the transform:
Modifications to Example
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.shear(0.5,0.5);
g2d.setFont(Font.decode("arial-bold-36"));
g2d.drawString("Affinity", 100, 100);
g2d.drawOval(100, 150, 35, 50);
g2d.drawOval(135, 150, 35, 50);}
References
http://java.sun.com/
http://www.developer.com/
http://www.particle.kth.se/htmlnew/
Download