Java 2D – Biến đổi hình

4.2/5 - (6 votes)

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.

Capture

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ả:

Capture

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.

Capture

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ả:

Capture

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.

Capture

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.

Capture
0 0 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments