2009年8月30日 星期日

Java Bézier Cubic Curve

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class CubicBezierCurve extends JFrame {

    private Point[] controlPoint = new Point[4];
    private Point[] curve = new Point[1024];
    private PaintPael paintPanel = null;
    private JLabel location = new JLabel("x: 0  y: 0");
    private static CubicBezierCurve cbc = null;
    private int controlPointCount = 0;
    public CubicBezierCurve() {
        for(int i = 0; i < controlPoint.length; ++i)
            controlPoint[i] = new Point(0, 0);
        InitComponent();
        setBackground(Color.WHITE);
        setSize(640, 480);
        setVisible(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }
    private void InitComponent() {
        setLayout(new BorderLayout());
        
        paintPanel = new PaintPael();
        
        add(paintPanel, BorderLayout.CENTER);
        
        Panel eastPanel = new Panel();
        eastPanel.setBackground(Color.BLACK);
        eastPanel.setLayout(new FlowLayout());
        Button restart = new Button("Restart");
        restart.addActionListener(new ButtonListener());
        
        
        eastPanel.add(restart);
        add(eastPanel, BorderLayout.EAST);
        location.setForeground(Color.RED);
        location.setBackground(Color.BLACK);
        add(location, BorderLayout.NORTH);
    }
    
    public Point BezierFunction(double t) {
      
      double tsqure = t * t;
      double tcubic = tsqure * t * t;

      double t1      = (1.0 - t);
      double t1square = t1 * t1; 
      double t1cubic = t1square * t1;
      
        double x = controlPoint[0].x * tcubic +
        3 * controlPoint[1].x * tsqure * t1 +
        3 * controlPoint[2].x * t * t1square+
        controlPoint[3].x * t1cubic;
        
        double y = controlPoint[0].y * t * t * t +
        3 * controlPoint[1].y * tsqure * t1 +
        3 * controlPoint[2].y * t * t1square+
        controlPoint[3].y * t1cubic;
            
        return new Point((int)x, (int)y);
    }
    public void ComputeCurve() {
        double t = 1.0 / 1024.0;
        for(int i = 0; i < curve.length; ++i) {
            curve[i] = BezierFunction(t * i);
        }
    }

    public static void main(String[] argv) {
        cbc = new CubicBezierCurve();
    }
   
    class PaintPael extends JPanel {

        public PaintPael() {
            PanelListener pl = new PanelListener();
            addMouseListener(pl);
            addMouseMotionListener(pl);
            setBackground(Color.BLACK);
        }
        public void paint(Graphics g) {
          super.paint(g);
            g.setClip(0, 0, getWidth(), getHeight());
            PaintControlPoint(g);
            PaintControlLine(g);
            PaintCurve(g);
        }
        private void PaintControlLine(Graphics g) {
            g.setColor(Color.green);
            if(controlPoint[0].x != 0 && controlPoint[0].y != 0 && controlPoint[1].x != 0 && controlPoint[1].y != 0)
                g.drawLine(controlPoint[0].x, controlPoint[0].y, controlPoint[1].x, controlPoint[1].y);
            if(controlPoint[1].x != 0 && controlPoint[1].y != 0 && controlPoint[2].x != 0 && controlPoint[2].y != 0)
                g.drawLine(controlPoint[1].x, controlPoint[1].y, controlPoint[2].x, controlPoint[2].y);
            if(controlPoint[2].x != 0 && controlPoint[2].y != 0 && controlPoint[3].x != 0 && controlPoint[3].y != 0)
                g.drawLine(controlPoint[2].x, controlPoint[2].y, controlPoint[3].x, controlPoint[3].y);
        }
        private void PaintControlPoint(Graphics g) {
            g.setColor(Color.BLUE);
            for(int i = 0; i < controlPoint.length; ++i) {
                if(controlPoint[i] != null && controlPoint[i].x != 0 && controlPoint[i].y != 0) {
                    g.fillOval(controlPoint[i].x - 2, controlPoint[i].y - 2, 4, 4);
                }
            }
        }
        private void PaintCurve(Graphics g) {
            if(curve[0] != null) {
                g.setColor(Color.RED);
                for(int i = 0; i < curve.length; ++i) {
                    g.fillOval(curve[i].x, curve[i].y, 2, 2);
                }
            }
        }
    }
    
    class ButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            for(int i = 0; i < controlPoint.length; ++i) {
                if(controlPoint[i] != null) {
                    controlPoint[i].setLocation(0, 0);
                }
            }
            curve = null;
            curve = new Point[1024];
            //paintPanel.paintImmediately(0, 0, paintPanel.getWidth(), paintPanel.getHeight());
            controlPointCount = 0;
            cbc.repaint();
        }
    }
    
    class PanelListener extends MouseAdapter implements MouseMotionListener {
        @Override
        public void mouseClicked(MouseEvent arg0) {
            for(int i = 0; i < controlPoint.length; ++i) {
                if(controlPoint[i] != null && controlPoint[i].x == 0 && controlPoint[i].y == 0) {
                    controlPoint[i].x = arg0.getX();
                    controlPoint[i].y = arg0.getY();
                    break;
                }
            }
            if(controlPoint[3].x != 0 && controlPoint[3].y != 0 && curve[0] == null) {
                cbc.ComputeCurve();
            }
            controlPointCount ++;
            cbc.repaint();

        }
        @Override
        public void mouseDragged(MouseEvent arg0) {
        }

        @Override
        public void mouseMoved(MouseEvent arg0) {
            location.setText("x: " + arg0.getX() + "  y: " + arg0.getX());
        }
    }
}

沒有留言: