LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 912|回复: 3

X window(上机作业)

[复制链接]
发表于 2006-4-29 21:40:20 | 显示全部楼层 |阅读模式
计算机图形学上机作业:
1.        输入三角形的三个顶点坐标,在屏幕上画出三角形。 画线子程序可以采用中点画线或Bresenham画线算法。
2.        输入圆心、半径 ,在屏幕上利用Bresenham画园算法画出该园。
注:输入可以在屏幕上直接确定 点,或用键盘输入坐标值。画线和画园的过程要加延时,以便观察是在画点。
3 .        对屏幕上所画图形进行拾取。可以用鼠标或键盘控制拾取。
4.        对拾取的图形进行比例、平移和旋转变换。比例系数可以由键盘输入,平移可以 由键盘或鼠标控制。旋转角度可以由键盘输入或鼠标控制。
5.        对比例 、平移和旋转后的图形用任意非边界色进行填充。

我刚刚做完了前两个,可是有些问题,初学xlib,好多地方还不了解只是照猫画虎。我把第2个Bresenham画园算法代码贴到下边:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#define DUMP_ERR printf

static void draw(Display *display,Window win,GC gc,int width,int height,int x0,int y0,double r);

int main()
{
Display *display;
int screennum;
int width;
int height;
Atom protocols;

Window win;
GC gc;

display = XOpenDisplay(NULL);
if( !display )
{
DUMP_ERR("call XOpenDisplay(%s) fail\n",XDisplayName(NULL));
return 1;
}

// get default screen
screennum = DefaultScreen(display);
width = DisplayWidth(display,screennum)/2;
height = DisplayHeight(display,screennum)/2;

// create window
win = XCreateSimpleWindow(display,RootWindow(display,screennum),0,0,width,height,3,BlackPixel(display,screennum),WhitePixel(display,screennum));

//增加这个代码是捕获程序退出事件
protocols = XInternAtom(display, "WM_DELETE_WINDOW", True);
XSetWMProtocols(display, win, &protocols, 1);

// select event
XSelectInput(display,win,ExposureMask|ButtonPressMask|ButtonReleaseMask|StructureNotifyMask);

// create gc
{
unsigned long valuemask = 0;
XGCValues values;
gc = XCreateGC(display,win,valuemask,&values);
}

// show window
XMapWindow(display,win);

int x0,y0;
double r;
/***                                  //注意这里的注释^_^
printf("\nthe center of the circle(x,y):");
scanf("%d%d",&x0,&y0);
printf("\nthe radius of the circle(r):");
scanf("%f",&r);
***/
// event loop
while(1)
{
XEvent event;
XNextEvent(display,&event);

switch(event.type)
{
  case Expose: // expose window
    if( event.xexpose.count != 0) break;
  /*                       //再注意这里的注释^_^
   printf("\nthe center of the circle(x,y):");
   scanf("%d%d",&x0,&y0);
   printf("\nthe radius of the circle(r):");
   scanf("%f",&r);
  */
   draw(display,win,gc,width,height,200,200,100);
  break;

  case ConfigureNotify: // when the window’s size change
      width = event.xconfigure.width;
      height = event.xconfigure.height;
      draw(display,win,gc,width,height,200,200,100);
  break;

  case ClientMessage :
    if(event.xclient.data.l[0] == protocols)
    {
     DUMP_ERR("recv destroy notify\n");
     XFreeGC(display,gc);
     XDestroyWindow(display, win);
     XCloseDisplay(display);
     return 0;
    }
  default:  break;
  }//switch
}//while
return 0;
}//main

// 使用changeGC修改属性的代码 只有valuemask被设置的属性才会根据XCGValues里面的值进行修改
static void set_gc_values(Display *display,GC gc)
{
XGCValues values;
values.line_width = 2;
values.line_style = LineSolid;
values.cap_style = CapRound;
values.join_style = JoinRound;

XChangeGC(display,gc,GCLineWidth|GCLineStyle,//|GCCapStyle|GCFillStyle,
&values);
}

int Bres_Circle(Display *display,Window win,GC gc,int width,int height,int x0,int y0,double r);

