文档库 最新最全的文档下载
当前位置:文档库 › 实验报告5 多边形裁剪与填充

实验报告5 多边形裁剪与填充

实验报告5 多边形裁剪与填充
实验报告5 多边形裁剪与填充

《计算机图形学》实验5实验报告

实验题目:多边形裁剪与填充

实验内容:1 阅读理解提供的参考资料。

2编写并调通一个多边形裁剪的java程序。

3编写并调通一个多边形填充的java程序。

参考资料:1fillPolygon.java

2 clipSC2.java

3变换与剪裁.ppt

4多边形的填充.ppt

基本概念:

1变换与裁剪:

(1)计算机处理图形的过程一般分为三个阶段:①图形的数字化;②图形操作;③图形输出。

(2)模型坐标系(局部坐标系):当构造单个对象的数字模型时,为了方便,可以将其置一个特定的坐标系下,即模型坐标系或局部坐标系。

(3)世界坐标系:为描述图形场景中所有图形之间的空间关系,将它们置于一个统一的坐标系中,该坐标系被称为世界坐标系。

(4)设备坐标系:要输出经过处理后的数字化图形,需要在输出设备上建立一个坐标系,称为设备坐标系。

(5)标准化设备坐标系:有些图形系统,对设备坐标系进行了规范化,将坐标范围限定在区间

{x,y,z | 0≤x≤1, 0≤y≤1, 0≤z≤1}

内,称标准化设备坐标系。

(6)三维图形的显示流程图

(7)裁剪

裁剪作用:选择显示的内容--图形在窗口内的部分被显示出来,窗口外的部分被裁剪掉。图形中每个基本元素都要经过裁剪,因此裁剪直接影响整个图形系统的效率。

裁剪类型:二维裁剪、三维裁剪

裁剪窗口:矩形,凸多边形,任意多边形

视见体:棱台、立方体

裁剪对象:直线段、多边形、文字等

2多边形的填充:

(1)多边形的填充指在给定区域填上所需要的颜色,就是把多边形的顶点表示转换为点阵表示,即从多边形的给定边界出发,求出位于其内部的各个像素,并将帧缓冲器内的各个对应元素设置相应的灰度或颜色。

(2)多边形的表示:

1)顶点表示是用多边形的顶点的序列来描述多边形,该表示几何意义强、占内存少,但它

不能直观地说明哪些像素在多边形内。

2)点阵表示是用位于多边形内的象素的集合来刻划多边形,该方法虽然没有多边形的几何信息,是面着色所需要的图像表示形式。

算法设计:

1 多边形的裁剪:

Sutherland-Cohen 算法:

基本思想:对于每条线段P1P2分为三种情况处理。

(1)若P1P2完全在窗口内,则显示该线段P1P2简称“取”之。

(2)若P1P2明显在窗口外,则丢弃该线段,简称“弃”之。

(3)若线段既不满足“取”的条件,也不满足“弃”的条件,则在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。

具体操作:分为两步

第一步是判定:

1) 完全在窗口内的直线段,称为完全可见的线段;

2) 完全在窗口外的线段,称为完全不可见线段。

第二步处理不能断定为完全可见或完全不可见的线段。

这时需要计算出直线段和窗口边界的一个交点,这个交点把直线分成两段,其中一条为完全不可见的线段,被抛弃。

对余下部分再作第一步的判断,重复上述过程,直到直线段余下的部分可用第一步的判断得出肯定的结论为止。

2多边形的填充:

(1) 多边形填充的扫描线算法

a. 令y = c 为一个常数,扫描整个多边形的边 ,记录横坐标为xi 记为序列1.

b. 设d 为一整数,d =c –1,且yi 0≥y ≥yi n ;设位于扫描线y =d 上的交点序列为 ,记为序列2。

c. 奇点的处理: 多边形P 的顶点可分为两类:极值点和非极值点。如果

称顶点Pi 为极值点(P1,P2,P3,P5, P6,P8);否则称Pi 为非极值点(P0,P4,P7)。若扫描线与多边形相交于多边形的顶点,则该交点(顶点)称为奇点。为了使交点个数保持为偶数,规定当奇点是P 的极值点时,该点按两个交点计算;否则按一个交点计算。

(2) 边缘填充算法:

对多边形P 的每一非水平边上的各像素做向右求反运算即可。

步骤:a. 以值为boundary-color 的特殊颜色勾画多边形P 的边界。设多边形顶点为Pi = (xi , yi ),0≤i ≤n , xi , yi 均为整数;置Pn +1=P 0。每一条扫描线上着上这种特殊颜色的点的个数必定是偶数(包括零)。

b. 设interior_point 是一布尔变量。对每一条扫描线从左到右进行搜索,如果当前是像素位于多边形P 内,则interior_point=true ,需要填上值为polygon_color 的颜色;否则该像素在多边形P 外,需要填上值为background_color 的颜色。

(3) 区域填充:

a. 区域是指已经表示成点阵形式的像素集合。在光栅图形 中,区域可采用内点表示和边界表示两种形式进行描述。

内点表示法:把位于给定区域内的所有像素一一列举出来的方法称为内点表示法。 边界表示法:把位于给定区域边界上的像素一一列举出来的方法称为边界表示法。 b.区域的连通性:

