资源描述
实验1实验报告格式
《计算机图形学》实验1实验报告
实验题目:用户坐标、视图坐标、Java awt坐标概念的建立和应用
实验内容:掌握用户坐标、视图坐标、Java awt坐标概念,掌握三类坐标的转换算法。编写自己的算法函数,并形成Java语言程序包。编写程序调用验证之。
参考程序:有两个示范程序MyCanvas.java和MyLineDrawApplet.java
基本概念:
用户坐标:是独立于设备的逻辑坐标,可以是用户用来定义设计对象的各种坐标。
视图坐标:是设备相关的坐标,随目标渲染设备不同而不同。
Java awt坐标:使用java.awt时的坐标。
填充:以已知的某一条线为基准,向周围区域扩展像素,然后对这些像素所在的位置进行着色。
将用户坐标转换为视图坐标实际上是将用户自己设计的逻辑坐标转换为设备相关的坐标,将视图坐标转化为AWT坐标就是将视图坐标按照显示窗口的大小进行缩放。
算法设计:
功能:用户可根据自己输入的用户坐标,进行视图坐标与awt坐标之间的转换,反向的转换原理与正向相同。此外,该程序还可以进行图形的绘制和填充,如矩形,椭圆等图形。
算法1:用户坐标向视图坐标的转换
设userMinx、userMaxx分别为用户坐标系x轴的最小值与最大值,userMiny、userMaxy分别为用户坐标系y轴的最小值与最大值;viewMinx、viewMaxx分别为视图坐标系x轴的最小值与最大值,viewMiny、viewMaxy分别为视图坐标系y轴的最小值与最大值。
若令(userX,userY)为要转换的用户坐标,(viewX,viewY)为转换后的视图坐标。则它们之间的转换关系为:
viewX=viewMinx+(userX-userMinx)/(userMaxx-userMinx)*(viewMaxx-viewMinx) ;
viewY=viewMiny+(userY-userMiny)/(userMaxy-userMiny)*(viewMaxy-viewMiny) ;
算法1实现如下:
public double viewX(double userX) {//x坐标的转换
double s=(userX-userMinx)/(userMaxx-userMinx);
double t=viewMinx+s*(viewMaxx-viewMinx); //坐标的平移及压缩
return t;
}
public double viewY(double userY) {//y坐标的转换
double s=(y-userMiny)/(userMaxy-userMiny);
double t=viewMiny+s*(viewMaxy-viewMiny); //坐标的平移及压缩
return t;
}
算法2:视图坐标向awt坐标的转换
若令(viewX,viewY)为视图坐标,(x,y)为awt坐标,width、height分别为窗口的宽度和高度,则它们之间的转换关系为:
X = viewX * width ;
Y = viewY * height ;
算法2实现如下:
//将视图坐标系的点转换到Java AWT坐标
public int getIntX(double viewX) {
return (int)(windowWidth * viewX); //注意视图坐标0-1之间
}
public int getIntY(double viewY) {
return (int)(windowHeight * (1-viewY)); //Y轴方向相反
}
算法3:绘制矩形
首先将传入的用户坐标转换为awt坐标,通过对传入的坐标比较,找出矩形左上角坐标(ix0,iy0),并求出矩形的宽度width和高度height,利用Graphics类的方法drawRect(ix0,iy0,width,height)可画出矩形。
算法3实现如下:
public void drawRect(double x1,double y1,double x2,double y2) {
//从用户的点坐标转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
int ix0=(ix1<ix2)?ix1:ix2; //矩形左上角坐标
int iy0=(iy1<iy2)?iy1:iy2;
int width=Math.abs((ix1-ix2))+1; //矩形宽度,单位像素
int height=Math.abs((iy1-iy2))+1; //矩形高度
graphics.drawRect(ix0,iy0,width,height);
}
代码:(给出主要的Java程序和注解)
//文件名:MyCanvas.java
//定义用户的canvas类,实现
// 从用户坐标到视图的转换
// 视图到JavaAWT坐标的转换
// 用户坐标系的二维图形的描画方法,等
//用编译命令javac -d . MyCanvas.java把本文件制作成包MyCanvas
//在调用这个包的程序里加入语句import MyCanvas.MyCanvas;
package shiyan1; //制作的包名,这里包名和类名同
import java.io.*;
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
//定义canvas类
public class MyCanvas extends Component {
public static void main(String[] args) {
Applet m = new Applet() ;
m.setSize(256, 256) ;
MyCanvas my = new MyCanvas(m) ;
my.setWindow(-1,1,-1,1); //设定用户坐标系范围
my.createViewport(2) ;
my.setViewport(0, 1, 0, 1) ;
System.out.println("用户坐标 视图坐标 awt坐标");
System.out.print(0.3+" ");
double x = my.viewX(0.3) ;
System.out.print(x+" ");
int xx = my.getIntX(x) ;
System.out.println(xx);
}
//用户坐标系范围缺省值([-1,1],[-1,1])
protected double userMinx=-1; //用户坐标系X轴的最小值
protected double userMaxx=1; //用户坐标系X轴的最大值
protected double userMiny=-1; //用户坐标系Y轴的最小值
protected double userMaxy=1; //用户坐标系Y轴的最大值
//视图的坐标范围缺省值([0,1],[0,1])
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; //当前视图的索引号
//窗口大小
final static int DefaultWindowSize=256; //缺省的窗口大小
protected int windowWidth=DefaultWindowSize; //窗口宽度
protected int windowHeight=DefaultWindowSize; //窗口宽度
//定义Java AWT 的Graphics 和 Component
protected Graphics graphics; //MyCanvas的Graphics数据类
protected Component component; //MyCanvas的component数据类
protected Color currentFrontColor=Color.white; //当前前景颜色
protected Color currentBackColor=Color.white; //当前背景色
//构造方法
//缺省的构造方法中viewportMax=256
public MyCanvas(Component a) {
component=a; //设定MyCanvas类所用的Component
graphics=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[currentViewport]=0.0; //设定当前视图的坐标轴范围
viewMiny[currentViewport]=0.0;
viewMaxx[currentViewport]=1.0;
viewMaxy[currentViewport]=1.0;
viewportNum=1; //当前视图数
}
//设定用户坐标系范围
public void setWindow(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) {
currentViewport=viewportNum; //设定新的当前视图索引号
viewportNum++; //当前视图数加1
viewMinx[currentViewport]=x1; //存放视图的X轴最小值
viewMaxx[currentViewport]=x2; //存放视图的X轴最大值
viewMiny[currentViewport]=y1; //存放视图的y轴最小值
viewMaxy[currentViewport]=y2; //存放视图的y轴最大值
}
//视图复位
public void resetViewport() {
currentViewport=0; //当前视图索引号重归于零
viewMinx[currentViewport]=0.0; //设定当前视图的坐标轴范围
viewMiny[currentViewport]=0.0;
viewMaxx[currentViewport]=1.0;
viewMaxy[currentViewport]=1.0;
viewportNum=1; //当前视图数
}
//将视图坐标系的点转换到Java AWT坐标
public int getIntX(double x) {
return (int)(windowWidth * x); //注意视图坐标0-1之间
}
public int getIntY(double y) {
return (int)(windowHeight * (1-y)); //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 AWT坐标
return ix;
}
public int getY(double y) {
double yy=viewY(y); //先将y转换到视图坐标
int iy=getIntY(yy); //将视图坐标转换到Java AWT坐标
return iy;
}
//将用户坐标系的宽度、高度值投影到Java AWT坐标
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) {
graphics.setColor(c); //设置图形对象的颜色
currentFrontColor=c; //设定当前颜色序号
}
public Color getForeground() {
return currentFrontColor; //得到当前前景色序号
}
public void setForeground(Color c) {
component.setForeground(c); //设置前景色
currentFrontColor=c; //设定当前前景色序号
}
public Color getBackground() {
return currentBackColor; //得到当前背景色序号
}
public void setBackground(Color c) {
component.setBackground(c); //设置背景色
currentBackColor=c; //设定当前背景色序号
}
//-----各类图形的描画方法-----------
//直线画法:两点式参数
public void drawLine(double x1,double y1,double x2,double y2) {
//从用户的点坐标转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
graphics.drawLine(ix1,iy1,ix2,iy2); //这个方法它是怎样画直线的?
}
//矩形画法:对角式参数
public void drawRect(double x1,double y1,double x2,double y2) {
//从用户的点坐标转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
int ix0=(ix1<ix2)?ix1:ix2; //矩形左上角坐标
int iy0=(iy1<iy2)?iy1:iy2;
int width=Math.abs((ix1-ix2))+1; //矩形宽度,单位像素
int height=Math.abs((iy1-iy2))+1; //矩形高度
graphics.drawRect(ix0,iy0,width,height);
}
//矩形填充
public void fillRect(double x1,double y1,double x2,double y2) {
//从用户的点坐标转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
int ix0=(ix1<ix2)?ix1:ix2; //矩形左上角坐标
int iy0=(iy1<iy2)?iy1:iy2;
int width=Math.abs((ix1-ix2))+1; //矩形宽度,单位像素
int height=Math.abs((iy1-iy2))+1; //矩形高度
graphics.fillRect(ix0,iy0,width,height); //填充算法如何实现?
}
//矩形区域的清除
public void clearRect(double x1,double y1,double x2,double y2) {
//从用户的点坐标转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
int ix0=(ix1<ix2)?ix1:ix2; //矩形左上角坐标
int iy0=(iy1<iy2)?iy1:iy2;
int width=Math.abs((ix1-ix2))+1; //矩形宽度,单位像素
int height=Math.abs((iy1-iy2))+1; //矩形高度
graphics.clearRect(ix0,iy0,width,height); //算法等同填充
}
//圆角矩形画法
public void drawRoundRect(double x1,double y1,double x2,double y2,
double arcW,double arcH) { //圆弧高度、圆弧宽度
//从用户坐标的点转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
int ix0=(ix1<ix2)?ix1:ix2; //矩形左上角坐标
int iy0=(iy1<iy2)?iy1:iy2;
int width=Math.abs((ix1-ix2))+1; //矩形宽度,单位像素
int height=Math.abs((iy1-iy2))+1; //矩形高度
int iarcWidth=getDimensionX(arcW); //圆弧宽度投影到Java AWT坐标
int iarcHeight=getDimensionX(arcH); //圆弧高度投影
graphics.drawRoundRect(ix0,iy0,width,height,iarcWidth,iarcHeight);
}
//圆角矩形填充
public void fillRoundRect(double x1,double y1,double x2,double y2,
double arcW,double arcH) { //圆弧高度、圆弧宽度
//从用户坐标的点转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
int ix0=(ix1<ix2)?ix1:ix2; //矩形左上角坐标
int iy0=(iy1<iy2)?iy1:iy2;
int width=Math.abs((ix1-ix2))+1; //矩形宽度,单位像素
int height=Math.abs((iy1-iy2))+1; //矩形高度
int iarcWidth=getDimensionX(arcW); //圆弧宽度投影到Java AWT坐标
int iarcHeight=getDimensionX(arcH); //圆弧高度投影
graphics.fillRoundRect(ix0,iy0,width,height,iarcWidth,iarcHeight);
}
//带阴影矩形的画法
public void draw3DRect(double x1,double y1,double x2,double y2,
boolean raised) { //阴影抬升或者洼陷
//从用户坐标的点转换到Java AWT坐标
int ix1=getX(x1); int iy1=getY(y1);
int ix2=getX(x2); int iy2=getY(y2);
int ix0=(ix1<ix2)?ix1:ix2; //矩形左上角坐标
int iy0=(iy1<iy2)?iy1:iy2;
int width=Math.abs((ix1-ix2))+1; //矩形宽度,单位像素
int height=Math.abs((iy1-iy2))+1; //矩形高度
graphics.draw3DRect(ix0,iy0,width,height,raised);
}
//椭圆的画法(圆心坐标和两个半径)
public void drawOval(double x,double y,double xr,double yr) {
//圆心从用户坐标转换到Java AWT坐标
int ix=getX(x); int iy=getY(y);
int ixr=getDimensionX(xr); //x轴半径投影到Java AWT坐标
int iyr=getDimensionX(yr); //y轴半径投影
int x0=ix-ixr; //椭圆外切矩形的左上角x坐标
int y0=iy-iyr; //椭圆外切矩形的左上角y坐标
graphics.drawOval(x0,y0,2*ixr,2*iyr);
}
//椭圆的填充(圆心坐标和两个半径)
public void fillOval(double x,double y,double xr,double yr) {
//圆心从用户坐标转换到Java AWT坐标
int ix=getX(x); int iy=getY(y);
int ixr=getDimensionX(xr); //x轴半径投影到Java AWT坐标
int iyr=getDimensionX(yr); //y轴半径投影
int x0=ix-ixr; //椭圆外切矩形的左上角x坐标
int y0=iy-iyr; //椭圆外切矩形的左上角y坐标
graphics.fillOval(x0,y0,2*ixr,2*iyr);
}
//圆弧的画法(圆心坐标和椭圆弧两个半径,两个角度)
public void drawArc(double x,double y,double xr,double yr,
double startAngle,double arcAngle) {
//圆心从用户坐标转换到Java AWT坐标
int ix=getX(x); int iy=getY(y);
int ixr=getDimensionX(xr); //x轴半径投影到Java AWT坐标
int iyr=getDimensionX(yr); //y轴半径投影
int x0=ix-ixr; //椭圆外切矩形的左上角x坐标
int y0=iy-iyr; //椭圆外切矩形的左上角y坐标
int is=(int)(90-(startAngle+arcAngle)); //开始角度
//注意Java AWT从Y轴顺时针度量
int ia=(int)arcAngle; //扇形的圆心角
graphics.drawArc(x0,y0,2*ixr,2*iyr,is,ia);
}
//扇形的填充(圆心坐标和椭圆弧两个半径,两个角度)
public void fillArc(double x,double y,double xr,double yr,
double startAngle,double arcAngle) {
//圆心从用户坐标转换到Java AWT坐标
int ix=getX(x); int iy=getY(y);
int ixr=getDimensionX(xr); //x轴半径投影到Java AWT坐标
int iyr=getDimensionX(yr); //y轴半径投影
int x0=ix-ixr; //椭圆外切矩形的左上角x坐标
int y0=iy-iyr; //椭圆外切矩形的左上角y坐标
int is=(int)(90-(startAngle+arcAngle)); //开始角度
//注意Java AWT从Y轴顺时针度量
int ia=(int)arcAngle; //扇形的圆心角
graphics.fillArc(x0,y0,2*ixr,2*iyr,is,ia);
}
//折线
public void drawPolyline(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 AWT坐标
iy[i]=getY(y[i]);
}
graphics.drawPolyline(ix,iy,numPoints);
}
//多边形
public void drawPolygon(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 AWT坐标
iy[i]=getY(y[i]);
}
graphics.drawPolygon(ix,iy,numPoints); //封闭的折线图
}
//多边形填充
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 AWT坐标
iy[i]=getY(y[i]);
}
graphics.fillPolygon(ix,iy,numPoints); //掌握填充的算法是重点
}
//写字符串
public void drawString(String str,double x,double y) {
//从用户坐标点转换到Java AWT坐标
int ix=getX(x); int iy=getY(y);
graphics.drawString(str,ix,iy);
}
//获取当前Graphics类的字体
public Font getFont() {
return graphics.getFont();
}
//设定当前Graphics类的字体
public void setFont(Font f) {
graphics.setFont(f);
}
//定义一种字体:仅对window已有字体放大尺寸
public Font MyFont(String name,int style,double size) {
int DefaultFontSize=12;
if(size<=0) size=1.0; //字体大小不能为负数
int isize=(int)(DefaultFontSize*size); //定义字体的大小
Font f=new Font(name,style,isize); //构造字体
return f;
}
//Java AWT坐标系到视图坐标系的反向转换
public int getViewport(int ix,int iy){
if(viewportNum==1) return 0; //默认视图
double s=(double)(ix)/(double)windowWidth;
double t=(double)(windowHeight-iy)/(double)windowHeight;
for(int i=0;i<viewportNum;i++) { //视图索引号
if(s>=viewMinx[i] && s<=viewMaxx[i] &&
t>=viewMiny[i] && t<=viewMaxy[i]) return i;
}
return 0;
}
//视图到用户坐标系的反向转换(x坐标)
public double getUserX(int ix,int v) {
double t=(double)(ix)/(double)windowWidth;
double x=userMinx+(t-viewMinx[v])/(viewMaxx[v]-viewMinx[v])*
(userMaxx-userMinx);
return x;
}
//视图到用户坐标系的反向转换(y坐标)
public double getUserY(int iy,int v) {
double t=(double)(windowHeight-iy)/(double)windowHeight;
double y=userMiny+(t-viewMiny[v])/(viewMaxy[v]-viewMiny[v])*
(userMaxy-userMiny);
return y;
}
//******线段光栅化的成员变量********
protected Image image; //Java图像类的对象
protected MemoryImageSource mis; //内存图像数据源
protected int pixelWidth; //图像点阵的宽度(像素数)
protected int pixelHeight; //图像点阵的高度(像素数)
protected int[] pixel; //存放图像点的颜色(行优先一维存放)
protected int xoffset; //像素数据窗口内X坐标的偏移
protected int yoffset; //像素数据窗口内Y坐标的偏移
//直线(光栅化)实数型Bresenham算法
public v
展开阅读全文