Skip to content
Snippets Groups Projects
Commit a6d6d19c authored by Keiko Katsuragawa's avatar Keiko Katsuragawa
Browse files

add 2-8-Transformation

parent e46a9c3f
No related branches found
No related tags found
No related merge requests found
/*
* 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
*
* 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
*
* SceneGraph Demonstrate simple scene graph that draws a house.
*
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.*;
public class SceneGraph extends JPanel {
public static void main(String[] args) {
// create the window
JFrame f = new JFrame("SceneGraph"); // jframe is the app window
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400); // window size
f.setContentPane(new SceneGraph()); // add canvas to jframe
f.setVisible(true); // show the window
}
SceneGraph() {
setOpaque(true);
setBackground(Color.WHITE);
// make sure panel is focusable for getting key events
// (remember focus dispatch?)
setFocusable(true);
this.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_RIGHT:
rotateBy += 5;
break;
case KeyEvent.VK_LEFT:
rotateBy -= 5;
break;
case KeyEvent.VK_UP:
scaleBy += .1;
break;
case KeyEvent.VK_DOWN:
scaleBy -= .1;
break;
}
repaint();
}
});
}
// scaleBy and rotation
double scaleBy = 2;
double rotateBy = 0;
// custom graphics drawing
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// draw the house in centre of screen
g2.translate(getWidth() / 2, getHeight()/ 2);
g2.rotate(Math.toRadians(rotateBy));
g2.scale(scaleBy, scaleBy);
g2.setStroke(new BasicStroke(3));
g2.drawPolygon(houseShape.xpoints, houseShape.ypoints, houseShape.npoints);
// save transform for later
AffineTransform save = g2.getTransform();
// remember: these are all in "house coordinates"
g2.translate(-25, 0); // window centred 25 px
g2.scale(0.4, 0.4); // window is 40% house width
drawWindow(g2);
// translate to right 50 px
g2.translate(50 / 0.4, 0);
drawWindow(g2);
// draw third window twice to demo different coordinate frames
// set transform to saved matrix to return to "House" coordinates
// since this window is drawn in house coordinates, it will be
// transformed with the house
g2.setTransform(save);
drawWindow(g2, 0, -50, 45, 0.25);
// set transform to identity to reset
// this means third window is drawn in World Coordinates
// and won't be transformed with the house
g2.setTransform(new AffineTransform());
// using function which has a model-to-world transform built in
drawWindow(g2, getWidth()/2, 89, 45, 0.5);
}
// 100 x 100 house shape using Java Polygon structure
// (model position is centred at top left corner)
private Polygon houseShape = new Polygon(new int[] { -50, 50, 50, 0, -50},
new int[] { 75, 75, -25, -75, -25}, 5);
// draws 100 x 100 window shape centred at 0,0
void drawWindow(Graphics2D g2) {
g2.setColor(Color.BLACK);
g2.fillRect(-50, -50, 100, 100);
g2.setColor(Color.WHITE);
g2.fillRect(-40, -40, 35, 35);
g2.fillRect(5, -40, 35, 35);
g2.fillRect(-40, 5, 35, 35);
g2.fillRect(5, 5, 35, 35);
}
// draws 100 x 100 window shape centred at 0,0
void drawWindow(Graphics2D g2, double x, double y, double theta, double s) {
// save the current g2 transform matrix
AffineTransform save = g2.getTransform();
// do the model to world transformation
g2.translate(x, y); // T
g2.rotate(Math.toRadians(theta)); // R
g2.scale(s, s); // S
// draws 100 x 100 window centred at 0,0
drawWindow(g2);
// reset the transform to what it was before we drew the shape
g2.setTransform(save);
}
}
/*
* 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);
}
}
# super simple makefile
# call it using 'make NAME=name_of_code_file_without_extension'
# (assumes a .java extension)
NAME = Transform2
# you may need to pass OS=win to run on windows
OS =
# HACK: vecmath is included regardless if needed
all:
@echo "Compiling..."
javac -cp vecmath.jar $(NAME).java
run: all
# windows needs a semicolon
ifeq ($(OS),win)
@echo "Running on windows ..."
java -cp "vecmath.jar;." $(NAME)
# everyone else likes a colon
else
@echo "Running ..."
java -cp "vecmath.jar:." $(NAME)
endif
clean:
rm -rf *.class
/*
* Shape: See ShapeDemo for an example how to use this class.
*
*/
import java.util.ArrayList;
import java.awt.*;
import java.awt.geom.*;
import javax.vecmath.*;
// simple shape model class
class Shape {
// shape points
ArrayList<Point2d> points;
public void clearPoints() {
points = new ArrayList<Point2d>();
pointsChanged = true;
}
// add a point to end of shape
public void addPoint(Point2d p) {
if (points == null) clearPoints();
points.add(p);
pointsChanged = true;
}
// add a point to end of shape
public void addPoint(double x, double y) {
addPoint(new Point2d(x, y));
}
public int npoints() {
return points.size();
}
// shape is polyline or polygon
Boolean isClosed = false;
public Boolean getIsClosed() {
return isClosed;
}
public void setIsClosed(Boolean isClosed) {
this.isClosed = isClosed;
}
// if polygon is filled or not
Boolean isFilled = false;
public Boolean getIsFilled() {
return isFilled;
}
public void setIsFilled(Boolean isFilled) {
this.isFilled = isFilled;
}
// drawing attributes
Color colour = Color.BLACK;
float strokeThickness = 3.0f;
public Color getColour() {
return colour;
}
public void setColour(Color colour) {
this.colour = colour;
}
public float getStrokeThickness() {
return strokeThickness;
}
public void setStrokeThickness(float strokeThickness) {
this.strokeThickness = strokeThickness;
}
// shape's transform
// quick hack, get and set would be better
float scale = 1.0f;
// some optimization to cache points for drawing
Boolean pointsChanged = false; // dirty bit
int[] xpoints, ypoints;
int npoints = 0;
void cachePointsArray() {
xpoints = new int[points.size()];
ypoints = new int[points.size()];
for (int i=0; i < points.size(); i++) {
xpoints[i] = (int)points.get(i).x;
ypoints[i] = (int)points.get(i).y;
}
npoints = points.size();
pointsChanged = false;
}
// let the shape draw itself
// (note this isn't good separation of shape View from shape Model)
public void draw(Graphics2D g2) {
// don't draw if points are empty (not shape)
if (points == null) return;
// see if we need to update the cache
if (pointsChanged) cachePointsArray();
// save the current g2 transform matrix
AffineTransform M = g2.getTransform();
// multiply in this shape's transform
// (uniform scale)
g2.scale(scale, scale);
// call drawing functions
g2.setColor(colour);
if (isFilled) {
g2.fillPolygon(xpoints, ypoints, npoints);
} else {
// can adjust stroke size using scale
g2.setStroke(new BasicStroke(strokeThickness / scale));
if (isClosed)
g2.drawPolygon(xpoints, ypoints, npoints);
else
g2.drawPolyline(xpoints, ypoints, npoints);
}
// reset the transform to what it was before we drew the shape
g2.setTransform(M);
}
// let shape handle its own hit testing
// (x,y) is the point to test against
// (x,y) needs to be in same coordinate frame as shape, you could add
// a panel-to-shape transform as an extra parameter to this function
// (note this isn't good separation of shape Controller from shape Model)
public boolean hittest(double x, double y)
{
if (points != null) {
// TODO Implement
}
return false;
}
}
/*
* CS 349 Java Code Examples
*
* ShapeDemo Demo of Shape class: draw shapes using mouse.
*
*/
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.vecmath.*;
// create the window and run the demo
public class ShapeDemo extends JPanel {
Shape shape;
ShapeDemo() {
this.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e) {
shape = new Shape();
// change shape type
// shape.setIsClosed(true);
// shape.setIsFilled(true);
shape.setColour(Color.BLUE);
// try setting scale to something other than 1
shape.scale = 1.0f;
repaint();
}
});
this.addMouseMotionListener(new MouseAdapter(){
public void mouseDragged(MouseEvent e) {
shape.addPoint(e.getX(), e.getY());
repaint();
}
});
}
public static void main(String[] args) {
// create the window
ShapeDemo canvas = new ShapeDemo();
JFrame f = new JFrame("ShapeDemo"); // jframe is the app window
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 300); // window size
f.setContentPane(canvas); // add canvas to jframe
f.setVisible(true); // show the window
}
// custom graphics drawing
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g; // cast to get 2D drawing methods
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // antialiasing look nicer
RenderingHints.VALUE_ANTIALIAS_ON);
if (shape != null)
shape.draw(g2);
}
}
# super simple makefile
# call it using 'make NAME=name_of_code_file_without_extension'
# (assumes a .java extension)
NAME="ShapeDemo"
# you may need to pass OS=win to run on windows
OS =
# HACK: vecmath is included regardless if needed
all:
@echo "Compiling..."
javac -cp vecmath.jar *.java
run: all
# windows needs a semicolon
ifeq ($(OS),win)
@echo "Running on windows ..."
java -cp "vecmath.jar;." $(NAME)
# everyone else likes a colon
else
@echo "Running ..."
java -cp "vecmath.jar:." $(NAME)
endif
clean:
rm -rf *.class
File added
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment