Java 2D Graphics Drawing Primitives, Affine Transformations, Scene Graphs, Hit Tests Drawing Primitives Graphics - Abstract Base Class that supports basic drawing and rendering - Conceptually sim. to WatGUI Graphics object - Provides methods to draw primitives http://docs.oracle.com/javase/7/docs/api/java/awt/graphics.html Using it is simple - Instantiate a canvas (JPanel) - Override PaintComponent(Graphics g) 2 1
Demo: SimpleDraw // JComponent is a base class for custom components public class SimpleDraw extends JComponent { public static void main(string[] args) { SimpleDraw canvas = new SimpleDraw(); JFrame f = new JFrame("SimpleDraw"); // jframe is app window f.setdefaultcloseoperation(jframe.exit_on_close); f.setsize(400, 400); // window size f.setcontentpane(canvas); // add canvas to jframe f.setvisible(true); // show the window // custom graphics drawing public void paintcomponent(graphics g) { Graphics2D g2 = (Graphics2D) g; // cast for 2D drawing methods g2.setstroke(new BasicStroke(32)); // 32 pixel thick stroke g2.setcolor(color.blue); // make it blue g2.drawline(0, 0, getwidth(), getheight()); // draw line g2.setcolor(color.red); g2.drawline(getwidth(), 0, 0, getheight()); 3 Java2D AffineTransform Class AffineTransform handles all matrix manipulations - A bit more control than Graphics2D Static Methods - static AffineTransform getrotateinstance(double theta) - static AffineTransform getrotateinstance(double theta, double anchorx, double anchory) - static AffineTransform getscaleinstance( double sx, double sy) - static AffineTransform gettranslateinstance( double tx, double ty) 4 2
Java2D AffineTransform Class Concatenation methods - void rotate(double theta), void rotate(double theta, double anchorx, double anchory) - void scale(double sx, double sy) - void translate(double tx, double ty) - void concatenate(affinetransform Tx) Other Methods - AffineTransform createinverse() - void transform(point2d[] ptsrc, int srcoff, Point2D[] ptdst, int dstoff, int numpts) * 5 Useful Graphics2D methods - AffineTransform gettransform(), void settransform(affinetransform Tx) Returns/sets a copy of the current Transform in the Graphics2D context. - void rotate(double theta), void rotate(double theta, double x, double y) Concatenates the current Graphics2D Transform with a rotation transform. Second variant translates origin to (x,y), rotates, and translates origin (-x, -y). - void scale(double sx, double sy) Concatenates the current Graphics2D Transform with a scaling transformation. Subsequent rendering is resized according to the specified scaling factors relative to the previous scaling. - void translate(double tx, double ty) Concatenates the current Graphics2D Transform with a translation transform. 6 3
Demo: RotateLine.java public void paintcomponent(graphics g) { Graphics2D g2 = (Graphics2D) g; // draw axes g2.translate(20, 240); g2.setstroke(new BasicStroke(3)); g2.setcolor(color.black); g2.drawline(0, 0, 0, - 200); // vertical axis g2.drawline(0, 0, 200, 0); // horizontal axis // draw a line w. ends along the x axis g2.setstroke(new BasicStroke(5)); g2.setcolor(color.red); g2.drawline(40, 0, 120, 0); g2.drawoval(40-4, - 4, 8, 8); g2.drawoval(120-4, - 4, 8, 8); 7 // rotate the line? Demo: AffineDemo.java 8 4
Shape Model an array of points: {P 1, P 2,, P n isclosed flag (shape is polyline or polygon) isfilled flag (polygon is filled or not) (and stroke thickness, colours, etc.) 9 Constructing Complex Shapes Construct instance of Polygon class from Point2D list g2.drawpolygon (x_points, y_points, points.size()); g2.drawpolyline (x_points, y_points, points.size()); public void paint(graphics2d g2) { g2.setcolor(color.yellow); g2.setstroke(new BasicStroke(12)); g2.drawpolygon(x_points, y_points, points.size()); 10 5
Demo: ShapeDemo, ShapeDemo2 MyShape.java Point2D.Double type haschanged flag // call right drawing function if (isfilled) g2.fillpolygon(x_points, y_points, points.size()); else if (isclosed) g2.drawpolygon(x_points, y_points, points.size()); else g2.drawpolyline(x_points, y_points, points.size()); 11 Scene Graphs Each part has a transform matrix Each part draws its children relative to itself 12 6
Inside/Hit Tests with Transformed Shapes Mouse and shape model must use same coordinate system Two options: - Transform mouse to model coordinates - Transform shapes to mouse coordinates 13 Transform Mouse to Model Coordinates Only one transformation Within 3 pixels of a line in screen coordinates is how far in model coordinates? Uniform scaling Maintaining the inverse 14 7
Transform Model to Mouse Coordinates Many transformations Manipulations (e.g. dragging) must be transformed back into model coordinates 15 Demo: ShapeDemo3 public boolean contains(graphics2d g, Point2D mouse) { AffineTransform inverse = null; try { inverse = g.gettransform().createinverse(); catch (NoninvertibleTransformException e) { System.out.print(e); // move mouse back to origin Point2D mouset = new Point2D.Float(); inverse.transform(mouse, mouset); // compare un- translated polygon to mouse coordinates Polygon p = new Polygon(x_points, y_points, points.size()); return p.contains(mouset.getx(), mouset.gety()); 16 8