// 画画的代码
static void draw(Display *display,Window win,GC gc,int width,int height,int x0,int y0,double r)
{
Bres_Circle(display,win,gc,width,height,x0,y0,r);
set_gc_values(display,gc);
}


void iSwap (int *a, int *b)
{
int tmp;

tmp=*a;
*a=*b;
*b=tmp;
}

int CirPot(Display *display,Window win,GC gc,int width,int height,int x0,int y0,int x,int y);
int Bres_Circle(Display *display,Window win,GC gc,int width,int height,int x0,int y0,double r)
{
    int x,y,d;

    x=0;
    y=(int)r;
    d=(int)(3-2*r);
    while(x<y)
    {
        CirPot(display,win,gc,width,height,x0,y0,x,y);
        if(d<0)
            d+=4*x+6;
        else
        {
            d+=4*(x-y)+10;
            y--;
        }
        x++;
    }
    if(x==y)
        CirPot(display,win,gc,width,height,x0,y0,x,y);
    return 0;
}  

int CirPot(Display *display,Window win,GC gc,int width,int height,int x0,int y0,int x,int y)
{
//    oldcolor=setcolor(color);
    XDrawPoint(display,win,gc,(x0+x),(y0+y));
    XDrawPoint(display,win,gc,(x0+y),(y0+x));
    XDrawPoint(display,win,gc,(x0+y),(y0-x));
    XDrawPoint(display,win,gc,(x0+x),(y0-y));
    XDrawPoint(display,win,gc,(x0-x),(y0-y));
    XDrawPoint(display,win,gc,(x0-y),(y0-x));
    XDrawPoint(display,win,gc,(x0-y),(y0+x));
    XDrawPoint(display,win,gc,(x0-x),(y0+y));
//tcolor(oldcolor);

    return 0;
}   


[adamzyg@adamzyg 图形]$ gcc -L/usr/X11R6/lib -lX11 hello.c -o hello -Wall
[adamzyg@adamzyg 图形]$ gcc -L/usr/X11R6/lib -lX11 hello.c -o hello -Wall
hello.c: 在函数 ‘main’ 中:
hello.c:55: 警告:未使用的变量 ‘r’
hello.c:54: 警告:未使用的变量 ‘y0’
hello.c:54: 警告:未使用的变量 ‘x0’
[adamzyg@adamzyg 图形]$ ls
Bres_Line.c  hello  hello1.c  hello.c  test  test.c  wxwindows.cpp
[adamzyg@adamzyg 图形]$./hello

如上的代码,我画圆的数据(圆心,半径)是通过常数传递的,如:
draw(display,win,gc,width,height,200,200,100);
本来应该从终端传入,可是就像我注释的部分一样在两个地方输入数据都会导致产生的窗口就是不画图,只有重复的输入数据。不知道怎么办才好。希望各位GGJJ们帮帮我,真的太笨了。^_^

上传的“画圆.tar.gz”里包括“hello.c”(源代码)和“hello”(可执行)两个文件。

[adamzyg@adamzyg 图形]$ gcc --version
gcc (GCC) 4.1.0 20060304 (Red Hat 4.1.0-3)
Copyright (C) 2006 Free Software Foundation, Inc.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
发表于 2006-4-30 21:10:26 | 显示全部楼层
说个方法吧,看看行不行
图形库应该有设置鼠标和键盘事件的吧?那些坐标和半径的值可设为全局变量,改变的话应该在上述两个事件中设置,而不需要在窗口事件中设置。
回复 支持 反对

使用道具 举报

发表于 2006-4-30 21:13:04 | 显示全部楼层
太长了,还是自己调吧  :)

这些图形生成和填充算法你还自己写啊?  我们那会都是直接抄X11实现的源代码

随便找两个开源的GUI源码看看吧,比如MicroWindows,MiniGUI等
回复 支持 反对

使用道具 举报

发表于 2006-5-2 00:11:15 | 显示全部楼层
楼主讲的那五个问题,microWindows, and MiniGui 里都有实现吗?已经是基本的CAD系统了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表