1、计算机图形学实验 2 实验报告实验题目:多视图绘图程序实验内容:掌握多视图绘图的概念,掌握二维统计图的绘制方法。调用实验 1 中自己编写的基本包,绘制自己所设计的统计图形(饼图、直方图以及折线) 。编写程序调用验证之。基本概念:(详细叙述自己对实验内容的理解)多视图:就是将多个绘制好的图形按照一定的规则组成一个具有特定意义的图形,在同一个视图中显示出来,如下面绘制的几种统计图形(饼图、直方图以及折线) 。饼图:可以清楚的表示出各个部分所占的比例;直方图:可以清楚地的显示各部分的数量的多少;折线:可以清楚地反应各个部分的变化趋势。算法设计:(详细叙述自己设计的多视图统计图以及程序的功能、算法及实
2、现)public abstract void drawLine(int x1, int y1, int x2, int y2) 使用当前颜色,在点(x1, y1) 和 (x2, y2) 之间画线。public abstract void drawOval(int x, int y, int width, int height) 画椭圆。public abstract void fillOval(int x, int y, int width, int height) 画实心椭圆。public abstract void drawPolygon(int xPoints, int yPoints,
3、 int nPoints) 画 x 和 y 坐标定义的多边形。public void drawRect(int x, int y, int width, int height) 画矩形。public void drawRect(int x, int y, int width, int height) 画实心矩形。public abstract void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) 使用当前颜色画圆角矩形。public abstract void drawStrin
4、g(String str, int x, int y) 使用当前字体和颜色画字符串 str。public abstract void setColor(Color c) 设置图形上下文的当前颜色。public abstract void setPaintMode() 设置画模式。public abstract boolean drawImage(Image img, int x, int y, ImageObserver observer) 画特定图。public abstract void setFont(Font font) 设置特定的 font 字体。使用时首先得到 font 对象的一个
5、实例,Font 类常用构造函数为:public Font(String name, int style, int size) public Color(int red, int green, int blue, int alpha)其中:前三个分量即 RGB 颜色模式中的参数,第四个 alpha 分量指透明的程度。当 alpha 分量为 255 时,表示完全不透明,正常显示;当 alpha 分量为 0 时,表示完全透明,前三个分量不起作用,而介于 0255 之间的值可以制造出颜色不同的层次效果。代码:(给出和实验内容相关的 Java 程序和注解,不要辅助代码,否则扣分)/画 圆饼统计图(薪资统
6、计 )public void paintPIGraph_1(MyCanvas m) double r=0.4;/外圆半径/*利用三基色构造颜色*/m.setColor(new Color(float)0.95,(float)0.75,(float)0.6);double excellent=0.10*360; /5k以上占 10%对应的扇形角m.fillArc(0,0,r,r,0,excellent); /从0 度起画“优秀“对应的扇形/* 扇弧终止点的坐标 */double excellentX=r*Math.sin(excellent*Math.PI/180);double excelle
7、ntY=r*Math.cos(excellent*Math.PI/180);double sum=excellent; /从0度起已经画出的扇弧角度m.setColor(new Color(float)0.80,(float)0.80,(float)0.50);double good=0.3*360; /4k5k占30%对应的扇形角m.fillArc(0,0,r,r,sum,good); /从sum度起画“良好“对应的扇形sum+=good; /从0度起已经画出的扇弧角度/* 扇弧终止点的坐标 */double goodX=r*Math.sin(sum*Math.PI/180);double
8、goodY=r*Math.cos(sum*Math.PI/180);m.setColor(new Color(float)0.65,(float)0.85,(float)0.40);double medium=0.40*360;/3k4k占40%对应的扇形角m.fillArc(0,0,r,r,sum,medium); /从sum度起画“中等“对应的扇形sum+=medium; /从0度起已经画出的扇弧角度double mediumX=r*Math.sin(sum*Math.PI/180);/扇弧终止点的坐标double mediumY=r*Math.cos(sum*Math.PI/180);m
9、.setColor(new Color(float)0.50,(float)0.90,(float)0.30);double pass=0.20*360; /3k以下占20%对应的扇形角m.fillArc(0,0,r,r,sum,pass); /从sum度起画“及格“对应的扇形sum+=pass; /从0度起已经画出的扇弧角度double passX=r*Math.sin(sum*Math.PI/180); /扇弧终止点的坐标double passY=r*Math.cos(sum*Math.PI/180);m.setColor(Color.black); /当前颜色m.drawOval(0,0
10、,r,r); /画(椭)圆m.drawLine(0,0,0,r); /画起点方位半径m.drawLine(0,0,excellentX,excellentY); /画扇形分界线半径m.drawLine(0,0,goodX,goodY);m.drawLine(0,0,mediumX,mediumY);m.drawLine(0,0,passX,passY);/* 定义字体, 标准大小 */Font f0=m.MyFont(m.getFont().getName(),m.getFont().getStyle(),1.0);m.setFont(f0); /设定字体m.drawString(“5k以上“
11、 ,0.00,0.30); /写字符串m.drawString(“10%“,0.00,0.20);m.drawString(“4k5k“,0.05,0.0); /写字符串m.drawString(“30%“,0.10,-0.10);m.drawString(“3k4k“,-0.2,-0.1); /写字符串m.drawString(“40%“,-0.2,-0.2);m.drawString(“3k以下“ ,-0.25,0.17); /写字符串m.drawString(“20%“,-0.2,0.07);Font f1=m.MyFont(m.getFont().getName(),m.getFont
12、().getStyle(),1.5); /字体放大m.setFont(f1);m.drawString(“薪资统计图“,-0.3,-0.8); /写字符串 /圆饼统计图结 束/ 画直方 图(薪资统计 )public void paintPIGraph_2(MyCanvas m) /画X轴double x1=0.49,0.51,0.49; /箭头三个点的X 坐标double y1=-0.32,-0.3,-0.28; /箭头三个点的Y 坐标m.drawLine(-0.5,-0.3,0.5,-0.3); /画X 轴m.fillPolygon(x1,y1,3);/填充箭头m.drawString(“薪
13、资范围“,0.40,-0.38); /X轴写字符串/画Y轴double y2=0.09,0.11,0.09; /箭头三个点的Y 坐标double x2=-0.48,-0.5,-0.52; /箭头三个点的X 坐标m.drawLine(-0.5,-0.3,-0.5,0.1); /画Y 轴m.fillPolygon(x2,y2,3);/填充箭头m.drawString(“人数/人“,-0.70,0.1); /Y轴写字符串/y轴画标尺m.drawLine(-0.5,-0.22,-0.48,-0.22);m.drawLine(-0.5,-0.14,-0.48,-0.14);m.drawLine(-0.5
14、,-0.06,-0.48,-0.06);m.drawLine(-0.5,0.02,-0.48,0.02);m.drawString(“40“, -0.60, 0.00);m.drawString(“30“, -0.60, -0.08);m.drawString(“20“, -0.60, -0.16);m.drawString(“10“, -0.60, -0.24);/x轴画标尺m.drawRect(-0.4, -0.3, -0.3, -0.14);m.setColor(Color.green);m.fillRect(-0.395, -0.3, -0.3, -0.145);m.setColor(
15、Color.black);m.drawRect(-0.2, -0.3, -0.1, 0.02);m.setColor(Color.blue);m.fillRect(-0.195, -0.3, -0.1, 0.015);m.setColor(Color.black);m.drawRect(0.0, -0.3, 0.1, -0.06);m.setColor(Color.orange);m.fillRect(0.005, -0.3, 0.1, -0.065);m.setColor(Color.black);m.drawRect(0.2, -0.3, 0.3, -0.22);m.setColor(Co
16、lor.red);m.fillRect(0.205, -0.3, 0.3, -0.225);m.setColor(Color.black);m.drawString(“3k以下“ , -0.45, -0.37);m.drawString(“3k4k“, -0.23, -0.37);m.drawString(“4k5k“, -0.03, -0.37);m.drawString(“5k以上“ , 0.17, -0.37);m.drawString(“o“, -0.55, -0.32);m.drawString(“11级应届毕业生薪资统计 直方图“, -0.5, -0.5);public void
17、paintPIGraph_3(MyCanvas m) /画 X轴double x1=1.79,1.81,1.79; /箭头三个点的X 坐标double y1=-0.32,-0.3,-0.28; /箭头三个点的Y 坐标m.drawLine(0.8,-0.3,1.8,-0.3); /画X 轴m.fillPolygon(x1,y1,3);/填充箭头m.drawString(“薪资范围“,1.7,-0.38); /X轴写字符串/画 Y轴double y2=0.09,0.11,0.09; /箭头三个点的Y坐标double x2=0.78,0.8,0.82; /箭头三个点的X 坐标m.drawLine(0
18、.8,-0.3,0.8,0.1); /画Y轴m.fillPolygon(x2,y2,3);/填充箭头m.drawString(“人数/人“,0.6,0.1); /Y轴写字符串/y轴画标尺m.drawLine(0.8,-0.22,0.82,-0.22);m.drawLine(0.8,-0.14,0.82,-0.14);m.drawLine(0.8,-0.06,0.82,-0.06);m.drawLine(0.8,0.02,0.82,0.02);m.drawString(“40“, 0.7, 0.00);m.drawString(“30“, 0.7, -0.08);m.drawString(“20
19、“, 0.7, -0.16);m.drawString(“10“, 0.7, -0.24);/x轴画标尺m.setColor(Color.black);m.drawLine(0.95,-0.3,0.95,-0.28);m.drawLine(1.15,-0.3,1.15,-0.28);m.drawLine(1.35,-0.3,1.35,-0.28);m.drawLine(1.55,-0.3,1.55,-0.28);m.drawString(“3k以下“ , 0.85, -0.37);m.drawString(“3k4k“, 1.07, -0.37);m.drawString(“4k5k“, 1.
20、27, -0.37);m.drawString(“5k以上“ , 1.47, -0.37);m.drawString(“o“, 0.75, -0.32);/画折 线double x3=0.95,1.15,1.35,1.55;double y3=-0.14,0.02,-0.06,-0.22;m.drawPolyline(x3, y3, 4);m.fillOval(0.95, -0.14, 0.01, 0.01);m.fillOval(1.15, 0.02, 0.01, 0.01);m.fillOval(1.35, -0.06, 0.01, 0.01);m.fillOval(1.55, -0.22
21、, 0.01, 0.01);m.drawString(“11级应届毕业生薪资统计折 线图“, 0.8, -0.5);/Applet程序的描绘方法 paintpublic void paint(Graphics g) m.setBackground(Color.gray); /当前背景色m.setWindow(-2,2,-1,1);/用户坐标系范围/视图 定义(第一个 圆饼统计图在窗口的位置)m.setViewport(-0.15,0.35,0.20,0.70); /窗口下半面,左右居中paintPIGraph_1(m); /画饼统计图m.setViewport(-0.15,0.35,0.60,
22、1.10); /窗口上半面,左右居中paintPIGraph_1(m); /再画圆饼统计图m.resetViewport(); /视图复位/视图 定义(第一个直方 图在窗口的位置)m.setViewport(-0.15,1.00,0.00,0.8); /窗口下半面,左右居中paintPIGraph_2(m); /画直方图m.setViewport(-0.15,1.00,0.50,1.30); /窗口上半面,左右居中paintPIGraph_2(m); /再直方图m.resetViewport(); /视图复位/视图 定义(第一个折 线图在窗口的位置)m.setViewport(-0.15,1.
23、00,0.00,0.8); /窗口下半面,左右居中paintPIGraph_3(m); /画折线图m.setViewport(-0.15,1.00,0.50,1.30); /窗口上半面,左右居中paintPIGraph_3(m); /再折线图m.resetViewport(); /视图复位Font f2=m.MyFont(m.getFont().getName(),m.getFont().getStyle(),2.0); /字体放大m.setFont(f2);m.drawString(“多视图演示程序(信息专业11级学生的就业薪资统计)“,-0.80,-0.85); /写字符串 /描 绘方法
24、paint结束运行结果:(给出运行结果的截屏和说明)分步制作过程1.饼图制作及位移效果(如图)2.直方图制作及位移效果(如图)3.折线图制作及位移效果(如图)实验体会:(简单说明学习到的知识点和收获)在本次实验中,我制作的是对 11 级信息专业应届生的基本薪资(纯属虚构)的统计图,利用三种统计图(饼图、直方图以及折线)分别完成,掌握了三种统计图的绘制方法,同时了解了如何改变字体的大小和颜色,此外,找到了可以改变运行窗口的代码(之前不知道如何改变运行窗口的大小) 。希望在以后的实验中可以掌握更多的知识。参考程序:有一个示范程序 MultiViewport.java 和一个辅助程序 MyCanva
25、s.javapackage dome2;/MultiViewport.java/多视图程序import java.awt.*; /绘图基于 java AWT 包import java.applet.Applet;/定义多视图类public class MultiViewport extends Applet MyCanvas m; /定义 MyCanvas 类的对象/ final static int idealSizeX=600; /窗口宽度/ final static int idealSizeY=600; /窗口高度/Applet 程序的自动初始化方法 initpublic void i
26、nit() m=new MyCanvas(this);/生成 MyCanvas 类的对象/画圆饼统计图(成绩统计)public void paintPIGraph_1(MyCanvas m) double r=0.8; /外圆半径double cr=0.3; /内圆半径/*利用三基色构造颜色*/m.setColor(new Color(float)0.95,(float)0.75,(float)0.6);double excellent=0.15*360; /优秀占 15%对应的扇形角m.fillArc(0,0,r,r,0,excellent); /从 0 度起画“优秀“ 对应的扇形/* 扇弧
27、终止点的坐标 */double excellentX=r*Math.sin(excellent*Math.PI/180);double excellentY=r*Math.cos(excellent*Math.PI/180);double sum=excellent; /从 0 度起已经画出的扇弧角度m.setColor(new Color(float)0.80,(float)0.80,(float)0.50);double good=0.25*360; /良好占 25%对应的扇形角m.fillArc(0,0,r,r,sum,good); /从 sum 度起画“良好“对应的扇形sum+=goo
28、d; /从 0 度起已经画出的扇弧角度/* 扇弧终止点的坐标 */double goodX=r*Math.sin(sum*Math.PI/180);double goodY=r*Math.cos(sum*Math.PI/180);m.setColor(new Color(float)0.65,(float)0.85,(float)0.40);double medium=0.35*360; /中等占 35%对应的扇形角m.fillArc(0,0,r,r,sum,medium); /从 sum 度起画“ 中等“对应的扇形sum+=medium; /从 0 度起已经画出的扇弧角度double med
29、iumX=r*Math.sin(sum*Math.PI/180); /扇弧终止点的坐标double mediumY=r*Math.cos(sum*Math.PI/180);m.setColor(new Color(float)0.50,(float)0.90,(float)0.30);double pass=0.20*360; /及格占 20%对应的扇形角m.fillArc(0,0,r,r,sum,pass); /从 sum 度起画“及格“对应的扇形sum+=pass; /从 0 度起已经画出的扇弧角度double passX=r*Math.sin(sum*Math.PI/180); /扇弧终
30、止点的坐标double passY=r*Math.cos(sum*Math.PI/180);m.setColor(new Color(float)0.35,(float)0.95,(float)0.2);double fail=0.05*360; /不及格占 5%对应的扇形角m.fillArc(0,0,r,r,sum,fail); /从 sum 度起画“不及格“对应的扇形sum+=fail; /从 0 度起已经画出的扇弧角度double failX=r*Math.sin(sum*Math.PI/180); /扇弧终止点的坐标double failY=r*Math.cos(sum*Math.PI
31、/180);m.setColor(Color.black); /当前颜色m.drawOval(0,0,r,r); /画(椭)圆m.drawLine(0,0,0,r); /画起点方位半径m.drawLine(0,0,excellentX,excellentY); /画扇形分界线半径m.drawLine(0,0,goodX,goodY);m.drawLine(0,0,mediumX,mediumY);m.drawLine(0,0,passX,passY);m.drawLine(0,0,failX,failY);/* 定义字体,标准大小 */Font f0=m.MyFont(m.getFont().
32、getName(),m.getFont().getStyle(),1.0);m.setFont(f0); /设定字体m.drawString(“优秀“,0.1,0.47); /写字符串m.drawString(“15%“,0.1,0.30);m.drawString(“良好“,0.25,0.0); /写字符串m.drawString(“25%“,0.25,-0.15);m.drawString(“中等“,-0.28,-0.3); /写字符串m.drawString(“35%“,-0.28,-0.45);m.drawString(“及格“,-0.5,0.17); /写字符串m.drawStrin
33、g(“20%“,-0.5,0.02);m.drawLine(-0.1,0.47,-0.2,1.0); /画引线m.drawString(“不及格“,-0.2,1.15); /写字符串m.drawString(“5%“,-0.2,1.0);Font f1=m.MyFont(m.getFont().getName(),m.getFont().getStyle(),1.5); /字体放大m.setFont(f1);m.drawString(“成绩统计图“,-0.4,-1.2); /写字符串 /圆饼统计图结束/Applet 程序的描绘方法 paintpublic void paint(Graphics
34、 g) m.setBackground(Color.white); /当前背景色m.setWindow(-1,1,-1,1);/用户坐标系范围/视图定义(第一个圆饼统计图在窗口的位置)m.setViewport(0.5,1.0,0.25,0.75); /窗口右半面,上下居中paintPIGraph_1(m); /画饼统计图m.setViewport(0.0,0.5,0.25,0.75); /窗口左半面,上下居中paintPIGraph_1(m); /再画圆饼统计图m.resetViewport(); /视图复位Font f2=m.MyFont(m.getFont().getName(),m.g
35、etFont().getStyle(),2.0); /字体放大m.setFont(f2);m.drawString(“多视图演示程序“,-0.4,-0.9); /写字符串 /描绘方法 paint 结束 /显式曲线描绘类结束/文件名:MyCanvas.java/定义用户的 canvas 类,实现/ 从用户坐标到视图的转换/ 视图到 JavaAWT 坐标的转换/ 用户坐标系的二维图形的描画方法,等/用编译命令 javac -d . MyCanvas.java 把本文件制作成包 MyCanvas/在调用这个包的程序里加入语句 import MyCanvas.MyCanvas;package dome
36、2; /制作的包名,这里包名和类名同import java.io.*;import java.awt.*;import java.awt.image.*;/定义 canvas 类public class MyCanvas extends Component /用户坐标系范围缺省值(-1,1,-1,1)protected double userMinx=-1; /用户坐标系 X 轴的最小值protected double userMaxx=1; /用户坐标系 X 轴的最大值protected double userMiny=-1; /用户坐标系 Y 轴的最小值protected double u
37、serMaxy=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
38、; /最大视图数protected int viewportNum=0; /当前视图数protected int currentViewport=0; /当前视图的索引号/窗口大小final static int DefaultWindowSize=256; /缺省的窗口大小protected int windowWidth=DefaultWindowSize; /窗口宽度protected int windowHeight=DefaultWindowSize; /窗口宽度/定义 Java AWT 的 Graphics 和 Componentprotected Graphics graphic
39、s; /MyCanvas 的 Graphics 数据类protected Component component; /MyCanvas 的 component 数据类protected Color currentFrontColor=Color.white; /当前前景颜色protected Color currentBackColor=Color.white; /当前背景色/构造方法/缺省的构造方法中 viewportMax=256public MyCanvas(Component a) component=a; /设定 MyCanvas 类所用的 Componentgraphics=a.g
40、etGraphics(); /设定 MyCanvas 类所用的 graphicswindowWidth=a.getSize().width; /窗口宽度windowHeight=a.getSize().height; /窗口高度createViewport(DefaultViewportMax); /创建视图/创建视图private void createViewport(int max) currentViewport=0;/设定当前视图索引号viewportMax=max;/设定视图数的最大值viewMinx=new doubleviewportMax; /存放各视图 X 轴最小值view
41、Maxx=new doubleviewportMax; /存放各视图 X 轴最大值viewMiny=new doubleviewportMax; /存放各视图 y 轴最小值viewMaxy=new doubleviewportMax; /存放各视图 y 轴最大值viewMinxcurrentViewport=0.0; /设定当前视图的坐标轴范围viewMinycurrentViewport=0.0;viewMaxxcurrentViewport=1.0;viewMaxycurrentViewport=1.0;viewportNum=1; /当前视图数/设定用户坐标系范围public void
42、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; /设定新的当前视图索引号viewportNu
43、m+; /当前视图数加 1viewMinxcurrentViewport=x1; /存放视图的 X 轴最小值viewMaxxcurrentViewport=x2; /存放视图的 X 轴最大值viewMinycurrentViewport=y1; /存放视图的 y 轴最小值viewMaxycurrentViewport=y2; /存放视图的 y 轴最大值/视图复位public void resetViewport() currentViewport=0;/当前视图索引号重归于零viewMinxcurrentViewport=0.0; /设定当前视图的坐标轴范围viewMinycurrentVie
44、wport=0.0;viewMaxxcurrentViewport=1.0;viewMaxycurrentViewport=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
45、) double s=(x-userMinx)/(userMaxx-userMinx);double t=viewMinxcurrentViewport+s* /坐标的平移及压缩(viewMaxxcurrentViewport-viewMinxcurrentViewport);return t;public double viewY(double y) double s=(y-userMiny)/(userMaxy-userMiny);double t=viewMinycurrentViewport+s* /坐标的平移及压缩(viewMaxycurrentViewport-viewMinycu
46、rrentViewport);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 坐标publ
47、ic int getDimensionX(double w) double x=viewMaxxcurrentViewport-viewMinxcurrentViewport;x*=windowWidth*w/(userMaxx-userMinx);/按比例投影,经由视图坐标系return (int)Math.abs(x); /用户坐标系可能反向public int getDimensionY(double h) double y=viewMaxycurrentViewport-viewMinycurrentViewport;y*=windowHeight*h/(userMaxy-userMi
48、ny);/按比例投影,经由视图坐标系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 s