1) 连通的区域: 取区域内任意两点,在该区域内若从其中一点出发通过上、下、左\右四0))((11≥--+-i i i i y y y y

种运动可到达另一点。

2)连通的区域: 取区域内任意两点,若从其中任一点出发,在该区域内通过沿水平方向、垂直方向和对角线方向的八种运动可到达另一点。

(4)扫描线种子填充算法:从给定的种子点开始,填充当前扫描线上种子点所在的一区段,然后确定与这一段相邻的上下两条扫描线上位于区域内的区段(需要填充的区间),从这些区间上各取一个种子点依次把它们存起来,作为下次填充的种子点。反复进行这过程,直到所保存的各区段都填充完毕。

步骤:

a.(初始化)将算法设置的堆栈置为空。将给定的种子点(x, y)压入堆栈

b.(出栈)如果堆栈为空,算法结束;否则取栈顶元素(x, y)作为种子点

c.(区段填充)从种子点(x, y)开始,沿纵坐标为y的当前扫描线向左右两个方向逐个像素用新的颜色值进行填充,直到边界为止即象素颜色等于边界色。设区间两边界的横坐标分别为xleft 和xright。

d. 在与当前扫描线相邻的上下两条扫描线上,以区间[xleft, xright]为搜索范围,求出需要填充的各小区间,把各小区间中最右边的点并作为种子点压入堆栈,转到步骤2。

代码:

1 多边形的裁剪:

public int code(float x,float y)

{

int c=0;

if(x

else if(x>xR)c=c|2;

if(y

else if(y>yT)c=c|8;

return c; //二进制分别为0 1 10 100 1000

}

//Sutherland_Cohen裁减算法

public void Sutherland_Cohen(Graphics g,float x0,float y0,float x2,float y2)

{

int c1,c2,c;

float x,y,wx,wy;

boolean accept=false,done=false;

c1=code(x0,y0);

c2=code(x2,y2);

do {

if ((c1|c2)==0)//两个编码都为0,表明在窗口内

{

accept=true;

done=true;

}

else if((c1&c2)!=0)done=true;//两个编码的某一位为1,则必然在外侧显然在窗口外

else

{

c=c1;

if(c==0)c=c2;

wx=x2-x0;

wy=y2-y0;

if ((c&8)==8) //求交点

{

x=x0+wx*(yT-y0)/wy;

y=yT;

}

else if ((c&4)==4)

{

x=x0+wx*(yB-y0)/wy;

y=yB;

}

else if ((c&1)==1)

{

y=y0+wy*(xL-x0)/wx;

x=xL;

}else//即(c&2)==2

{

y=y0+wy*(xR-x0)/wx;

x=xR;

}

if (c==c1) //表明c1!=0,起始点不在窗口内,将交点作为新的起点重复判断步骤;

{

x0=x;

y0=y;

c1=code(x0,y0);

}else//终点不在窗口内,交点作为新的终点

{

x2=x;

y2=y;

c2=code(x2,y2);

}

}//else

} while (done==false);

if(accept)g.drawLine((int)x0,(int)y0,(int)x2,(int)y2);

}

2多边形的填充:

class activeEdgeList {

activeEdgeListEntry header=null;

activeEdgeListEntry tailer=null;

public activeEdgeList(activeEdgeListEntry element) {

header=tailer=element; //指向第一个边结点

}

//把新结点插入有序排列的多边形单链表

public void insert(activeEdgeListEntry element) {

activeEdgeListEntry sentinel;

if(element==null || this.header==null) //新结点异常或者链表空

throw new NullPointerException(); //出错,抛出异常

sentinel=this.header; //当前指针指向表头结点

int xt=element.topx; //新结点的topx

int xtold=sentinel.topx;

double oldDelta=sentinel.delta; //当前结点的delta

double newDelta=element.delta;

/* 排序第一关键字结点的topx,第二关键字结点的delta */

/* 两个关键字由小到大*/

if((xtold

while(true){ //在链表头指针之后寻找新结点element的位置

if(sentinel.next==null) {

sentinel.next=element; //追加到表尾

this.tailer=element;

break; //结束while循环

}

activeEdgeListEntry mp=sentinel.next; //下一结点

int xmt=mp.topx;

double midDelta=mp.delta;

if((xmt

sentinel=mp; //新结点仍然大于下一结点,当前结点指针后移,继续循环

}

else { //否则,新结点就应该插入当前位置

sentinel.next=element;

element.next=mp;

break; //结束while循环,尾指针不动

}

}

}

else { //新结点作为单链表头结点

sentinel=this.header;

this.header=element;

element.next=sentinel;

}

} //插入新结点结束

//把新结点作为多边形链表的头结点或者尾结点

public void append(activeEdgeListEntry element) {

if(element==null) throw new NullPointerException();

if(tailer==null) { //如果单链表是空

tailer=element;header=element;

}

else { //否则把新结点作为单链表尾结点

tailer.next=element;tailer=element;

}

}

//两个多边形单链表的合并:自身单链表与list单链表的合并public activeEdgeList merge(activeEdgeList list,int y) {

if(list==null) return this;

activeEdgeListEntry a=this.header; //自身单链表的头指针activeEdgeListEntry b=list.header; //单链表list的头指针

activeEdgeListEntry save=null; //指向链表结点的工作指针activeEdgeListEntry anext,bnext; //指向链表结点的工作指针activeEdgeList result=null; //合并结果链表

while(true) {

if(a==null&&b==null) return result; //两个空表

else if(a==null) { //自身为空表

if(save!=null) {

save.next=b;

result.tailer=list.tailer;

return result;

}

}

else if(b==null){ //list为空表

if(save!=null) {

save.next=a;

result.tailer=this.tailer;

return result;

}

}

/*两个表都不空*/

int xa=(int)(a.topx+(a.topy-y)*a.delta); //自身链表

int xb=b.topx; //list链表头结点的topx

if(xa<=xb) { //决定合并后两个表的先后

anext=a.next;

a.next=null;

if(result==null) { //结果链表为空,则a表在前

result=new activeEdgeList(a);

save=result.tailer;

}

else result.append(a); //结果链表不空,则a表在后

save=a;

a=anext;

}

else {

bnext=b.next;

b.next=null;

if(result==null) { //结果链表为空,则b表在前

result=new activeEdgeList(b);

save=result.tailer;

}

else result.append(b); //结果链表不空,则b表在后

save=b;

b=bnext;

}

} //结束while

} //单链表合并结束

//删除多边形单链表的结点

public void remove(activeEdgeListEntry element) {

activeEdgeListEntry p,q;

if(header==element) { //要删除的是头结点

header=element.next;

if(tailer==element) tailer=header;

return;

}

p=q=header;

while(p!=element) {

q=p;p=p.next;

if(p==null) throw new NullPointerException(); //查无此结点}

if(element==tailer) tailer=q; //要删除的是尾结点

q.next=p.next; //要删除的是非头尾结点

}

//多边形单链表的相邻结点

public void traverse() {

activeEdgeListEntry p,q,r,tmp;

p=r=header;

while(p!=null){

q=p.next;

if(q==null) break; //到达末尾

if(q.x

if(p==header) header=q; else r.next=q;

q.next=p;

p.next=tmp;

}

r=p; //指向尾结点

p=p.next; //下一个结点

} //结束while

tailer=r; //多边形单链表新的尾指针

}

} //结束多边形单链表类

//*****定义直线类

class Line {

public double x1,y1;

public double x2,y2;

public Line(double x1,double y1,double x2,double y2) {

this.x1=x1;this.y1=y1;

this.x2=x2;this.y2=y2;

}

} //结束直线类

//***********定义多边形的填充类*******//

public class fillPolygon extends Applet //继承鼠标事件监听接口implements MouseListener,MouseMotionListener {

protected MyCanvas m; //定义MyCanvas的对象

//扫描行处理用数据

protected activeEdgeListEntry[] edgeData=null; //边结点数组

protected activeEdgeList[] bucket=null; //多边形单链表数组

protected activeEdgeList activeHeader=null; //当前边单链表的头指针protected int numEdge=0; //多边形的边数

//鼠标相关数据

protected boolean isFirstClicked=true; //鼠标最初点击

protected boolean isDoubleClicked=false; //双击标志

protected boolean isSingleClicked=false; //单击标志

//绘图区域

protected int width,height; //Applet绘图区的大小

protected Image image=null; //图像区域

protected MemoryImageSource mis=null; //内存图像

protected int[] pixel=null; //内存图像配色数组

protected int pixelWidth; //图像宽度

protected int pixelHeight; //图像高度

protected int xoffset; //pixel数据的窗口内显示偏移量

protected int yoffset;

protected double leftTopx; //pixel数据的起始点

protected double leftTopy;

//多边形的绘图数据

protected double x0,y0; //边的起点

protected double lastx,lasty; //边的终点位置

protected double movingx,movingy; //用户坐标系下一个点的坐标

protected int numPoints=0; //顶点计数器

protected boolean isPolygonMode=true; //标志

protected Vector lines=new Vector(256,256); //Java的向量类

//APPLET程序的初始化

public void init(){

m=new MyCanvas(this); //本APPLET容器的MyCanvas对象

addMouseListener(this); //定义鼠标按钮监听器

addMouseMotionListener(this); //定义鼠标按钮监听器

Dimension d=getSize(); //本APPLET容器的大小

width=d.width; height=d.height;

}

//成员变量初始化

public void initData(){

isFirstClicked=true; //鼠标最初点击

isPolygonMode=true; //标志描绘多边形

numPoints=0; //多边形顶点计数器

bucket=new activeEdgeList[height+1]; //边的单链表数组

for(int i=0;i

if(lines.size()>0) lines.removeAllElements(); //向量类的对象

}

//APPLET程序的绘图

public void paint(Graphics g) {

if(isFirstClicked) { //初始状态

initData();

Font f=m.MyFont(m.getFont().getName(),Font.BOLD+Font.ITALIC,1.5);

m.setFont(f);

m.drawString("单击画多边形",-0.5,0.2);

m.drawString("双击填充多边形",-0.9,-0.15);

}

m.setBackground(new Color(220,220,220)); //背景色

m.setColor(Color.black); //前景色

for(int i=0;i

Line l=(Line)lines.elementAt(i); //转换第i个向量

m.drawLine(l.x1,l.y1,l.x2,l.y2);

}

if(isPolygonMode&&!isFirstClicked) //画线

m.drawLine(lastx,lasty,movingx,movingy);

if((!isPolygonMode)&&(image!=null)) //填充

m.myDrawImage(image,leftTopx,leftTopy,this);

} //APPLET程序的绘图

//把多边形顶点数据生成边结点

public void registerActiveEdgeEntry() {

numEdge=lines.size(); //多边形边的数量

edgeData=new activeEdgeListEntry[numEdge];

for(int i=0;i

edgeData[i]=new activeEdgeListEntry();

/* 四个极值用于确定显示图像的大小和范围*/

int LARGE=0x0ffffffff;

int xmin=LARGE,xmax=-1,ymin=LARGE,ymax=-1;

double dxmin=LARGE,dxmax=-1,dymin=LARGE,dymax=-1;

for(int i=0;i

int ix1=m.getX(l.x1); //将用户坐标的点转换到Java AWT坐标int iy1=height-m.getY(l.y1);

int ix2=m.getX(l.x2);

int iy2=height-m.getY(l.y2);

edgeData[i].topx=0;

edgeData[i].name=i;

edgeData[i].next=null;

if(iy1>iy2) { //边的斜向

edgeData[i].isHorizontal=false;

edgeData[i].topy=iy1;

edgeData[i].topx=ix1;

edgeData[i].x=ix1;

edgeData[i].boty=iy2;

edgeData[i].delta=(double)(-(ix2-ix1))/(iy2-iy1);

if(iy2

ymin=iy2;

dymin=l.y2;

}

if(iy1>ymax) {

ymax=iy1;

dymax=l.y1;

}

}

else if(iy1

edgeData[i].isHorizontal=false;

edgeData[i].topy=iy2;

edgeData[i].topx=ix2;

edgeData[i].x=ix2;

edgeData[i].boty=iy1;

edgeData[i].delta=(double)(-(ix1-ix2))/(iy1-iy2);

if(iy1

ymin=iy1;

dymin=l.y1;

}

if(iy2>ymax) {

ymax=iy2;

dymax=l.y2;

}

}

else { //水平边y1==iy2

edgeData[i].isHorizontal=true;

if(iy1

dymin=l.y1;

}

if(iy1>ymax) {

ymax=iy1;

dymax=l.y1;

}

}

if(ix1

xmin=ix1;

dxmin=l.x1;

}

if(ix2>xmax) {

xmax=ix2;

dxmax=l.x2;

}

}

else if(ix2

if(ix2

xmin=ix2;

dxmin=l.x2;

}

if(ix1>xmax) {

xmax=ix1;

dxmax=l.x1;

}

}

else { //垂直边ix2==ix1

if(ix1

xmin=ix1;

dxmin=l.x1;

}

if(ix1>xmax) {

xmax=ix1;

dxmax=l.x1;

}

}

} //结束for循环

/*内存图像的数组空间及相关数据*/

pixelWidth=xmax-xmin+1;

pixelHeight=ymax-ymin+1;

pixel=new int[pixelWidth*pixelHeight]; //图像的个点颜色

for(int k=0;k

pixel[k]=0x00000000; //初值透明色

xoffset=xmin;yoffset=ymin;

leftTopx=dxmin; //用于显示图像方法myDrawImage();

leftTopy=dymax;

} //生成边结点registerActiveEdgeEntry()

//多边形单链表数组bucketd初始化

public void bucketSort() {

for(int i=0;i

Line l=(Line)lines.elementAt(i); //转换第i个向量

if(edgeData[i].isHorizontal) continue; //水平边不处理

int yt=edgeData[i].topy;

if(bucket[yt]==null) { //该行未建立链表

bucket[yt]=new activeEdgeList(edgeData[i]);

continue;

}

bucket[yt].insert(edgeData[i]); //该行有链表,按顺序插入到链表i } //结束for循环

}

//多边形的扫描转换

public void scanPolygon() {

activeHeader=null; //当前要处理的单链表

for(int y=height-1;y>=0;y--) {

if(bucket[y]!=null) { //该指针元素存在

makeActiveEdgeList(bucket[y],y); //建立该行的边链表

processActiveEdgeList(y); //处理该行的边链表

}

else if(activeHeader!=null&&activeHeader.header!=null)

processActiveEdgeList(y); //处理该行的边链表

} //结束for循环

} //多边形的扫描转换

//处理给定行的边链表

public void processActiveEdgeList(int y) {

int xleft,xright;

double xl,xr;

activeEdgeListEntry left=activeHeader.header;

activeEdgeListEntry right=left.next;

if(right==null) return;

while(true) {

xl=left.x;

xr=right.x;

xleft=(int)xl;

xright=(int)(xr+0.5);

if(xleft<=xright)

fillScanline(xleft,xright,y); //填充y行像素列left.x+=left.delta; //起终点右移一个步长

right.x+=right.delta;

if(left.boty>=y-1 && right.boty>=y-1) {

xleft=(int)left.x;

xright=(int)(right.x+0.5);

if(xleft<=xright)

fillScanline(xleft,xright,y-1); //填充y-1行像素列}

if(left.boty>=y-1) //将左面的边从当前链表中删去

activeHeader.remove(left);

if(right.boty>=y-1) //将左面的边从当前链表中删去

activeHeader.remove(right);

left=right.next; //选择当前链表中下一对结点

if(left==null) break; //到达链表末尾,退出循环

right=left.next;

if(right==null) //边链表的结点数一定为偶数

throw new NullPointerException(); //出错} //结束while

activeHeader.traverse(); //边封闭后,重新整理单链表

} //处理给定行的边链表

//建立指定行的边链表

public void makeActiveEdgeList(activeEdgeList list,int y) { if(activeHeader==null)

activeHeader=list; //指定为当前单链表

else//把list与当前单链表合并

activeHeader=activeHeader.merge(list,y);

}

//填充何种图案

public boolean isTilePattern(int i,int j) {

if( i%8==0 || j%8==0 || i%8==1 || j%8==1 ||

i%8==2 || j%8==2 ) return true; // 填充图案1 return false; // 填充图案2

}

//设定像素颜色

public void putPixel(int i,int j) {

int r,g,b;

if(isTilePattern(i,j))

r=g=b=0; //黑色

else {

r=(int)(Math.random()*255); //0到255之间的随机数

g=(int)(Math.random()*255);

b=(int)(Math.random()*255);

}

int a=0xff000000|(r<<16)|(g<<8)|b; //像素颜色

/*图像的i行j列处的颜色*/

pixel[(pixelHeight-1-(j-yoffset))*pixelWidth+(i-xoffset)]=a;

}

//填充指定行的像素列

public void fillScanline(int xleft,int xright,int y) {

for(int x=xleft;x<=xright;x++)

putPixel(x,y); //调用putPixel(),设定改点像素颜色

}

//------多边形填充总控程序----

public void scanLineFillPolygon() {

registerActiveEdgeEntry(); //生成边结点

bucketSort(); //单链表数组bucketd初始化

scanPolygon(); //多边形的扫描转换

repaint(); //paint绘图

}

//响应鼠标击键事件

public void mousePressed(MouseEvent e) {

int ix=e.getX(); //鼠标的Jawa AWT坐标

int iy=e.getY();

if(isPolygonMode) { //正在进行多边形填充

double x,y; //鼠标的当前位置

if(e.getClickCount()>=2) { //双击,添加多边形的顶点

isDoubleClicked=true; //标记

/* 给光栅向量表增加一行,这个向量成员方法导致编译

要加上参数-Xlint,会出现警告错误*/

lines.addElement(new Line(lastx,lasty,x0,y0));

isPolygonMode=false;

scanLineFillPolygon(); //多边形填充总控程序

if(numEdge>2) { //内存图像生成

mis=new MemoryImageSource(pixelWidth,

pixelHeight,pixel,0,pixelWidth);

image=createImage(mis);

}

}

else { //单击,准备开始

if(isFirstClicked) { //初次点击

isFirstClicked=false;

/*先按照Jawa AWT坐标ix iy得到视图索引号,

再由视图反向转换得到用户坐标系下的lastx lasty*/

lastx=x0=m.getUserX(ix,m.getViewport(ix,iy));

lasty=y0=m.getUserY(iy,m.getViewport(iy,iy));

movingx=lastx; movingy=lasty;

}

else { //非初次点击

/*ix iy所对应的用户坐标系下的坐标*/

x=m.getUserX(ix,m.getViewport(ix,iy));

y=m.getUserY(iy,m.getViewport(iy,iy));

/* 给光栅向量表增加一行*/

lines.addElement(new Line(lastx,lasty,x,y));

lastx=x; lasty=y;

}

numPoints++;

}

repaint(); //paint绘图

} //结束if(isPolygonMode)语句

} //响应鼠标击键事件

//响应鼠标移动事件

public void mouseMoved(MouseEvent e) {

if(!isFirstClicked && isPolygonMode) {

int ix,iy;

ix=e.getX(); //鼠标的Jawa AWT坐标

iy=e.getY();

/*ix iy所对应的用户坐标系下的坐标*/

movingx=m.getUserX(ix,m.getViewport(ix,iy));

movingy=m.getUserY(iy,m.getViewport(ix,iy));

repaint();

}

} //响应鼠标移动事件

//****java语法列出有关鼠标接口中的虚方法

public void mouseClicked(MouseEvent e){}

public void mouseEntered(MouseEvent e){}

public void mouseExited(MouseEvent e){}

public void mouseReleased(MouseEvent e){}

public void mouseDragged(MouseEvent e){}

} //结束多边形填充类

运行结果:

1 多边形的裁剪:

2 多边形的填充:

实验体会:

通过这次的实习报告的编写,我学习了图形变换与裁剪的知识,学习了Sutherland-Cohen 算法的方法原理。多边形的填充主要是扫描知识。在本次实验中,图形的变换按比例来放大缩小,通过转换完成。应用了大量的数学知识,计算机图形学离不开数学。此次实验让我对多边形的裁剪和填充有了一个更加深入的了解。

图形学实验报告

计 算 机 图 形 学 实验指导书 学号:1441901105 姓名:谢卉

实验一:图形的几何变换 实验学时:4学时 实验类型:验证 实验要求:必修 一、实验目的 二维图形的平移、缩放、旋转和投影变换(投影变换可在实验三中实现)等是最基本的图形变换,被广泛用于计算机图形学的各种应用程序中,本实验通过算法分析以及程序设计实验二维的图形变换,以了解变换实现的方法。如可能也可进行裁剪设计。 二、实验内容 掌握平移、缩放、旋转变换的基本原理,理解线段裁剪的算法原理,并通过程序设计实现上述变换。建议采用VC++实现OpenGL程序设计。 三、实验原理、方法和手段 1.图形的平移 在屏幕上显示一个人或其它物体(如图1所示),用交互操作方式使其在屏幕上沿水平和垂直方向移动Tx和Ty,则有 x’=x+Tx y’=y+Ty 其中:x与y为变换前图形中某一点的坐标,x’和y’为变换后图形中该点的坐标。其交互方式可先定义键值,然后操作功能键使其移动。 2.图形的缩放 在屏幕上显示一个帆船(使它生成在右下方),使其相对于屏幕坐标原点缩小s倍(即x方向和y方向均缩小s倍)。则有: x’=x*s y’=y*s 注意:有时图形缩放并不一定相对于原点,而是事先确定一个参考位置。一般情况下,参考点在图形的左下角或中心。设参考点坐标为xf、yf则有变换公式x’=x*Sx+xf*(1-Sx)=xf+(x-xf)*Sx y’=y*Sy+yf*(1-Sy)=yf+(y-yf)*Sy 式中的x与y为变换前图形中某一点的坐标,x’和y’为变换后图形中该点的坐标。当Sx>1和Sy>1时为放大倍数,Sx<1和Sy<1时为缩小倍数(但Sx和Sy

实验一 手工测试报告

淮海工学院计算机工程学院实验报告书 课程名:《软件测试技术》 题目:上机1 手工测试 班级: 学号: 姓名:

上机1 手工测试 一.实验目的 1.找出软件的缺陷,熟悉软件测试后期的测试工作。 2.复习软件测试的确认测试,黑盒测试方法。 二.实验内容 找出鸿飞记事本的20个bug。 三.软件缺陷 1.登陆界面缺陷。某些文字使用淡灰色字体,不够突出,容易被用户忽略。 2.不是第一次登陆并之前修改用户密码之后,仍提示“默认密码为1,登陆后请修 改”;容易对用户产生误导。 3.界面按钮不够清晰、突出,易对用户造成困扰。 4.用户可以一次性修改用户名和密码,造成用户信息安全隐患。 5.皮肤设置时,软件控制按钮会随界面的皮肤设置而改变,一些特殊的皮肤颜色会 掩盖软件控制按钮,尤其是白色皮肤的时候。

自动保存,一旦改变后即使用户觉得没原来的好也就不能取消。 7.软件的使用帮助是互联网的外连接,而软件介绍时说不需要网络即可以使用。一 旦用户没有连接网络而用户又不会使用,此时使用帮助起不到帮助效果。 8.软件使用框架嵌套,大框架的边框颜色不协调且不能修改。 9. 没有告诉用户打开日志的方法。 10.文本的背景颜色过于浓厚会掩盖文本内容

立日志时比它早建立的日志之前。 体设置”按钮修改;有的时候会出现乱码,如图“人”卧倒了。

13.字体大小设置只有1-7七个规格,可选字体大小过少。 14.表格插入有问题。没有插入选项,自动选择三行三列,只能一行、一列的修改, 工作繁琐,尤其是大表格的时候。 15.文本没有撤销功能,如某些文字视频、表格、文档插进去之后不能撤销。 16.正在编写日志时突然退出时,只提示是否退出,并不提示是否保存编写的日志。 17.图片插入后不能删除

多边形区域填充算法

13. 设五边形的五个顶点坐标为(10, 10),(15, 5),(12, 5),(8, 2)和(4, 5),利用多边形区域填充算法,编一程序生成一个实心图。 解:假设以上五个顶点依次对应编号A-B-C-D-E,首先计算得到ET表: 6-10 5 4 3 2 1 该多边形的AET指针的内容为: 1 AET为空 2 3 4 1 2 3 4 5 6 7 8 9 10 01234567891011121314 1516

5 6 7 8 9 10 具体编程实现如下: 第1步:(1) 根据输入的五个顶点坐标找到y 值最小的点(例如点D ,此时y=2),并找到与D 有边关系的两个顶点(此时为E 和C),在y=2处建立ET 边表记录(ymax 、xi 和m 值均可通过顶点坐标间的计算得到,例如DE 边的建立,特别注意:当D 点和E 点y 坐标值相同时,也即是DE 与x 轴平行,该边不能计入ET 边表),之后标记D 点被访问过;(2) 排除访问过的点以及和该点相关联的边,重复(1)直至将ET 表建立完善。 [注]边关系的建立可通过邻接矩阵的数据结构实现,权值可以为该矩阵行编号对应点的y 坐标值,ET 边表采用邻接表的数据结构 第2步:根据ET 表构建AET 表,并逐行完成多边形填充,具体的C++代码如下: (1) 建立头文件base_class.h ,主要是边表结点结构体和ET 边表类的实现 enum ResultCode{Success, Failure}; template struct Enode { Enode() {next=NULL;} Enode(T pymax, float pxi, float pm, Enode *pnext) { ymax=pymax; xi=pxi; m=pm; next=pnext; } T ymax, xi; //ymax 表示最大的y 值,xi 表示最底端点的x 坐标值 float m; //m 表示斜率的倒数 Enode *next; }; //定义了ET 表和AET 表中结点的结构体

计算机图形学实验报告

《计算机图形学》实验报告姓名:郭子玉 学号:2012211632 班级:计算机12-2班 实验地点:逸夫楼507 实验时间:15.04.10 15.04.17

实验一 1 实验目的和要求 理解直线生成的原理;掌握典型直线生成算法;掌握步处理、分析实验数据的能力; 编程实现DDA 算法、Bresenham 中点算法;对于给定起点和终点的直线,分别调用DDA 算法和Bresenham 中点算法进行批量绘制,并记录两种算法的绘制时间;利用excel 等数据分析软件,将试验结果编制成表格,并绘制折线图比较两种算法的性能。 2 实验环境和工具 开发环境:Visual C++ 6.0 实验平台:Experiment_Frame_One (自制平台) 3 实验结果 3.1 程序流程图 (1)DDA 算法 是 否 否 是 是 开始 计算k ,b K<=1 x=x+1;y=y+k; 绘点 x<=X1 y<=Y1 绘点 y=y+1;x=x+1/k; 结束

(2)Mid_Bresenham 算法 是 否 否 是 是 是 否 是 否 开始 计算dx,dy dx>dy D=dx-2*dy 绘点 D<0 y=y+1;D = D + 2*dx - 2*dy; x=x+1; D = D - 2*dy; x=x+1; x

3.2程序代码 //-------------------------算法实现------------------------------// //绘制像素的函数DrawPixel(x, y); (1)DDA算法 void CExperiment_Frame_OneView::DDA(int X0, int Y0, int X1, int Y1) { //----------请实现DDA算法------------// float k, b; float d; k = float(Y1 - Y0)/float(X1 - X0); b = float(X1*Y0 - X0*Y1)/float(X1 - X0); if(fabs(k)<= 1) { if(X0 > X1) { int temp = X0; X0 = X1; X1 = temp; }

常用剪切波波速

常用剪切波 剪切波波速成果图 相关公式编辑 剪切波速测试单孔法 压缩波或剪切波从振源到达测点时间得确定,应符合下列规定: (1)确定压缩波得时间,应采用竖向传感器记录得波形; (2)确定剪切波得时间,应采用水平传感器记录得波形。 压缩波或剪切波从振源到达测点得时间,应按下列公式进行斜距校正: 式中T——压缩波或剪切波从振源到达测点经斜距校正后得时间(s)(相应于波从孔口到达测点得时间); TL ———-压缩波或剪切波从振源到达测点得实测时间(s); K——斜距校正系数; H ——测点得深度(m); H0——振源与孔口得高差(m),当振源低于孔口时,H0为负值; L—-从板中心到测试孔得水平距离(m)。 时距曲线图得绘制,应以深度H为纵坐标,时间T为横坐标。 波速层得划分,应结合地质情况,按时距曲线上具有不同斜率得折线段确定、 每一波速层得压缩波波速或剪切波波速,应按下式计算: 式中V-—波速层得压缩波波速或剪切波波速(m/s); △H——波速层得厚度(m);

△T--压缩波或剪切波传到波速层顶面与底面得时间差(s)。 剪切波速测试跨孔法 压缩波或剪切波从振源到达测点时间得确定,应符合下列规定: (1)确定压缩波得时间,应采用水平传感器记录得波形; (2)确定剪切波得时间,应采用竖向传感器记录得波形。 由振源到达每个测点得距离,应按测斜数据进行计算。 每个测试深度得压缩波波速及剪切波波速,应按下列公式计算: 式中VP——压缩波波速(m/s); VS—-剪切波波速(m/s); TP1——压缩波到达第1个接收孔测点得时间(s); TP2——压缩波到达第2个接收孔测点得时间(s); TS1——剪切波到达第1个接收孔测点得时间(s); TS2—-剪切波到达第2个接收孔测点得时间(s); S1-—由振源到第1个接收孔测点得距离(m) S2——由振源到第2个接收孔测点得距离(m) △S--由振源到两个接收孔测点距离之差(m)、[1] 卓越周期得计算 《高层建筑岩土工程勘察规程JGJ72-2004》条文说明 [2] 规范重点摘录编辑 剪切波速土得类型划分与剪切波速范围

手工焊接实验报告

手工焊接实验报告 篇一:手工焊实训报告 XX大学 手工焊实训总结 年级专业: 学生姓名:学号:指导教师:焊接 XX大学 完成时间: 2012 年月日 1 2 3 4 篇二:手工电弧焊实习报告 学校实习安排

本次实习主要安排在新疆土哈油田建设有限公司进行,以顶班上岗为主,通过实习使学生全面了解企业单位的各方面工作,强化安全意识,规范操作要领,做到安全生产与文明生产。 我在吐哈油建公司实习以有几个月了,公司首先对我门进行了手工焊接的培训,培训期间遇到了很多问题和困难在几个月的时间内体验到当今电焊界普遍所应用的方法,总的来说这次实习活动是一次有趣且必将影响今后学习和工作的重要实践经验。 手工电弧焊是一门实践性的技术课,是学生学习焊接技术工艺方法和技术,完成工程基本训练的重要必修课。实习不仅可以让我们获得焊接的基础知识,了解焊接的一般操作,而且还可以提高自己的焊接技能和动手能力,而且加强了理论联系实际的锻炼,提高了我们的实践能力,培养了我们的素质。实习是一次我们学习、锻炼的好机会。通

过这次几个月充实的实习我懂得了很多……… 在这几个月内,大家每天都要加强学习焊接技术,并在很短的实习时间里,完成从对各项焊工作业的过程,我们在老师们耐心细致地指导下,很顺利的完成各自的实习内容,并且基本上都达到了老师预期的实习要求,圆满地完成了实习。在实习期间,通过学习焊接的操作,我们做出了自己的工件,虽然这几个月的焊接实习是对我们的一个很大的考验,我们都喜不自禁,感到很有成就感。 在实习中,安全是第一位,这是每个老师给我们的第一忠告。实习是培养学生实践能力的有效途径,又是我们工科类大学生非常重要的也特别有意义的实习课,也是我们一次,离开课堂严谨的环境,感受到车间的气氛,亲手掌握知识的机会。 实习要求

图形学实验报告

山东建筑大学测绘地理信息学院 实验报告 (2016—2017学年第一学期) 课程:计算机图形学 专业:地理信息科学 班级:地信141 学生姓名:王俊凝 学号:20140113010 指

实验一直线生成算法设计 一、实验目的 掌握基本图形元素直线的生成算法,利用编程语言C分别实现直线和圆的绘制算法。 二、实验任务 在TurboC环境下开发出绘制直线和圆的程序。 三、实验仪器设备 计算机。 四、实验方法与步骤 1 运行TurboC编程环境。 2 编写Bresenham直线绘制算法的函数并进行测试。 3 编写中点圆绘制算法的函数并进行测试。 4 增加函数参数,实现直线颜色的设置。 提示: 1. 编程时可分别针对直线和圆的绘制算法,设计相应的函数,例如void drawline(…)和void drawcircle(…),直线的两个端点可作为drawline的参数,圆的圆心和半径可作为drawcircle的参数。 2. 使用C语言编写一个结构体类型用来表示一个点,结构体由两个成员构成,x和y。这样,在向函数传入参数时,可使用两个点类型来传参。定义方法为:

typedef struct{ int x; int y; }pt2; 此处,pt2就是定义的一个新的结构体数据类型,之后就可用pt2来定义其他变量,具体用法见程序模板。 3. 在main函数中,分别调用以上函数,并传入不同的参数,实现对直线的绘制。 4. 线的颜色也可作为参数传入,参数可采用TurboC语言中的预设颜色值,具体参见TurboC图形函数。 五、注意事项 1 代码要求正确运行,直线和圆的位置应当为参数,实现可配置。 2 程序提交.c源文件,函数前和关键代码中增加注释。 程序模板 #include #include typedef struct{ int x; int y; }pt2; /*declare your drawing functions.*/ void drawline(pt2 startpt,pt2 endpt,int color); void drawcircle(pt2 centerpt,int radius,int color); void circlePlotPoints(pt2 centerpt,int x,int y,int color); int main() { int color,radius;

计算机模拟手工实验报告

计算机模拟手工实验 学生实验报告 学院:商学院 课程名称:计算机模拟手工实验 专业班级: 姓名: 学号:

学生实验报告 第一部分:实验概况与内容 一、实验的目的及要求 1、实验目的 本实验以模拟企业的实际会计工作为基础,按照企业会计制度和企业会计准则的要求,进行操作训练,有目的地检验和复习所学的会计理论、方法、技能和技巧通过实际的操作,使我们能够比较系统、全面地掌握工业企业会计核算的基本程序和具体方法,加强我们对会计基本理论的理解和对会计基本技能的掌握,把枯燥、抽象的书本知识转化为实际、具体的操作,使我们能够形象地掌握各种业务的处理及记账凭证的填写方法,掌握账簿的处理及登记方法,掌握成本核算方法,掌握各种报表的编制方法,掌握会计资料的整理归档方法,同时,我们可以体验在不同岗位进行不同操作,使之在实验中,培养职业道德和职业判断能力,提高职业工作能力,为我们今后从事会计实务工作打下扎实的基础。 2、实验要求 ①熟悉会计工作的基本流程,工作内容以及工作规范等基础知识; ②能够熟练的进行对实验企业所发生各经济业务的会计核算和账务处理; ③掌握实验企业建立账户、填制凭证,登记账簿、编制报表等会计实务操作流程。 二、实验内容 1、企业基本情况 津阳市永安公司是批零兼营的以零售为主的商品流通企业,主要经营五金、百货、家电等商品,分设一部四柜组,其中一部为批发部,四柜组为小百货组、五金家电组、鞋帽组、针织服装组。

开户行及账号:中国工商银行贵溪分理处 5189958。 地址:津阳市盛兴路160号。 经营规模:一般纳税人,适用增值税税率为17%。 纳税人识别号:235678902283156。 所得税税率:25% 2、内部主要财务会计制度 (1)批发商品流转业务核算的有关规定和要求: ①库存商品采用数量进价金额核算法,按商品品名开设明细账进行数量进价金额核算。 ②“商品销售收入”、“商品销售成本”账户按批发设置明细账,以便结转成本。 ③商品销售使用增值税专用发票,税率为17%。 ④商品销售成本本月末采用先进先出法,在“库存商品——批发”账户中倒算并结转成本。平时只填制出库单。 (2)零售商品流转业务核算的有关规定和要求: ①库存商品采用售价金额核算法,“库存商品”账户按零售分设小百货组、五金家电组、鞋帽组、针织服装组分户进行明细核算。 ②“商品销售收入”、“商品销售成本”账户按批发设置明细账,以便结转成本。 ③商品销售使用增值税专用发票,税率为17%。 ④商品销售实行“价税合一”、平时“商品销售收入”反映含税(增值税、下同)销售额,月末按下列公式调整为不含税销售额,以此计算冲销已销商品收入所含的增值税(进项税额)。不含税销售额=含税销售额/ (1+增值税税率) ⑤商品销售成本按含税销售额随销随转办法,注销书屋负责人的经济责任。 ⑥“商品进销差价”账户反映含税售价与不含说进价之差的数额,并按前述四柜组分别核算。 ⑦月末,按分类(柜组)差价率计算法计算并分摊已销商品实现的进销差价。(3)本公司采用的是非定额的备用金制度 3.实验过程

多边形填充

计算机图形学实验报告 班级: 学号:

姓名:

实验三多边形填充 一实验目的 1)掌握多边形的有效边表填充算法; 2)掌握边界像素处理原则; 3)掌握菱形图形的填充方法。 二实验要求 1)设计实现多边形填充类,可以设置顶点序列,调用填充函 数。 2)多边形填充采用有效边表填充算法进行实现,通过建立多 边形的桶表和边表数据,按照算法步骤依次扫描填充;3)调用设计实现的多边形填充类,对菱形线框进行颜色填充。三实验步骤 第1步:创建MFC应用程序框架 参照第一章的步骤建立空的MFC应用程序框架。 第2步:设计实现直线绘制类 设计实现多边形填充类 1)有效边表填充算法原理 在多边形填充过程中,常采用:“下闭上开”和“左闭右开”的原则对边界像素进行处理。有效边表填充算法通过维护“桶表和边表”数据,节省了有效数据存储空间,避免了扫描线与多

边形所有边求交的运算耗时。 图1 边表结点数据结构 有效边表填充算法实现步骤为: a)根据多边形的顶点序列,建立其“桶表和边表”数据。b)按照扫描线从小到大的移动顺序,取出当前扫描线对应桶的边表数据。 c)如果“桶表”数据已经取完,则填充结束;否则,继续后续填充操作。 d)将当前桶里的边表数据加入到有效边表,根据“下闭上开”的原则,删除已经到y max的无效边。 e)对当前扫描线的有效边表按x值递增的顺序进行排序、配对,以确定填充区间;根据“左闭右开”的原则,对两两配对的填充空间进行像素填充。 f)继续回到步骤b。 1)新建多边形填充类CFillPoly头文件

首先声明二维点类“CP2”、边表类“CAET”和桶表类“CBucket”,用于存储和传递多边形“桶表和边表”数据。多边形填充类中主要包括存放多边形顶点数据、有效边表结点指针和桶表结点指针的成员变量,以及创建桶表、边表、有效边表排序和填充多边形等成员函数。“FillPoly.h”头文件中具体类型声明代码如下: #pragma once class CP2 { public: CP2 (); virtual~CP2 (); CP2 (double,int);

计算机图形学 有效边表填充算法实验报告

实验题目:实验二有效边表填充算法 1.实验目的: 设计有效边表结点和边表结点数据结构 设计有效边表填充算法 编程实现有效边表填充算法 2.实验描述: 下图1 所示多边形覆盖了12 条扫描线,共有7 个顶点和7 条边。7 个顶点分别为:P0(7,8),P1(3,12),P2(1,7),P3(3,1), P4(6,5), P5(8,1), P6(12,9)。在1024×768 的显示分辩率下,将多边形顶点放大为P0(500,400),P1(350,600),P2(250,350),P3(350,50), P4(500,250), P5(600,50), P6(800,450)。请使用有效边表算法填充该多边形。 图1示例多边形

图2 屏幕显示多边形 3.算法设计: (1)建立AET和BUCKET类; (2)初始化桶,并在建立桶结点时为其表示的扫描线初始化为带头结点的链表; (3)对每个桶结点进行循环,将桶内每个结点的边表合并为有效边表,并进行有效边表循环; (4)按照扫描线从小到大的移动顺序,计算当前扫描线与多边形各边的交点,然后把这些交点按X值递增的顺序进行排序,配对,以确定填充区间; (5)用指定颜色点亮填充区间内的所有像素,即完成填充工作。 4.源程序: 1)//AET.h class AET { public: AET(); virtual ~AET(); double x; int yMax; double k;//代替1/k AET *next; }; //AET..cpp AET::AET() {

} AET::~AET() { } 2) //Bucket.h #include "AET.h" class Bucket { public: Bucket(); virtual ~Bucket(); int ScanLine; AET *p;//桶上的边表指针 Bucket *next; }; // Bucket.cpp Bucket::Bucket() { } Bucket::~Bucket() { } 3)//TestView.h #include "AET.h"//包含有效边表类 #include "Bucket.h"//包含桶类 #define Number 7//N为闭合多边形顶点数,顶点存放在整型二维数组Point[N]中class CTestView : public CView { 。。。。。。。。。 public: void PolygonFill();//上闭下开填充多边形 void CreatBucket();//建立桶结点桶 void Et();//构造边表 void AddEdge(AET *);//将边插入AET表 void EdgeOrder();//对AET表进行排序

