天天看點

Bezier曲線的繪制

曲線介紹

貝賽爾曲線的每一個頂點都有兩個控制點,用于控制在該頂點兩側的曲線的弧度。它是應用于二維圖形應用程式的數學曲線。曲線的定義有四個點:起始點、終止點(也稱錨點)以及兩個互相分離的中間點。滑動兩個中間點,貝塞爾曲線的形狀會發生變化。二十世紀六十年代晚期,Pierre Bézier應用數學方法為雷諾公司的汽車制造業描繪出了貝塞爾曲線。

Bezier曲線的繪制

曲線的繪制

通過以下兩個java檔案,實作給定控制頂點,繪制對應的Bezier曲線,拖動控制點時,Bezier曲線可自動更新;

BezierFrame.java檔案内容:

package test1;
import java.awt.*;

import javax.swing.*;

public class BezierFrame extends JFrame
{
	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
		{
			public void run()
			{
				JFrame frame = new JFrame();
				frame.setTitle("BezierTest");
				frame.setSize(600,600);
				
				BezierPanel bezier = new BezierPanel();
				bezier.setPreferredSize(new Dimension(580, 580));
				frame.add(bezier, BorderLayout.CENTER);
				
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setVisible(true);
			}
		});
	}
	
}
           

BezierPanel.java檔案内容:

package test1;

import javax.swing.*;

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;

class BezierPanel extends JComponent
{
	private static int SIZE = 10;
	private int current;
	private static Random generator = new Random();
	private Point2D[] points;

	public BezierPanel()
	{
		//initPoints(4);
		Point2D p1= new Point2D.Double(100,200);
		Point2D p2= new Point2D.Double(150,100);
		Point2D p3= new Point2D.Double(200,100);
		Point2D p4= new Point2D.Double(250,200);
		points = new Point2D[]{p1,p2,p3,p4};
		
		
		addMouseListener(new MouseAdapter()
		{
			public void mousePressed(MouseEvent event)
			{
				Point2D p =event.getPoint();
				for(int i = 0; i < points.length; i++)
				{
					double x = points[i].getX() - SIZE/2;
					double y = points[i].getY() - SIZE/2;
					Rectangle2D r = new Rectangle2D.Double(x, y, SIZE, SIZE);
					if(r.contains(p))
					{
						current = i;
						return;
					}
				}
			}
			
			public void mouseReleased(MouseEvent event)
			{
				current = -1;
			}
		});
		
		addMouseMotionListener(new MouseMotionAdapter()
		{
			public void mouseDragged(MouseEvent event)
			{
				if(current == -1)
					return;
				points[current] = event.getPoint();
				repaint();
			}
		});
		current = -1;
	}
	
	//給定細分節點的位置,傳回插值點
	public Point2D cubicBezier(double t, Point2D[] p) {
		Point2D[] temp = new Point2D[p.length];
		for (int k=0; k < p.length; k++) temp[k]=p[k];
		for (int i=0; i<3; i++) {
			for (int j=0; j<4-i-1 ; j++) {
				double x = (1-t)*temp[j].getX() + t*temp[j+1].getX();
				double y = (1-t)*temp[j].getY()+ t*temp[j+1].getY();
				temp[j] = new Point2D.Double(x,y);
			}
		}
		return temp[0];
	}
	
	//給定控制點,繪制三次Bezier曲線
	public void drawBezier(Graphics g, Point2D[] p) {
		for (double t = 0; t < 1; t+=0.002) {
			Point2D p1= cubicBezier(t,p);
			Point2D p2 = cubicBezier(t+0.001,p);
			g.drawLine((int)p1.getX(),(int)p1.getY(),(int)p2.getX(),(int)p2.getY());
		}
	}
	
	//覆寫JComponent的方法,用于啟動時的初始化繪制
	public void paintComponent(Graphics g)
	{
		if(points == null) return;
		//繪制四個控制點
		Graphics2D g2 = (Graphics2D) g;
		for(int i = 0; i < points.length; i++)
		{
			double x = points[i].getX() - SIZE/2;
			double y = points[i].getY() - SIZE/2;
			g2.fill(new Rectangle2D.Double(x, y, SIZE, SIZE));
		}
		//繪制曲線
		drawBezier(g,points);
	}
}
           

上述兩個java檔案來自資源:http://download.csdn.net/detail/amuguelove/4331693