2D Graphics Shape Models, Drawing, Selection using Java 1
Graphic Models vs. Images Computer Graphics: the creation, storage, and manipulation of images and their models Model: a mathematical representation of an image containing the important properties of an object (location, size, orientation, color, texture, etc.) in data structures Rendering: Using the properties of the model to create an image to display on the screen Image: the rendered model Model Rendering Image 2
Implementing Direct Manipulation Objectives: draw a shape on the screen at specified position, size, orientation perhaps draw many copies, each different from the others test when a rendered shape is selected could be a filled or outlined polygon or a polyline selections that just miss the shape should snap to shape Tasks: create a model of the shape Now: what we did in X, in Java draw it Later: 2D transformations choose a selection paradigm implement shape hit tests and/or inside tests (with snapping) respond to events 3
Example Shape Models An array of points: {P 1, P 2,, P n Can be open, closed, filled Java has primitive shapes built in: Lines, Ellipses, Rectangles Tools for building others: CubicCurves, Paths, drawpolygon, drawpolyline, fillpolygon 4
SimpleDraw: Drawing in Java package twod_graphics; import javax.swing.*; import java.awt.*; import java.awt.geom.path2d; public class SimpleDraw { public static void main(string[] args) { JFrame f = new JFrame("SimpleDraw"); // jframe is the app window f.setdefaultcloseoperation(jframe.exit_on_close); f.setsize(400, 400); // window size f.setcontentpane(new Canvas()); // add canvas to jframe f.setvisible(true); // show the window // JComponent is a base class for custom components class Canvas extends JComponent { // custom graphics drawing public void paintcomponent(graphics g) { 5
SimpleDraw: Drawing in Java package twod_graphics; import javax.swing.*; import java.awt.*; import java.awt.geom.path2d; public class SimpleDraw { // JComponent is a base class for custom components class Canvas extends JComponent { // custom graphics drawing public void paintcomponent(graphics g) { super.paintcomponent(g); Graphics2D g2 = (Graphics2D) g; g2.setstroke(new BasicStroke(32)); g2.setcolor(color.blue); g2.drawline(0, 0, getwidth(), getheight()); // draw line g2.setcolor(color.red); g2.drawline(getwidth(), 0, 0, getheight()); g2.setcolor(color.yellow); g2.setstroke(new BasicStroke(1)); g2.draw(new Star()); // cast to get 2D drawing methods // 32 pixel thick stroke // make it blue 6
SimpleDraw: Drawing in Java package twod_graphics; import javax.swing.*; import java.awt.*; import java.awt.geom.path2d; public class SimpleDraw { class Canvas extends JComponent { class Star extends Path2D.Double { public Star() { super(wind_even_odd); this.moveto(0, 0); this.lineto(-1.5, 5); this.lineto(-7, 5); this.lineto(-2.5, 8); this.lineto(-4.2, 13); this.lineto(0, 10); this.lineto(4.2, 13); this.lineto(2.5, 8); this.lineto(7, 5); this.lineto(1.5, 5); this.lineto(0, 0); How do you get the star where you want it and the size you want? 7
Selection Paradigms Click selection different for filled and outlined shapes Rubberband rectangle Lasso (see Ch 14 of text) 8
Closest Shape to Mouse Test check distance from every line segment of every shape to mouse position (can be optimized ) check distance from mouse to line segment using vector projection ClosestPointDemo.java 9 http://en.wikipedia.org/wiki/distance_from_a_point_to_a_line
Mouse Inside Filled-Shape Test Is a point inside or outside a polygon? P1 P3 P4 P2 Java Shapes have a contains(point2d p) method 10
MouseEventDemo (1/4) import javax.swing.jframe; import javax.swing.jcomponent; import java.awt.event.*; import java.awt.*; public class MouseEventDemo { public static void main(string[] args) { JFrame f = new JFrame("MouseEventDemo"); // jframe is the app window f.setdefaultcloseoperation(jframe.exit_on_close); f.setsize(400, 400); // window size f.setcontentpane(new Canvas()); // add canvas to jframe f.setvisible(true); // show the window Same as before, except for imports. 11
MouseEventDemo (2/4) class Canvas extends JComponent { 12 private Color colour = Color.GRAY; private int x; private int y; private int size = 50; Canvas() { // add listeners this.addmouselistener(new MListener()); this.addmousemotionlistener(new MMListener()); // custom graphics drawing public void paintcomponent(graphics g) { super.paintcomponent(g); Graphics2D g2 = (Graphics2D) g; g2.setcolor(colour); g2.filloval(this.x - this.size / 2, this.y - this.size / 2, this.size, this.size); private class MListener implements MouseListener { private class MMListener implements MouseMotionListener { Updated when appropriate events are received. Each listener defines a group of events that we care about. Same function as XSelectInput. What do we do when we receive an event?
MouseEventDemo (3/4) private class MMListener implements MouseMotionListener { @Override public void mousedragged(mouseevent arg0) { System.out.format("drag %d,%d\n", arg0.getx(), arg0.gety()); x = arg0.getx(); y = arg0.gety(); repaint(); A mouse motion listener is interested in two kinds of events: mouse moved and mouse dragged. @Override public void mousemoved(mouseevent arg0) { System.out.format("move %d,%d\n", arg0.getx(), arg0.gety()); x = arg0.getx(); y = arg0.gety(); repaint(); 13
MouseEventDemo (4/4) private class MListener implements MouseListener { @Override public void mouseclicked(mouseevent arg0) { System.out.format("click %d,%d count %d\n", arg0.getx(), arg0.gety(), arg0.getclickcount()); if (arg0.getclickcount() == 2) // double click Canvas.this.colour = Color.PINK; else Canvas.this.colour = Color.GREEN; Canvas.this.repaint(); @Override public void mouseentered(mouseevent arg0) { System.out.format("enter %d,%d\n", arg0.getx(), arg0.gety()); Canvas.this.colour = Color.BLACK; Canvas.this.repaint(); @Override public void mouseexited(mouseevent arg0) { @Override public void mousepressed(mouseevent arg0) { 14 @Override public void mousereleased(mouseevent arg0) { System.out.format("release %d,%d\n", arg0.getx(), arg0.gety()); colour = Color.BLUE; repaint();