常用剪切波波速

常用剪切波波速 集团文件发布号:(9816-UATWW-MWUB-WUNN-INNUL-DQQTY-

相关公式 剪切波速测试单孔法 压缩波或剪切波从振源到达测点时间的确定,应符合下列规定: (1)确定压缩波的时间,应采用竖向传感器记录的波形; (2)确定剪切波的时间,应采用水平传感器记录的波形。 压缩波或剪切波从振源到达测点的时间,应按下列公式进行斜距校正: 式中T——压缩波或剪切波从振源到达测点经斜距校正后的时间(s)(相应于波从孔口到达测点的时间); TL————压缩波或剪切波从振源到达测点的实测时间(s); K——斜距校正系数; H——测点的深度(m); H0——振源与孔口的高差(m),当振源低于孔口时,H0为负值; L——从板中心到测试孔的水平距离(m)。 时距曲线图的绘制,应以深度H为纵坐标,时间T为横坐标。 波速层的划分,应结合地质情况,按时距曲线上具有不同斜率的折线段确定。 每一波速层的压缩波波速或剪切波波速,应按下式计算: 式中V——波速层的压缩波波速或剪切波波速(m/s); △H——波速层的厚度(m); △T——压缩波或剪切波传到波速层顶面和底面的时间差(s)。

剪切波速测试跨孔法 压缩波或剪切波从振源到达测点时间的确定,应符合下列规定: (1)确定压缩波的时间,应采用水平传感器记录的波形; (2)确定剪切波的时间,应采用竖向传感器记录的波形。 由振源到达每个测点的距离,应按测斜数据进行计算。 每个测试深度的压缩波波速及剪切波波速,应按下列公式计算: 式中VP——压缩波波速(m/s); VS——剪切波波速(m/s); TP1——压缩波到达第1个接收孔测点的时间(s); TP2——压缩波到达第2个接收孔测点的时间(s); TS1——剪切波到达第1个接收孔测点的时间(s); TS2——剪切波到达第2个接收孔测点的时间(s); S1——由振源到第1个接收孔测点的距离(m) S2——由振源到第2个接收孔测点的距离(m) △S——由振源到两个接收孔测点距离之差(m)。[1]卓越周期的计算 《高层建筑岩土工程勘察规程JGJ72-2004》条文说明 [2] 规范重点摘录 剪切波速土的类型划分和剪切波速范围

手工香皂 实验报告 朱琳 1131592007

开放性实验报告 实验名称手工香皂(红酒香皂)的制作学院艺术设计学院 专业班产品设计131 姓名朱琳 学号1131592007 同组实验者丁佳杰din jia jie 实验日期2015.4.——2015.6. 指导教师李惠

一、实验目的 1.学习制作手工香皂的方法。 2.掌握皂化反应原理,并将它运用到实践。 二、实验原理 香皂是一种最普遍和最广泛使用的个人洗涤用品。香皂制作的主要反应是皂化反应,皂化反应是碱催化下的酯水解反应,尤其指的是油脂的水解。狭义地讲,皂化反应仅限于油脂与氢氧化钠混合,得到高级脂肪酸的钠盐和甘油的反应(还有部分水)。这个反应是制造肥皂流程中的一步,因此而得名。 皂化反应是一个放热反应。它是一个较慢的化学反应,为了加快反应速率,可以在化学反应的过程中保持系统的较高温度,用物理方式不断搅拌溶液以增加分子碰撞的数量。 脂肪和植物油的主要成分是甘油三酯,它们在碱性条件下水解的方程式为: CH2COOR CH2OH | | CHCOOR + 3 NaOH → 3 RCOONa + CHOH | | CH2COOR CH2OH R基可能不同,但生成的R-COONa都可以做肥皂。常见的R基有:十七碳烯基。R-COOH为油酸。 正十五烷基。R-COOH为软脂酸。 正十七烷基。R-COOH为硬脂酸。 香皂的制作方法大致可以分为热制法和冷制法。热制法属于持续性地加热成形,它的好处是制皂时间较短,约2个小时即可完成,缺点是部分营养都在持续性的高温下被破坏了。而冷制法的好处是可以保留大多数的营养,但缺点是制作时间非常长,最少必须等待3--8周以上才可以完成。 通常市售的普通香皂大多数采用热制法制作,在制皂的过程中会产生甘油,一般会将甘油提取出来,并添加一些化学物质与防腐剂等,所以使用后常常会将肌肤的天然油脂一起带走。而手工香皂大多数采取天然的植物油及其他天然原料,再加上不提取甘油,相对而言,不仅健康,而且滋润肌肤的效果更是普通香皂无法比拟的。手工香皂的制作过程之中没有添加清洁的人工化学物质,因此手工香皂遇到水之后,大约24小时以内就会被完全中和分解掉,所以并不会造成生态环境的破坏。 本实验采取冷制法制备手工红酒香皂。

计算机图形学 多边形裁剪与填充 计算机图形学课程设计

课程设计报告 课程名称计算机图形学 课题名称多边形裁剪与填充 专业计算机科学与技术 班级计算机0902 学号 姓名 指导教师刘长松曹燚 2012年10 月9 日

湖南工程学院 课程设计任务书 课程名称计算机图形学课题多边形裁剪与填充 专业班级计算机0902 学生姓名 学号 指导老师刘长松曹燚 审批 任务书下达日期2012年9月15 日 任务完成日期2012 年10月9 日

一、设计内容与设计要求 1.设计内容: 交互式地实现多边形的裁剪和填充。。 2.设计要求: 1)窗口功能设计。 2)实现鼠标画多边形与数据存储功能。 3)实现鼠标剪裁窗口选择功能。 4)实现多边形裁剪和填充功能。 3.算法提示: 多边形裁剪算法分析: 基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,该线把平面分成两个部分:可见一侧,不可见一侧。用一条裁剪边对多边形进行裁剪,得到一个顶点序列,作为下一条裁剪边处理过程的输入点。 对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。 多边形填充算法分析: 确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin 和ymax),从y=ymin 到 y=ymax, 每次用一条扫描进行填充。对一条扫描线填充的过程可分为四个步骤: a.求交b.排序c.交点配对d.区间填色。 二、进度安排 第 3 周星期一8:00——12:00 星期二8:00——12:00 星期三8:00——12:00 星期四8:00——12:00 星期五8:00——12:00 第 4 周星期一8:00——12:00 附: 课程设计报告装订顺序:封面、任务书、目录、正文、附件(A4大小的图纸及程序清单)、评分。正文的格式:一级标题用3号黑体,二级标题用四号宋体加粗,正文用小四号宋体;行距为22。 正文的内容:一、课题的主要功能;二、课题的功能模块的划分(要求画出模块图);三、主要功能的实现(至少要有一个主要模块的流程图);四、程序调试;五、总结;六、附件(所有程序的原代码,要求对程序写出必要的注释)。 正文总字数要求在5000字以上(不含程序原代码)。

数字图像处理实验报告

数字图像处理实验报告 实验一数字图像基本操作及灰度调整 一、实验目的 1)掌握读、写图像的基本方法。 2)掌握MATLAB语言中图像数据与信息的读取方法。 3)理解图像灰度变换处理在图像增强的作用。 4)掌握绘制灰度直方图的方法,理解灰度直方图的灰度变换及均衡化的方 法。 二、实验内容与要求 1.熟悉MATLAB语言中对图像数据读取,显示等基本函数 特别需要熟悉下列命令:熟悉imread()函数、imwrite()函数、size()函数、Subplot()函数、Figure()函数。 1)将MATLAB目录下work文件夹中的forest.tif图像文件读出.用到imread, imfinfo 等文件,观察一下图像数据,了解一下数字图像在MATLAB中的处理就是处理一个矩阵。将这个图像显示出来(用imshow)。尝试修改map颜色矩阵的值,再将图像显示出来,观察图像颜色的变化。 2)将MATLAB目录下work文件夹中的b747.jpg图像文件读出,用rgb2gray() 将其 转化为灰度图像,记为变量B。 2.图像灰度变换处理在图像增强的作用 读入不同情况的图像,请自己编程和调用Matlab函数用常用灰度变换函数对输入图像进行灰度变换,比较相应的处理效果。 3.绘制图像灰度直方图的方法,对图像进行均衡化处理 请自己编程和调用Matlab函数完成如下实验。 1)显示B的图像及灰度直方图,可以发现其灰度值集中在一段区域,用 imadjust函 数将它的灰度值调整到[0,1]之间,并观察调整后的图像与原图像的差别,调整后的灰

度直方图与原灰度直方图的区别。 2) 对B 进行直方图均衡化处理,试比较与源图的异同。 3) 对B 进行如图所示的分段线形变换处理,试比较与直方图均衡化处理的异同。 图1.1 分段线性变换函数 三、实验原理与算法分析 1. 灰度变换 灰度变换是图像增强的一种重要手段,它常用于改变图象的灰度范围及分布,是图象数字化及图象显示的重要工具。 1) 图像反转 灰度级范围为[0, L-1]的图像反转可由下式获得 r L s --=1 2) 对数运算:有时原图的动态范围太大,超出某些显示设备的允许动态范围, 如直接使用原图,则一部分细节可能丢失。解决的方法是对原图进行灰度压缩,如对数变换: s = c log(1 + r ),c 为常数,r ≥ 0 3) 幂次变换: 0,0,≥≥=γγc cr s 4) 对比拉伸:在实际应用中,为了突出图像中感兴趣的研究对象,常常要求 局部扩展拉伸某一范围的灰度值,或对不同范围的灰度值进行不同的拉伸处理,即分段线性拉伸: 其对应的数学表达式为:

剪切波报告汇总

道真自治县道真中学第二食堂单孔法Ps波速度检层测试报告 工程名称:道真自治县道真中学第二食堂 测试地点:工地现场 测试日期:2016年9月 勘察单位:贵州鼎盛岩土工程有限公司 证书等级:工程勘察专业类甲级 证书编号:B152004778-6/4 提交日期: 2016年9月

