基於java圖形學實踐記錄(The First Day)

 

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);
    }

}

 

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();
   }

}

RUN:

 My View:能看到的在MyCoordinate.java的頂端有這麼一段"//<applet   code=MyCoordinate   width   =300   height   =300>    //</applet>" 目的是在命令行中直接運行Applet.

  而在編譯時也有點問題,用下圖的命令可得到比較好的解決。

運行命令:

 

運行結果:

閃……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章