Download: jar file
A "grow line" is a line that is continually redrawn as the mouse is dragged from a fixed pivot point.
getGraphics()
setXORMode
drawLine
growline.java
Line2.java
Vec2.java
growline.java
001: import java.awt.*; 002: import java.awt.event.*; 003: import java.util.*; 004: import java.awt.geom.*; 005: import javax.swing.*; 006: 007: 008: class MousePanel extends JPanel implements MouseMotionListener 009: { 010: ArrayList<Line2> lines; 011: Point base, current; 012: boolean isDragging; 013: 014: MousePanel() 015: { 016: isDragging = false; 017: lines = new ArrayList<Line2>(); 018: addMouseListener(new MouseHandler()); 019: addMouseMotionListener(this); 020: } 021: 022: public void paintComponent(Graphics g) 023: { 024: super.paintComponent(g); 025: 026: Graphics2D g2 = (Graphics2D) g; 027: for (Line2 line: lines) line.draw(g); 028: } 029: 030: private class MouseHandler extends MouseAdapter 031: { 032: 033: public void mousePressed(MouseEvent event) 034: { 035: isDragging = true; 036: current = event.getPoint(); 037: base = event.getPoint(); 038: } 039: 040: public void mouseReleased(MouseEvent event) 041: { 042: isDragging = false; 043: current = event.getPoint(); 044: 045: Graphics g = getGraphics(); 046: int bx = base.x; 047: int by = base.y; 048: g.setXORMode(Color.WHITE); 049: g.drawLine(bx,by,current.x,current.y); 050: g.setPaintMode(); 051: g.setColor(Color.BLACK); 052: lines.add(new Line2(bx,by,current.x,current.y)); 053: repaint(); 054: } 055: } 056: 057: public void mouseDragged(MouseEvent event) 058: { 059: Graphics g = getGraphics(); 060: int bx = base.x; 061: int by = base.y; 062: g.setXORMode(Color.WHITE); 063: g.drawLine(bx,by,current.x,current.y); 064: current = event.getPoint(); 065: g.drawLine(bx,by,current.x,current.y); 066: g.setPaintMode(); 067: g.setColor(Color.BLACK); 068: } 069: 070: public void mouseMoved(MouseEvent event) 071: { 072: } 073: } 074: 075: public class growline extends JApplet 076: { 077: public void init() 078: { 079: EventQueue.invokeLater(new Runnable() { 080: public void run() 081: { 082: MousePanel panel = new MousePanel(); 083: add(panel); 084: } 085: }); 086: } 087: public static void main(String[] args) 088: { 089: EventQueue.invokeLater(new Runnable() { 090: public void run() 091: { 092: MousePanel panel = new MousePanel(); 093: JFrame frame = new JFrame("Grow Line"); 094: frame.add(panel); 095: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 096: frame.setSize(400,400); 097: frame.setVisible(true); 098: } 099: }); 100: } 101: }
Line2.java
001: /* \file Line2.java 002: * 003: */ 004: import java.awt.Graphics; 005: 006: public class Line2 007: { 008: public Vec2 [] pt; 009: public Line2() { this(0.0,0.0,0.0,0.0); } //!< default no-argument constructor 010: public Line2(Vec2 to) { this(0.0,0.0,to.v[0],to.v[1]); } 011: //! construct Line2 from origin to (x,y) 012: public Line2(double x, double y) { this(0.0,0.0,x,y); } 013: //! constructs Line2 from (x1,y1) to (x2,y2) 014: public Line2(double x1, double y1, double x2, double y2) 015: { 016: pt = new Vec2[2]; 017: pt[0] = new Vec2(x1,y1); 018: pt[1] = new Vec2(x2,y2); 019: } 020: //! construct Line2 from screen coordinates (integers) 021: public Line2(int x1, int y1, int x2, int y2) 022: { 023: pt = new Vec2[2]; 024: pt[0] = new Vec2(x1,y1); 025: pt[1] = new Vec2(x2,y2); 026: } 027: //! constructs Line2 from two points 028: public Line2(Vec2 from, Vec2 to) 029: { 030: pt = new Vec2[2]; 031: pt[0] = new Vec2(from); 032: pt[1] = new Vec2(to); 033: } 034: //! returns length of associated array 035: public int rows() { return 2; } 036: public int cols() { return 2; } 037: //! return pointer to first element 038: public Line2 set(double x1, double y1, double x2, double y2) 039: { 040: pt[0].v[0]=x1; pt[0].v[1]=y1; 041: pt[1].v[0]=x2; pt[1].v[1]=y2; 042: return this; 043: } 044: public Line2 from(double x, double y) 045: { 046: pt[0].v[0]=x; pt[0].v[1]=y; 047: return this; 048: } 049: public Line2 from(Vec2 src) 050: { 051: pt[0]=src; 052: return this; 053: } 054: public Line2 to(double x, double y) 055: { 056: pt[1].v[0]=x; pt[1].v[1]=y; 057: return this; 058: } 059: 060: public Line2 to(Vec2 src) { 061: pt[1]=src; 062: return this; 063: } 064: 065: public Line2 away(double r, double theta) 066: { 067: Vec2 angl = new Vec2(theta); 068: pt[1] = Vec2.sum(pt[0],angl.scale(r)); 069: return this; 070: } 071: 072: public Line2 translate(double tx, double ty) 073: { 074: pt[0].translate(tx,ty); pt[1].translate(tx,ty); 075: return this; 076: } 077: 078: public Line2 translate(Vec2 b) 079: { 080: pt[0].translate(b); pt[1].translate(b); 081: return this; 082: } 083: 084: public Vec2 getDirection() 085: { 086: return Vec2.diff(pt[1],pt[0]); 087: } 088: 089: public void draw(Graphics g) 090: { 091: int [] from = pt[0].convert(); 092: int [] to = pt[1].convert(); 093: g.drawLine(from[0],from[1],to[0],to[1]); 094: } 095: 096: public String toString() 097: { 098: return (pt[0] + ":" + pt[1]); 099: } 100: 101: //! return distance between two endpoints 102: public double length() 103: { 104: return Vec2.distance(pt[0],pt[1]); 105: } 106: 107: //! returns angle (in degrees) between two lines 108: public static double angle(Line2 a, Line2 b) 109: { 110: Vec2 va = Vec2.diff(a.pt[1],a.pt[0]); 111: Vec2 vb = Vec2.diff(b.pt[1],b.pt[0]); 112: return Vec2.angle(va,vb); 113: } 114: public Vec2 lerp(double u) 115: { 116: double up = 1.0-u; 117: double x = up*pt[0].v[0]+u*pt[1].v[0]; 118: double y = up*pt[0].v[1]+u*pt[1].v[1]; 119: return new Vec2(x,y); 120: } 121: 122: public double getClosestPosition( Vec2 v) 123: { 124: Vec2 p = Vec2.diff(v,pt[0]); 125: Vec2 k = getDirection(); 126: return Vec2.dot(p,k)/Vec2.dot(k,k); 127: } 128: }
Vec2.java
001: // Vec2.java 002: // Definition of class Vec2 003: import java.awt.Graphics; 004: 005: /** 006: * <b>Vec2</b> describes a two-dimensional point. 007: */ 008: 009: public class Vec2 010: { 011: static double Resolution = 96; 012: static int xoffset = 120; 013: static int yoffset = 120; 014: public double [] v; // coordinates of the Point 015: 016: // No-argument constructor 017: public Vec2() { this( 0, 0 ); } 018: 019: 020: // Constructor 021: public Vec2( double x, double y ) 022: { 023: v = new double[2]; 024: set(x,y); 025: } 026: 027: public Vec2( int x, int y) 028: { 029: v = new double[2]; 030: reconvert(x,y); 031: } 032: 033: // copy constructor 034: public Vec2( Vec2 src) 035: { 036: this(src.v[0],src.v[1]); 037: } 038: 039: // Constructor (angle theta) 040: public Vec2(double theta) 041: { 042: theta *= radg; 043: v = new double[2]; 044: set(Math.cos(theta),Math.sin(theta)); 045: } 046: 047: 048: public int length() { return v.length; } 049: 050: 051: // Set x and y coordinates of Point 052: public Vec2 set( double x, double y ) 053: { 054: v[0] = x; 055: v[1] = y; 056: return this; 057: } 058: 059: public int [] convert() 060: { 061: int [] iv = new int[2]; 062: convert(iv); 063: return iv; 064: } 065: 066: public void convert(int [] iv) 067: { 068: if (Resolution == 0) 069: { 070: iv[0] = (int) v[0]; 071: iv[1] = (int) v[1]; 072: } 073: else 074: { 075: iv[0] = (int) (xoffset + v[0]*Resolution); 076: iv[1] = (int) (yoffset - v[1]*Resolution); 077: } 078: } 079: 080: public void reconvert(int x, int y) 081: { 082: if (Resolution==0) 083: { 084: v[0] = x; 085: v[1] = y; 086: } 087: else { 088: v[0] = (x-xoffset)/Resolution; 089: v[1] = (yoffset-y)/Resolution; 090: } 091: } 092: 093: static public Vec2 sum(Vec2 a, Vec2 b) 094: { 095: return new Vec2(a.v[0]+b.v[0],a.v[1]+b.v[1]); 096: } 097: 098: static public Vec2 diff(Vec2 a, Vec2 b) 099: { 100: return new Vec2(a.v[0]-b.v[0],a.v[1]-b.v[1]); 101: } 102: 103: /** 104: * returns magnitude of 2D vector 105: */ 106: public double magn() 107: { 108: return Math.sqrt(v[0]*v[0]+v[1]*v[1]); 109: } 110: 111: // multiply point by a scalar 112: public Vec2 scale(double s) 113: { 114: v[0] *= s; 115: v[1] *= s; 116: return this; 117: } 118: 119: 120: // offset (translate) point by the amount (tx, ty) 121: public Vec2 translate(double tx, double ty) 122: { 123: v[0] += tx; 124: v[1] += ty; 125: return this; 126: } 127: 128: // offset (translate) point by a Vec2 129: public Vec2 translate(Vec2 b) 130: { 131: v[0] += b.v[0]; 132: v[1] += b.v[1]; 133: return this; 134: } 135: 136: final static double radg = Math.atan(1)/45.0; 137: 138: // rotate point about the origin 139: public Vec2 rotate(double theta) 140: { 141: double c, s, t; 142: theta *= radg; 143: c = Math.cos(theta); 144: s = Math.sin(theta); 145: t = v[1]*c+v[0]*s; 146: v[0] = v[0]*c-v[1]*s; 147: v[1] = t; 148: return this; 149: } 150: 151: public Vec2 perp() 152: { 153: double t = v[0]; 154: v[0] = -v[1]; 155: v[1] = t; 156: return this; 157: } 158: 159: static public Vec2 perp(Vec2 a) 160: { 161: return new Vec2(-a.v[1],a.v[0]); 162: } 163: 164: static public double perpdot(Vec2 a, Vec2 b) 165: { 166: return (a.v[0]*b.v[1]-a.v[1]*b.v[0]); 167: } 168: 169: static public double dot(Vec2 a, Vec2 b) 170: { 171: return (a.v[0]*b.v[0]+a.v[1]*b.v[1]); 172: } 173: 174: static public double distance(Vec2 a, Vec2 b) 175: { 176: return Vec2.diff(a,b).magn(); 177: } 178: 179: //! returns angle (in degrees) between two vectors 180: static public double angle(Vec2 a, Vec2 b) 181: { 182: double c, s; 183: c = dot(a,b); 184: s = perpdot(a,b); 185: return Math.atan2(s,c)/radg; 186: } 187: 188: public void setSize(double sz) 189: { 190: double vnorm = magn(); 191: if (vnorm==0.0) return; 192: sz /= vnorm; 193: v[0] *= sz; 194: v[1] *= sz; 195: } 196: 197: public void draw(Graphics g) 198: { 199: int [] iv = convert(); 200: g.fillOval(iv[0]-4,iv[1]-4,9,9); 201: } 202: 203: // convert the point into a String representation 204: public String toString() 205: { return String.format("[%.3g %.3g]",v[0],v[1]); } 206: 207: static public void main(String args[]) 208: { 209: Vec2 a, b, xaxis; 210: a = new Vec2(0.2,0.5); 211: System.out.println("a = " + a); 212: int [] iv = a.convert(); 213: System.out.println("a.convert() = " + iv[0] + " " + iv[1]); 214: System.out.println("perp(a) = " + perp(a) ); 215: b = new Vec2(1,0); 216: b.scale(2).rotate(30); 217: xaxis = new Vec2(1,0); 218: System.out.println("b = " + b + String.format(" magn %.3g at %.3g deg.",b.magn(),angle(xaxis,b))); 219: } 220: 221: }
Maintained by John Loomis, updated Thu Mar 27 21:34:10 2008