道真自治县道真中学第二食堂单孔法Ps波速度检层测试报告 项目负责:陈简 报告编写:罗仿超 审核:姚本焱 审定:曾昭涤 总工程师:秦启明 总经理:袁万骅 勘察单位:贵州鼎盛岩土工程有限公司 证书等级:工程勘察专业类甲级 证书编号:B152004778-6/4 提交日期: 2016年9月

目录 一、工程概况 二、场地工程地质简况及测试条件 1、场地工程地质简况 2、场地岩土体的微振动、Vs波特征及测试条件 三、仪器选用及测试方法 (一)仪器选用 (二)测试方法 四、测试分析结果 1、动弹性参数的计算 2、土层等效剪切波(Vse)的计算 3、场地类别划分 4、测试分析结果 五、结论 附件 1、单孔波速测试测点原始数据表 2、单孔波速测试测点计算数据表 3、单孔波速测试分层结果数据表 一、工程概况

拟建道真自治县道真中学第二食堂位于道真县城,交通便利,地理位置优越。受打钻自治县道真中学的委托,我公司测试人员于2016年8月对该场地具有代表性的2个勘探钻孔进行了Ps波测试(测试位置见钻孔平面布置图),其主要目的为: 1、测试纵、横波在钻孔土体的传播速度; 2、利用Vs、Vp值计算场地土体的小应变条件下的动弹参数,以供设计参考; 3、利用场地剪切波(Vs波)的等效波速值(Vse),对场地土的类型进行划分,进而对场地类别进行划分: 测试过程及资料处理的技术依据为: 《岩土工程勘察规范》(GB50021-2001)2009年版; 《工程岩体试验方法标准》(GB/T50266-99); 《建筑抗震设计规范》(GB50011—2010); 《地基动力特性测试规范》(GB/T50269-97); 《水电水利工程物探规程》(DL/T5010-2005); 《水利水电工程物探规程》(SL/326-2005)等。 二、场地工程地质简况及测试条件 1、场地工程地质简况 根据地质调查和钻探揭露,场地覆盖土层有素填土(Q4ml)红粘土(Q4el),下伏基岩为三叠系下统茅草铺组(T1m)石灰岩,岩层倾向100°,倾角8°。 2、场地岩土体的微振动、Vs波特征及测试条件 按《建筑抗震设计规范》(GB50011—2010),一般情况下,应按地面至剪切波速大于500 m/s,且其下卧各岩土的剪切波速均不小于500 m/s的土层顶面距离确定。 场地局部地段回填土结构较松散,对激发的应力波有较强的衰减和吸收作用,附近的车辆和施工作业也对测试数据带来一定的干扰,在资料分析过程中,通过调整信号增益和对信号进行滤波分析处理。 三、仪器选用及测试方法

计算机图形学实验报告 (2)

中南大学信息科学与工程学院 实验报告实验名称 实验地点科技楼四楼 实验日期2014年6月 指导教师 学生班级 学生姓名 学生学号 提交日期2014年6月

