Assignment ;因爲java的座標系和習慣的座標系不一樣(Y軸正方向向下),所以要先建立自己的座標。
爲了達到這個目的,實現方法的思路大概是這樣:自己的座標系->視圖->java座標系(這三傢伙兩兩之間的轉換都是根據比例建立變換關係的).
CODE:
MyCanvas.java(我的畫布類)
My View:註釋都很詳細,大家應該能看明白.
哦,要注意的一點是:在視圖->java座標系中,Y軸的變換有點特別.
一般屏幕座標系是直角左手系,y軸方向向下爲正,原點在屏幕的左上角.解釋窗口內圖形上任一點(x,y)變換到視口內成爲(sx,xy),而(x,y)是相對用戶座標系(直角右手系)的。(sx,sy)是相對屏幕座標系(直角左手系)的,因此y軸方向相反。爲使窗口內圖形變換到視口上圖形其形狀一致,需將視口上圖形y軸方向變換成窗口內圖形y軸方向。這隻要將求得的視口內各點的sy整型座標均用sy2去減,即sy2-sy(整型)代替sy(整型)即可,經這樣的座標軸方向變換後得到的視口內圖形與窗口內圖形一致。
程序中使用的是:1-y.
//MyCanvas.java
import java.awt.*;
import java.awt.image.*;
public class MyCanvas extends Component{
//自定義座標系範圍
protected double userMinX = -1;//X軸的最小值
protected double userMaxX = 1;//x軸的最大值
protected double userMinY = -1;//Y軸的最小值
protected double userMaxY = -1;//Y軸的最小值
//視圖範圍The range of view
protected double[] viewMinX;//X軸的最小值
protected double[] viewMaxX;//x軸的最大值
protected double[] viewMinY;//Y軸的最小值
protected double[] viewMaxY;//Y軸的最小值
final static int DefaultViewportMax = 256;//缺省試圖數
protected int viewportMax = DefaultViewportMax;//視圖數
protected int viewportNum = 0;//當前視圖數
protected int currentViewport = 0;//當前試圖的索引
//窗口大小The size of window
final static int DefaultWindowSize = 256;//缺省的窗口大小
protected int windowWidth = DefaultWindowSize;//窗口寬度
protected int windowHeight = DefaultWindowSize;//窗口高度
//Graphic and its Component
protected Graphics myGraphics;//Graphic類數據
protected Component myComponent;//Component類數據
protected Color currentFrontColor = Color.white;//當前顏色
protected Color currentBackColor = Color.black;//當前背景色
//構造器
public MyCanvas(Component a){
myComponent = a;//設定MyCanvas類用的Component
myGraphics = a.getGraphics();//設定MyCanvas用的Graphics
windowWidth = a.getSize().width;//窗口寬度
windowHeight = a.getSize().height;//窗口高度
createViewport(DefaultViewportMax);//創建視圖
}
private void createViewport(int max){
currentViewport = 0;//視圖索引的初始值設定
viewportMax = max;//設定視圖數的最大值
viewMinX = new double[viewportMax];//視圖X軸的最小值數組
viewMaxX = new double[viewportMax];//視圖X軸的最大值數組
viewMinY = new double[viewportMax];//視圖Y軸的最小值數組
viewMaxY = new double[viewportMax];//視圖Y軸的最大值數組
viewMinX[0] = viewMinY[0] = 0.0;//視圖的最小值爲0
viewMaxX[0] = viewMaxY[0] = 1.0;//視圖的最大值爲1
viewportNum = 1;//視圖的當前索引爲1
}
//自定義座標系的範圍的設定
public void setMyWindow(double x1,double x2,double y1,double y2){
userMinX = x1;//窗口的X軸的最小值設定
userMaxX = x2;//窗口的X軸的最大值設定
userMinY = y1;//窗口的Y軸的最小值設定
userMaxY = y2;//窗口的Y軸的最大值設定
}
//視圖的設定
public void setViewport(double x1,double x2,double y1,double y2){
viewMinX[viewportNum] = x1;//視圖的X軸的最小值設定
viewMaxX[viewportNum] = x2;//視圖的X軸的最大值設定
viewMinY[viewportNum] = y1;//視圖的Y軸的最小值設定
viewMaxY[viewportNum] = y2;//視圖的Y軸的最大值設定
currentViewport = viewportNum;//當前視圖索引的設定
viewportNum++;//視圖數加1
}
/****視圖的復位****/
public void resetViewport(){
currentViewport = 0;//視圖索引返回到0
viewMinX[0] = viewMinY[0] = 0.0;//視圖的最小值爲0
viewMaxX[0] = viewMaxY[0] = 1.0;//視圖的最大值爲1
viewportNum = 1;//視圖數爲1
}
/****將視圖座標轉換到java AWT座標方法***/
public int getIntX(double x){
return (int)(windowWidth * x);
}//窗口寬度加倍
public int getIntY(double y){
return (int)(windowHeight * (1 - y));
}//窗口高度加倍
/*******將自定義座標轉換到視圖座標**********/
public double viewX(double x){
double s = (x - userMinX)/(userMaxX - userMinX);
double t = viewMinX[currentViewport] + s *
(viewMaxX[currentViewport] - viewMinX[currentViewport]);
return t;
}
public double viewY(double y){
double s = (y - userMinY)/(userMaxY - userMinY);
double t = viewMinY[currentViewport] + s *
(viewMaxY[currentViewport] - viewMinY[currentViewport]);
return t;
}
/*******將自定義座標轉換到java AWT座標********/
public int getX(double x){
double xx = viewX(x);//x轉換到視圖座標
int ix = getIntX(xx);//視圖轉換到java座標
return ix;
}
public int getY(double y){
double yy = viewY(y);//y轉換到視圖座標
int iy = getIntY(yy);//視圖轉換到java座標
return iy;
}
/******得到Dimension(維數)的方法**********/
public int getDimensionX(double w){
double x = viewMaxX[currentViewport] - viewMinX[currentViewport];
x *= windowWidth * w / (userMaxX - userMinX);
return((int)Math.abs(x));
}
public int getDimensionY(double h){
double y = viewMaxY[currentViewport] - viewMinY[currentViewport];
y *= windowHeight * h / (userMaxY - userMinY);
return((int)Math.abs(y));
}
/*****顏色設定方法******/
public Color getColor(){return currentFrontColor;}//當前的顏色檢索
public void setColor(Color c){
myGraphics.setColor(c);
currentFrontColor = c;//當前顏色設定
}
public Color getForeground(){return currentFrontColor;}//前面顏色檢索
public void setForeground(Color c){//前面顏色設定
myComponent.setForeground(c);
currentFrontColor = c;
}
public Color getBackground(){return currentBackColor;}//背景顏色檢索
public void setBackground(Color c){
myComponent.setBackground(c);
currentBackColor = c;//背景顏色設定
}
/*******************
***直線描畫方法
********************/
public void drawLine(double x1,double y1,double x2,double y2){
//轉換到java座標系值
int ix1 = getX(x1);
int iy1 = getY(y1);
int ix2 = getX(x2);
int iy2 = getY(y2);
myGraphics.drawLine(ix1,iy1,ix2,iy2);
}
/*******************
***文字列的描畫
********************/
public void drawString(String str,double x,double y){
int ix = getX(x);//自定義座標軸到java座標軸
int iy = getY(y);//自定義座標軸到java座標軸
myGraphics.drawString(str,ix,iy);
}
/*******************
***多邊形的填充
********************/
public void fillPolygon(double[] x,double[] y,int numPoints){
int[] ix = new int[numPoints];
int[] iy = new int[numPoints];
for(int i=0;i<numPoints;i++){
ix[i] = getX(x[i]);//自定義座標軸到java座標軸
iy[i] = getY(y[i]);//自定義座標軸到java座標軸
}
myGraphics.fillPolygon(ix,iy,numPoints);
}
}
import java.awt.*;
import java.awt.image.*;
public class MyCanvas extends Component{
//自定義座標系範圍
protected double userMinX = -1;//X軸的最小值
protected double userMaxX = 1;//x軸的最大值
protected double userMinY = -1;//Y軸的最小值
protected double userMaxY = -1;//Y軸的最小值
//視圖範圍The range of view
protected double[] viewMinX;//X軸的最小值
protected double[] viewMaxX;//x軸的最大值
protected double[] viewMinY;//Y軸的最小值
protected double[] viewMaxY;//Y軸的最小值
final static int DefaultViewportMax = 256;//缺省試圖數
protected int viewportMax = DefaultViewportMax;//視圖數
protected int viewportNum = 0;//當前視圖數
protected int currentViewport = 0;//當前試圖的索引
//窗口大小The size of window
final static int DefaultWindowSize = 256;//缺省的窗口大小
protected int windowWidth = DefaultWindowSize;//窗口寬度
protected int windowHeight = DefaultWindowSize;//窗口高度
//Graphic and its Component
protected Graphics myGraphics;//Graphic類數據
protected Component myComponent;//Component類數據
protected Color currentFrontColor = Color.white;//當前顏色
protected Color currentBackColor = Color.black;//當前背景色
//構造器
public MyCanvas(Component a){
myComponent = a;//設定MyCanvas類用的Component
myGraphics = a.getGraphics();//設定MyCanvas用的Graphics
windowWidth = a.getSize().width;//窗口寬度
windowHeight = a.getSize().height;//窗口高度
createViewport(DefaultViewportMax);//創建視圖
}
private void createViewport(int max){
currentViewport = 0;//視圖索引的初始值設定
viewportMax = max;//設定視圖數的最大值
viewMinX = new double[viewportMax];//視圖X軸的最小值數組
viewMaxX = new double[viewportMax];//視圖X軸的最大值數組
viewMinY = new double[viewportMax];//視圖Y軸的最小值數組
viewMaxY = new double[viewportMax];//視圖Y軸的最大值數組
viewMinX[0] = viewMinY[0] = 0.0;//視圖的最小值爲0
viewMaxX[0] = viewMaxY[0] = 1.0;//視圖的最大值爲1
viewportNum = 1;//視圖的當前索引爲1
}
//自定義座標系的範圍的設定
public void setMyWindow(double x1,double x2,double y1,double y2){
userMinX = x1;//窗口的X軸的最小值設定
userMaxX = x2;//窗口的X軸的最大值設定
userMinY = y1;//窗口的Y軸的最小值設定
userMaxY = y2;//窗口的Y軸的最大值設定
}
//視圖的設定
public void setViewport(double x1,double x2,double y1,double y2){
viewMinX[viewportNum] = x1;//視圖的X軸的最小值設定
viewMaxX[viewportNum] = x2;//視圖的X軸的最大值設定
viewMinY[viewportNum] = y1;//視圖的Y軸的最小值設定
viewMaxY[viewportNum] = y2;//視圖的Y軸的最大值設定
currentViewport = viewportNum;//當前視圖索引的設定
viewportNum++;//視圖數加1
}
/****視圖的復位****/
public void resetViewport(){
currentViewport = 0;//視圖索引返回到0
viewMinX[0] = viewMinY[0] = 0.0;//視圖的最小值爲0
viewMaxX[0] = viewMaxY[0] = 1.0;//視圖的最大值爲1
viewportNum = 1;//視圖數爲1
}
/****將視圖座標轉換到java AWT座標方法***/
public int getIntX(double x){
return (int)(windowWidth * x);
}//窗口寬度加倍
public int getIntY(double y){
return (int)(windowHeight * (1 - y));
}//窗口高度加倍
/*******將自定義座標轉換到視圖座標**********/
public double viewX(double x){
double s = (x - userMinX)/(userMaxX - userMinX);
double t = viewMinX[currentViewport] + s *
(viewMaxX[currentViewport] - viewMinX[currentViewport]);
return t;
}
public double viewY(double y){
double s = (y - userMinY)/(userMaxY - userMinY);
double t = viewMinY[currentViewport] + s *
(viewMaxY[currentViewport] - viewMinY[currentViewport]);
return t;
}
/*******將自定義座標轉換到java AWT座標********/
public int getX(double x){
double xx = viewX(x);//x轉換到視圖座標
int ix = getIntX(xx);//視圖轉換到java座標
return ix;
}
public int getY(double y){
double yy = viewY(y);//y轉換到視圖座標
int iy = getIntY(yy);//視圖轉換到java座標
return iy;
}
/******得到Dimension(維數)的方法**********/
public int getDimensionX(double w){
double x = viewMaxX[currentViewport] - viewMinX[currentViewport];
x *= windowWidth * w / (userMaxX - userMinX);
return((int)Math.abs(x));
}
public int getDimensionY(double h){
double y = viewMaxY[currentViewport] - viewMinY[currentViewport];
y *= windowHeight * h / (userMaxY - userMinY);
return((int)Math.abs(y));
}
/*****顏色設定方法******/
public Color getColor(){return currentFrontColor;}//當前的顏色檢索
public void setColor(Color c){
myGraphics.setColor(c);
currentFrontColor = c;//當前顏色設定
}
public Color getForeground(){return currentFrontColor;}//前面顏色檢索
public void setForeground(Color c){//前面顏色設定
myComponent.setForeground(c);
currentFrontColor = c;
}
public Color getBackground(){return currentBackColor;}//背景顏色檢索
public void setBackground(Color c){
myComponent.setBackground(c);
currentBackColor = c;//背景顏色設定
}
/*******************
***直線描畫方法
********************/
public void drawLine(double x1,double y1,double x2,double y2){
//轉換到java座標系值
int ix1 = getX(x1);
int iy1 = getY(y1);
int ix2 = getX(x2);
int iy2 = getY(y2);
myGraphics.drawLine(ix1,iy1,ix2,iy2);
}
/*******************
***文字列的描畫
********************/
public void drawString(String str,double x,double y){
int ix = getX(x);//自定義座標軸到java座標軸
int iy = getY(y);//自定義座標軸到java座標軸
myGraphics.drawString(str,ix,iy);
}
/*******************
***多邊形的填充
********************/
public void fillPolygon(double[] x,double[] y,int numPoints){
int[] ix = new int[numPoints];
int[] iy = new int[numPoints];
for(int i=0;i<numPoints;i++){
ix[i] = getX(x[i]);//自定義座標軸到java座標軸
iy[i] = getY(y[i]);//自定義座標軸到java座標軸
}
myGraphics.fillPolygon(ix,iy,numPoints);
}
}
MyCoordinate.java(測試類)
//<applet code=MyCoordinate width =300 height =300>
//</applet>
//MyCoordinate.java
import java.awt.*;
import java.applet.Applet;
public class MyCoordinate extends Applet{
MyCanvas m;//MyCanvas用數據
final static int idealSizeX = 600;
final static int idealSizeY = 350;
public void init(){m = new MyCanvas(this);}//生成myCanvas 對象
public void paint(Graphics g){
m.setBackground(new Color(200,200,200));
m.setColor(Color.black);
m.setViewport(0.1,0.9,0.1,0.9);//設定視圖範圍座標[0,1]*[0,1]
m.setMyWindow(-1,1,-1,1);//設定自定義座標系範圍
//畫X軸
double[] x1 = {0.95,1.0,0.95};//箭頭的座標值
double[] y1 = {-0.05,0.0,0.05};//箭頭的座標值
m.drawLine(-1,0,1,0);//畫X軸
m.fillPolygon(x1,y1,3);//填充箭頭
m.drawString("x軸",0.8,-0.2);//標註"X軸"
//畫y軸
double[] x2 = {-0.05,0.05,0.0};//箭頭的座標值
double[] y2 = {0.95,0.95,1.0};//箭頭的座標值
m.drawLine(0,-1,0,1);//畫X軸
m.fillPolygon(x2,y2,3);//填充箭頭
m.drawString("y軸",-0.2,0.9);//標註"X軸"
m.resetViewport();
}
}
//</applet>
//MyCoordinate.java
import java.awt.*;
import java.applet.Applet;
public class MyCoordinate extends Applet{
MyCanvas m;//MyCanvas用數據
final static int idealSizeX = 600;
final static int idealSizeY = 350;
public void init(){m = new MyCanvas(this);}//生成myCanvas 對象
public void paint(Graphics g){
m.setBackground(new Color(200,200,200));
m.setColor(Color.black);
m.setViewport(0.1,0.9,0.1,0.9);//設定視圖範圍座標[0,1]*[0,1]
m.setMyWindow(-1,1,-1,1);//設定自定義座標系範圍
//畫X軸
double[] x1 = {0.95,1.0,0.95};//箭頭的座標值
double[] y1 = {-0.05,0.0,0.05};//箭頭的座標值
m.drawLine(-1,0,1,0);//畫X軸
m.fillPolygon(x1,y1,3);//填充箭頭
m.drawString("x軸",0.8,-0.2);//標註"X軸"
//畫y軸
double[] x2 = {-0.05,0.05,0.0};//箭頭的座標值
double[] y2 = {0.95,0.95,1.0};//箭頭的座標值
m.drawLine(0,-1,0,1);//畫X軸
m.fillPolygon(x2,y2,3);//填充箭頭
m.drawString("y軸",-0.2,0.9);//標註"X軸"
m.resetViewport();
}
}
RUN:
My View:能看到的在MyCoordinate.java的頂端有這麼一段"//<applet code=MyCoordinate width =300 height =300> //</applet>" 目的是在命令行中直接運行Applet.
而在編譯時也有點問題,用下圖的命令可得到比較好的解決。
運行命令:
運行結果:
閃……