Trong phần này chúng ta sẽ tìm hiểu về các phép biến đổi hình.
Một phép biến đối hình có thể là kết quả của nhiều phép biến đổi tuyến tính bao gồm phép xoay hình, co dãn hình, biến dạng hình và phép tịnh tiến. Trong đó xoay hình là công việc xoay một đối tượng xung quanh một điểm cố định. Phép co dãn thực hiện phóng to hoặc thu nhỏ đối tượng. Phép tịnh tiến di chuyển một đối tượng theo một hướng nào đó. Phép biến dạng là thay đổi hình dạng của đối tượng theo một trục nào đó.
Trong Java chúng ta sử dụng lớp AffineTransform
để thực hiện các phép biến đổi nói trên.
Phép tịnh tiến – Translation
import java.awt.Color; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JFrame; import javax.swing.JPanel; class Surface extends JPanel { private void doDrawing(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setPaint(new Color(150, 150, 150)); g2d.fillRect(20, 20, 80, 50); g2d.translate(150, 50); g2d.fillRect(20, 20, 80, 50); g2d.dispose(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } } public class TranslationEx extends JFrame { public TranslationEx() { initUI(); } private void initUI() { add(new Surface()); setTitle("Translation"); setSize(300, 200); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { TranslationEx ex = new TranslationEx(); ex.setVisible(true); } }); } }
Trong ví dụ trên, chúng ta vẽ một hình chữ nhật, sau đó thực hiện phép tịnh tiến rồi vẽ thêm một hình chữ nhật nữa.
g2d.translate(150, 50);
Phương thức translate()
di chuyển tâm của đối tượng Graphics2D
đến tọa độ mới.
Lưu ý là phương thức translate()
di chuyển tâm vẽ của đối tượng Graphics2D
chứ không di chuyển hình chữ nhật nào cả:
Phép xoay hình – Rotation
import java.awt.Color; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JFrame; import javax.swing.JPanel; class Surface extends JPanel { private void doDrawing(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setPaint(new Color(150, 150, 150)); g2d.fillRect(20, 20, 80, 50); g2d.translate(180, -50); g2d.rotate(Math.toRadians(45)); g2d.fillRect(80, 80, 80, 50); g2d.dispose(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } } public class RotationEx extends JFrame { public RotationEx() { initUI(); } private void initUI() { setTitle("Rotation"); add(new Surface()); setSize(300, 200); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { RotationEx ex = new RotationEx(); ex.setVisible(true); } }); } }
Trong ví dụ trên, chúng ta vẽ một hình chữ nhật, sau đó thực hiện phép xoay hình rồi vẽ lại hình chữ nhật đó.
g2d.rotate(Math.toRadians(45));
Để xoay hình thì chúng ta dùng phương thức rotate().
Đơn vị góc của phương thức này là radian nên nếu bạn dùng đơn vị độ thì nên chuyển sang radian bằng phương thức Math.toRadians()
trước.
Cũng giống như với phép tịnh tiến, phép xoay chỉ xoay cửa sổ từ tâm vẽ chứ không xoay một hình nào cả:
Hình minh họa vẽ bằng paint nên hơi xấu 🙂
Phép co dãn hình – Scaling
import java.awt.Color; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import javax.swing.JFrame; import javax.swing.JPanel; class Surface extends JPanel { private void doDrawing(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setColor(new Color(150, 150, 150)); g2d.fillRect(20, 20, 80, 50); AffineTransform tx1 = new AffineTransform(); tx1.translate(110, 22); tx1.scale(0.5, 0.5); g2d.setTransform(tx1); g2d.fillRect(0, 0, 80, 50); AffineTransform tx2 = new AffineTransform(); tx2.translate(170, 20); tx2.scale(1.5, 1.5); g2d.setTransform(tx2); g2d.fillRect(0, 0, 80, 50); g2d.dispose(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } } public class ScalingEx extends JFrame { public ScalingEx() { initUI(); } private void initUI() { add(new Surface()); setTitle("Scaling"); setSize(330, 160); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { ScalingEx ex = new ScalingEx(); ex.setVisible(true); } }); } }
Trong ví dụ trên chúng ta vẽ một hình chữ nhật rồi phóng to và thu nhỏ hình chữ nhật đó.
AffineTransform tx2 = new AffineTransform(); tx2.translate(170, 20); tx2.scale(1.5, 1.5);
Ở đây chúng ta thực hiện các phép co dãn sử dụng phương thức scale()
của lớp AffineTransform
.
Phép biến dạng – Shearing
import java.awt.Color; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import javax.swing.JFrame; import javax.swing.JPanel; class Surface extends JPanel { private void doDrawing(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); AffineTransform tx1 = new AffineTransform(); tx1.translate(50, 90); g2d.setTransform(tx1); g2d.setPaint(Color.green); g2d.drawRect(0, 0, 160, 50); AffineTransform tx2 = new AffineTransform(); tx2.translate(50, 90); tx2.shear(0, 1); g2d.setTransform(tx2); g2d.setPaint(Color.blue); g2d.draw(new Rectangle(0, 0, 80, 50)); AffineTransform tx3 = new AffineTransform(); tx3.translate(130, 10); tx3.shear(0, 1); g2d.setTransform(tx3); g2d.setPaint(Color.red); g2d.drawRect(0, 0, 80, 50); g2d.dispose(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } } public class ShearingEx extends JFrame { public ShearingEx() { initUI(); } private void initUI() { add(new Surface()); setTitle("Shearing"); setSize(330, 270); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { ShearingEx ex = new ShearingEx(); ex.setVisible(true); } }); } }
Trong ví dụ trên, chúng ta vẽ 3 hình chữ nhật và áp dụng phép biến dạng cho 2 hình.
tx2.shear(0, 1);
Để thực hiện phép biến dạng thì chúng ta dùng phương thức shear(),
tham số đầu tiên làm biến dạng theo trục x, tham số thứ 2 biến dạng theo trục y.