实验一Window图形编程基础 一、实验类型:验证型实验 二、实验目的 1、熟练使用实验主要开发平台VC6.0; 2、掌握如何在编译平台下编辑、编译、连接和运行一个简单的Windows图形应用程序; 3、掌握Window图形编程的基本方法; 4、学会使用基本绘图函数和Window GDI对象; 三、实验内容 创建基于MFC的Single Document应用程序(Win32应用程序也可,同学们可根据自己的喜好决定),程序可以实现以下要求: 1、用户可以通过菜单选择绘图颜色; 2、用户点击菜单选择绘图形状时,能在视图中绘制指定形状的图形; 四、实验要求与指导 1、建立名为“颜色”的菜单,该菜单下有四个菜单项:红、绿、蓝、黄。用户通过点击不同的菜单项,可以选择不同的颜色进行绘图。 2、建立名为“绘图”的菜单,该菜单下有三个菜单项:直线、曲线、矩形 其中“曲线”项有级联菜单,包括:圆、椭圆。 3、用户通过点击“绘图”中不同的菜单项,弹出对话框,让用户输入绘图位置,在指定位置进行绘图。

五、实验结果: 六、实验主要代码 1、画直线:CClientDC *m_pDC;再在OnDraw函数里给变量初始化m_pDC=new CClientDC(this); 在OnDraw函数中添加: m_pDC=new CClientDC(this); m_pDC->MoveTo(10,10); m_pDC->LineTo(100,100); m_pDC->SetPixel(100,200,RGB(0,0,0)); m_pDC->TextOut(100,100); 2、画圆: void CMyCG::LineDDA2(int xa, int ya, int xb, int yb, CDC *pDC) { int dx = xb - xa; int dy = yb - ya; int Steps, k; float xIncrement,yIncrement; float x = xa,y= ya; if(abs(dx)>abs(dy))

剪切波速汇报

剪切波速 剪切波速是区别土动力学和土静力学的一个主要物理量。它反映了土在动力影响下的惯性作用和波传行为。因此也是反映土体在地震作用下行为反应的一个重要物理量。土层的剪切波速Vs只与组成土层的骨架的性质有关, 而与孔隙中的充填物无关, 这是由剪切波的运动特点所决定的, 剪切波是由介质的质点垂直于传播方向的振动形式向前运动的,即后一个质点的振动是由前一个质点的振动产生的剪切作用力所推的。剪切波的这一传播特性决定了它不能在气体或液体中传播, 因此, 剪切波速Vs与介性中是否含有气体或液体无关, 而只与土层骨架的性质有关。土层的骨架性质变化是一个漫长的缓慢的渐变过程, 其性质是相对稳定的。对于一种特定的土层而言, 它有比较稳定的剪切波速值, 它几乎不受时间及自然条件的影响。所以, 剪切波速是衡量土层物理力学性质的一项硬指标。 在工程试验中,通常假定所试验的土层位均匀土层,或者各层均匀土体,在这种土体中,远离任何边界的波动,存在两种基本莫泰:压缩波(P波)和剪切波(S波),他们的传播速度取决于弹性介质的刚度和质量密度,即: V p=M = E1?υ (1)V s= G ρ(2) 其中ρ为土体质量密度,M、G和E分别是约束、剪切模量和杨氏模量,υ为泊松比。 而在均质各向同性线弹性材料具有独特的弹性性质,因此知道弹性模量中的任意两种,就可由换算公式求出其他所有的弹性模量,由以上两公式知,我们以杨氏模量E和泊松比υ为变量,那么剪切模量G就可以表示为: G= E 2(1+υ)(3) 那么(2)式可变为: V s=E1 (4) 对比(1)式和(4)式,压缩波(P波)波速V p和和剪切波(S波)波速V s有公共因子 Eρ,因此归一化后,可得压缩波(P波)波速V p和和剪切波(S波)波速V s随泊松比变化的趋势图(图1),土层泊松比的取值范围是0.3~0.5。

手工帐实训报告

报告一: 《会计模拟实习》实验报告 授课实验室:会计实验室授课地点: 授课单位:会计系指导老师: 报告二: 模拟会计实训报告 一模拟会计目的 会计是企业最主要,最基本的一种工具,是一种最主要,最普及的商业语言。是加强经济管理,提高经济效益的重要手段,经济管理离不开会计,经济越发展会计工作就显得越重要。我们在学校只是学到会计的基础理论知识,缺乏会计理论在企业实践的经验。学校开展的模拟实训课,对我们即将毕业的学生来说极其重要。同其他理论一样,会计理论来自实践,同时又能够对实践进行指导。学生通过对企业模拟实训,加强对所学的会计理论知识的理解与认识,完成理论到实践的认知过程。理论与实践是密相连的,只有把书本上学到的理论知识应用到实际的会计实务操作真正掌握这门知识。学校实训的目的就是提高我们的能力和加强我们的职业道德精神。 二模拟会计实训的主要内容 手工账的主要内容有:填制原始凭证,设置账户,编制会计分录,填制记账凭证,编制记账凭证科目汇总表、总分类账、明细分类账、数量账,账项调整,对账,结账,编制会计报表。 电子账的主要内容有:1、建立账套,增加用户,设置权限,设置基础档案,填制记账凭证,填制报表,审核凭证,自动转账定义。2、建立工资账套,定义计算公式,工资分摊。3、建立固定资产系统,控制参数,录入固定资产原始卡片。 三模拟实训要求 (一)手工账实训要求 1根据2006年12月份的实际经济业务填制原始凭证。 2根据审核无误的原始凭证填制记账凭证。 3将记账凭证所记载的有关账户金额登记到相应的日记账,明细账。 4根据12月份的全部记账凭证编制记账凭证科目汇总表。 5根据记账凭证科目汇总表登记总分类账薄。 6根据总分类账期末余额填制资产负债表,并试算平衡。 7结算本年利润,填制利润分配表。 (二)电子账实训要求 1、根据企业信息建立账套。 2、根据操作员的岗位设置权限,进行账务分工。 3、根据规定2002年12月份的实际经济业务,填制原始凭证。 4、进行银行对账 5、根据基础信息建立工资账套。 6、根据工资项目定义公式。 7、根据计税基数代扣个人所得税。 8、根据固定资产资料,录入固定资产原始卡片。 四实训的基本流程 (一)手工账的基本流程 首先对取得或自制的原始凭证进行合规性审核、完整性审核、技术性审核,然后以经济业务发生而引起会计要素增减变动来设置账户编制记账凭证。根据有关记账凭证逐日逐笔的

《计算机图形学实验报告》

一、实验目的 1、掌握中点Bresenham直线扫描转换算法的思想。 2掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。 3掌握透视投影变换的数学原理和三维坐标系中几何图形到二维图形的观察流程。 4掌握三维形体在计算机中的构造及表示方法 二、实验环境 Windows系统, VC6.0。 三、实验步骤 1、给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描转换算法画出连接两点的直线。 实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下: void DrawLine(CDC *pDC, int p0x, int p0y, int p1x, int p1y); 在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。 COLORREF SetPixel(int x, int y, COLORREF crColor ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine 函数画出不同斜率情况的直线,如下图:

最后、调试程序直至正确画出直线。 2、给定多边形的顶点的坐标P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)…使用边标志算法或有效边表算法进行多边形填充。 实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、实现边标志算法或有效边表算法函数,如下: void FillPolygon(CDC *pDC, int px[], int py[], int ptnumb); px:该数组用来表示每个顶点的x坐标 py :该数组用来表示每个顶点的y坐标 ptnumb:表示顶点个数 注意实现函数FillPolygon可以直接通过窗口的DC(设备描述符)来进行多边形填充,不需要使用帧缓冲存储。(边标志算法)首先用画线函数勾画出多边形,再针对每条扫描线,从左至右依次判断当前像素的颜色是否勾画的边界色,是就开始填充后面的像素直至再碰到边界像素。注意对顶点要做特殊处理。 通过调用GDI画点函数SetPixel来画出填充过程中的每个点。需要画线可以使用CDC的画线函数MoveTo和LineTo进行绘制,也可以使用实验一实现的画直线函数。 CPoint MoveTo(int x, int y ); BOOL LineTo(int x, int y ); 实现边标志算法算法需要获取某个点的当前颜色值,可以使用CDC的成员函数 COLORREF GetPixel(int x, int y ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用FillPolygon 函数画出填充的多边形,如下: void CTestView::OnDraw(CDC* pDC) { CTestcoodtransDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);

相关文档
相关文档 最新文档