Download: jar file
A "grow line" is a line that is continually redrawn as the mouse is dragged from a fixed pivot point.
getGraphics()setXORModedrawLine
growline.javaLine2.javaVec2.javagrowline.java001: 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.java001: /* \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.java001: // 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