Commit a00d2347 authored by Daniel Vogel's avatar Daniel Vogel
Browse files

added affine demos

parent 7c10e239
/*
* CS 349 Java Code Examples
*
* BarExercise Demo of multiple transformation exercise.
*
*/
import javax.swing.JFrame;
import javax.swing.JComponent;
import javax.swing.JButton;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.vecmath.*;
import java.lang.Math.*;
import java.util.Random;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
// create the window and run the demo
public class BarExercise {
public static void main(String[] args) {
// create the window
Canvas canvas = new Canvas();
JFrame f = new JFrame("BarExercise"); // jframe is the app window
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500, 500); // window size
f.setContentPane(canvas); // add canvas to jframe
f.setBackground(Color.WHITE);
f.setVisible(true); // show the window
}
}
class Canvas extends JComponent {
// the house shape (model position is centred at top left corner)
private Polygon shape = new Polygon(new int[] { -50, 50, 50, 0, -50},
new int[] { 75, 75, -25, -75, -25}, 5);
int step = 0;
Canvas() {
// only mouse clicked events
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
step ++;
repaint();
}
});
}
// custom graphics drawing
public void paintComponent(Graphics g) {
super.paintComponent(g); // JPanel paint
Graphics2D g2 = (Graphics2D)g;
// make a centred grid
int gridSize = 250;
g2.translate((this.getWidth() - gridSize) / 2, (this.getHeight() - gridSize) / 2);
drawGrid(g2, gridSize, gridSize, gridSize / 10);
// draw the original shape in "model" coordinates
g2.setColor(Color.BLACK);
drawBar(g2, 50, 100, 150, 100);
// save the current transform matrix
AffineTransform M = g2.getTransform();
// the shape will get transformed into "world" coordinates
if (true) {
g2.translate(50, 100);
g2.rotate(Math.toRadians(30));
g2.translate(-50, -100);
g2.setColor(Color.BLUE.darker());
drawBar(g2, 50, 100, 150, 100);
// demo the steps
} else {
g2.setColor(Color.BLUE.darker());
switch (step % 4) {
case 1:
g2.translate(-50, -100);
drawBar(g2, 50, 100, 150, 100);
g2.setTransform(M);
break;
case 2:
g2.rotate(Math.toRadians(30));
g2.translate(-50, -100);
drawBar(g2, 50, 100, 150, 100);
g2.setTransform(M);
break;
case 3:
g2.translate(50, 100);
g2.rotate(Math.toRadians(30));
g2.translate(-50, -100);
drawBar(g2, 50, 100, 150, 100);
g2.setTransform(M);
break;
}
}
}
private void drawBar(Graphics2D g2, int x1, int y1, int x2, int y2) {
int d = 12;
g2.setStroke(new BasicStroke(4));
g2.drawLine(x1, y1, x2, y2);
g2.fillOval(x1 - d/2, y1 - d/2, d, d);
g2.fillOval(x2 - d/2, y2 - d/2, d, d);
}
private void drawGrid(Graphics2D g2, int w, int h, int s) {
// Draw grid
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.GRAY.brighter());
// horizontal lines
for(int i = 0; i <= h; i += s) {
g2.drawLine(0, i, w, i);
}
// vertical lines
for(int i = 0; i <= w; i += s) {
g2.drawLine(i, 0, i, h);
}
}
}
/* /*
* CS 349 Java Code Examples * CS 349 Java Code Examples
* *
* ClosestPointDemo Uses two methods to compute distance from * ClosestPoint Uses two methods to compute distance from
mouse to closest point on line. Double click mouse to closest point on line. Double click
to generate new line. to generate new line.
* *
...@@ -19,7 +19,7 @@ import java.lang.Math.*; ...@@ -19,7 +19,7 @@ import java.lang.Math.*;
import java.util.Random; import java.util.Random;
// create the window and run the demo // create the window and run the demo
public class ClosestPointDemo extends JPanel public class ClosestPoint extends JPanel
implements MouseInputListener { implements MouseInputListener {
Point P0 = new Point(); Point P0 = new Point();
...@@ -28,15 +28,15 @@ public class ClosestPointDemo extends JPanel ...@@ -28,15 +28,15 @@ public class ClosestPointDemo extends JPanel
public static void main(String[] args) { public static void main(String[] args) {
// create the window // create the window
ClosestPointDemo canvas = new ClosestPointDemo(); ClosestPoint canvas = new ClosestPoint();
JFrame f = new JFrame("ClosestPointDemo"); // jframe is the app window JFrame f = new JFrame("ClosestPoint"); // jframe is the app window
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400); // window size f.setSize(400, 400); // window size
f.setContentPane(canvas); // add canvas to jframe f.setContentPane(canvas); // add canvas to jframe
f.setVisible(true); // show the window f.setVisible(true); // show the window
} }
ClosestPointDemo() { ClosestPoint() {
setBackground(Color.WHITE); setBackground(Color.WHITE);
// add listeners // add listeners
addMouseListener(this); addMouseListener(this);
......
/*
* CS 349 Java Code Examples
*
* CompositionOrder Demo of different concatenation orders of matrix transforms.
* Click the window to change the order.
*
*/
import javax.swing.JFrame;
import javax.swing.JComponent;
import javax.swing.JButton;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.vecmath.*;
import java.lang.Math.*;
import java.util.Random;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
// create the window and run the demo
public class CompositionOrder {
public static void main(String[] args) {
// create the window
Canvas canvas = new Canvas();
JFrame f = new JFrame("CompositionOrder"); // jframe is the app window
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500, 500); // window size
f.setContentPane(canvas); // add canvas to jframe
f.setBackground(Color.WHITE);
f.setVisible(true); // show the window
}
}
class Canvas extends JComponent {
// rotate
double theta = 30;
// translate
double tx = 100;
double ty = 0;
// scale
double sx = 2;
double sy = 1.2;
// the house shape (model position is centred at top left corner)
private Polygon shape = new Polygon(new int[] { -50, 50, 50, 0, -50},
new int[] { 75, 75, -25, -75, -25}, 5);
// a larger font for displaying the concatenation order
private Font font = new Font("SansSerif", Font.PLAIN, 30);
// the concatenation order
private int order = 0;
Canvas() {
// only mouse clicked events
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
order = (order + 1) % 6;
repaint();
}
});
System.out.println("click to change transformation composition order");
}
// custom graphics drawing
public void paintComponent(Graphics g) {
super.paintComponent(g); // JPanel paint
Graphics2D g2 = (Graphics2D)g;
// make a centred grid
int gridSize = 250;
g2.translate((this.getWidth() - gridSize) / 2, (this.getHeight() - gridSize) / 2);
drawGrid(g2, gridSize, gridSize, gridSize / 10);
// save the current transform matrix
AffineTransform M = g2.getTransform();
// draw the original shape in "model" coordinates
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(3));
g2.drawPolygon(shape.xpoints, shape.ypoints, shape.npoints);
// mark 0, 0 too
g2.setStroke(new BasicStroke(1));
g2.drawOval(-5, -5, 10, 10);
// create transformation matrices
AffineTransform R = AffineTransform.getRotateInstance(Math.toRadians(theta));
AffineTransform T = AffineTransform.getTranslateInstance(tx, ty);
AffineTransform S = AffineTransform.getScaleInstance(sx, sy);
// concatenate the matrices in 1 of 6 orders
String s = "p'=";
switch (order)
{
case 0:
s += "TRS";
g2.transform(T);
g2.transform(R);
g2.transform(S);
break;
case 1:
s += "TSR";
g2.transform(T);
g2.transform(S);
g2.transform(R);
break;
case 2:
s += "RST";
g2.transform(R);
g2.transform(S);
g2.transform(T);
break;
case 3:
s += "RTS";
g2.transform(R);
g2.transform(T);
g2.transform(S);
break;
case 4:
s += "SRT";
g2.transform(S);
g2.transform(R);
g2.transform(T);
break;
case 5:
s += "STR";
g2.transform(S);
g2.transform(T);
g2.transform(R);
break;
}
s += "p";
// the shape will get transformed into "world" coordinates
g2.setColor(Color.RED);
g2.setStroke(new BasicStroke(3));
g2.drawPolygon(shape.xpoints, shape.ypoints, shape.npoints);
// mark 0, 0 too
g2.setStroke(new BasicStroke(1));
g2.drawOval(-5, -5, 10, 10);
// reset to transform before we did the T, R, and S
// so we can draw the text
g2.setTransform(M);
// display the order text
g2.setColor(Color.BLACK);
g2.setFont(font);
g2.drawString(s, 0, gridSize + 50);
}
private void drawGrid(Graphics2D g2, int w, int h, int s) {
// Draw grid
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.GRAY.brighter());
// horizontal lines
for(int i = 0; i <= h; i += s) {
g2.drawLine(0, i, w, i);
}
// vertical lines
for(int i = 0; i <= w; i += s) {
g2.drawLine(i, 0, i, h);
}
}
}
/*
* CS 349 Java Code Examples
*
* PolygonHittest Uses built-in method to hit-test closed polygon.
*
*/
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.awt.geom.*; import java.awt.geom.*;
import javax.swing.*; import javax.swing.*;
public class PolygonHittestDemo extends JPanel{ public class PolygonHittest extends JPanel{
Point M = new Point(); // mouse point Point M = new Point(); // mouse point
Polygon poly = new Polygon(); Polygon poly = new Polygon();
public static void main(String args[]){ public static void main(String args[]){
JFrame window = new JFrame("PolygonHittestDemo"); JFrame window = new JFrame("PolygonHittest");
window.setSize(300, 300); window.setSize(300, 300);
window.setContentPane(new PolygonHittestDemo()); window.setContentPane(new PolygonHittest());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true); window.setVisible(true);
} }
public PolygonHittestDemo(){ public PolygonHittest(){
this.addMouseListener(new MouseAdapter(){ this.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){ public void mouseClicked(MouseEvent e){
poly.addPoint(e.getX(), e.getY()); poly.addPoint(e.getX(), e.getY());
......
...@@ -34,7 +34,8 @@ class Canvas extends JComponent { ...@@ -34,7 +34,8 @@ class Canvas extends JComponent {
M.y = e.getY(); M.y = e.getY();
repaint(); repaint();
} }
}); });
} }
// custom graphics drawing // custom graphics drawing
......
/*
* CS 349 Java Code Examples
*
* Transform1 Shows how to "manually" transform a shape model. NOTE: in practice,
you don't want do this. Use Graphics2D matrix tranformations instead.
*
*/
import javax.swing.JFrame;
import javax.swing.JComponent;
import javax.swing.JButton;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.vecmath.*;
import java.lang.Math.*;
import java.util.Random;
import java.awt.event.*;
// create the window and run the demo
public class Transform1 {
public static void main(String[] args) {
// create the window
Canvas canvas = new Canvas();
JFrame f = new JFrame("Transform1"); // jframe is the 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
}
}
class Canvas extends JComponent {
// the house shape model (position is centred at top left corner)
private Polygon shape = new Polygon(new int[] { -50, 50, 50, 0, -50},
new int[] { 75, 75, -25, -75, -25}, 5);
Point2d M = new Point2d();
Canvas() {
// events
this.addMouseMotionListener(new MouseAdapter(){
public void mouseMoved(MouseEvent e){
M.x = e.getX();
M.y = e.getY();
repaint();
}});
}
// custom graphics drawing
public void paintComponent(Graphics g) {
super.paintComponent(g); // JPanel paint
Graphics2D g2 = (Graphics2D)g;
// the shape will get transformed into "world" coordinates
// transform by hand
// get copy of shape
Polygon transShape = new Polygon(shape.xpoints, shape.ypoints, shape.npoints);
scale(transShape, 2, 1);
rotate(transShape, 45);
translate(transShape, M.x, M.y);
g2.setStroke(new BasicStroke(3));
g2.drawPolygon(transShape.xpoints, transShape.ypoints, transShape.npoints);
}
// non-matrix translate
void translate(Polygon s, double tx, double ty) {
for (int i = 0; i < s.npoints; i++) {
s.xpoints[i] += tx;
s.ypoints[i] += ty;
}
}
// non-matrix scale
void scale(Polygon s, double sx, double sy) {
for (int i = 0; i < s.npoints; i++) {
s.xpoints[i] *= sx;
s.ypoints[i] *= sy;
}
}
// no-matrix rotate
void rotate(Polygon s, double theta) {
double rad = Math.toRadians(theta);
for (int i = 0; i < s.npoints; i++) {
int x = s.xpoints[i];
int y = s.ypoints[i];
s.xpoints[i] = (int)((double)x * Math.cos(rad) - y * Math.sin(rad));
s.ypoints[i] = (int)((double)x * Math.sin(rad) + y * Math.cos(rad));
}
}
}
/*
* CS 349 Java Code Examples
*
* Transform2 Shows how to use Graphics2D matrix tranformations to transform a shape model.
*
*/
import javax.swing.JFrame;
import javax.swing.JComponent;
import javax.swing.JButton;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.vecmath.*;
import java.lang.Math.*;
import java.util.Random;
import java.awt.event.*;
// create the window and run the demo
public class Transform2 {
public static void main(String[] args) {
// create the window
Canvas canvas = new Canvas();
JFrame f = new JFrame("Transform2"); // jframe is the 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
}
}
class Canvas extends JComponent {
// the house shape (model position is centred at top left corner)
private Polygon shape = new Polygon(new int[] { -50, 50, 50, 0, -50},
new int[] { 75, 75, -25, -75, -25}, 5);
Point2d M = new Point2d();
Canvas() {
// events
this.addMouseMotionListener(new MouseAdapter(){
public void mouseMoved(MouseEvent e){
M.x = e.getX();
M.y = e.getY();
repaint();
}});
}
// custom graphics drawing
public void paintComponent(Graphics g) {
super.paintComponent(g); // JPanel paint
Graphics2D g2 = (Graphics2D)g;
// the shape will get transformed when rendered
g2.translate(M.x, M.y);
g2.rotate(45);
g2.scale(2, 1);
g2.setStroke(new BasicStroke(3));
g2.drawPolygon(shape.xpoints, shape.ypoints, shape.npoints);
}
}
...@@ -4,15 +4,16 @@ ...@@ -4,15 +4,16 @@
* `SimpleDraw.java` Responds to mouse events and draws primitives in 2D canvas. * `SimpleDraw.java` Responds to mouse events and draws primitives in 2D canvas.
* `ClosestPointDemo.java` Computes distance from mouse to closest point on line using algorithm discussed in class. Also uses built-in method to accomplish same thing. * `ClosestPoint.java` Computes distance from mouse to closest point on line using algorithm discussed in class. Also uses built-in method to accomplish same thing.
* `PolygonHittestDemo.java` Uses built-in method to hit-test closed polygon. * `PolygonHittest.java` Uses built-in method to hit-test closed polygon.
* `Transform1.java` Shows how to "manually" transform a shape model. NOTE: in practice, you don't want do this. Use Graphics2D matrix tranformations instead.
<!-- TransConcatDemo Demo of different concatenation orders of matrix transforms using * `Transform2.java` Shows how to use Graphics2D matrix tranformations to transform a shape model.
MyShape class. Click the window to change the order.
RotateLine Use transformations to rotate line * `CompositionOrder` Demo of different concatenation orders of matrix transforms. Click the window to change the order.