zoukankan      html  css  js  c++  java
  • 在VisualSudio上实现Cohen-Southerland线段裁剪算法

    直线绘制:

    首先现在MFC文件中的xxxView.h头文件中添加一个直线的结构体(xxx表示你MFC文件的名字)

    typedef struct       //线段结构
    {
        CPoint startpoint;
        CPoint endpoint;
    }  LINE;

    还是在头文件里,加入下面那部分的代码(从CArry开始),encode函数是Cohen-Southerland算法实现编码的函数的定义,具体的代码在cpp文件里写

    在菜单(Menu)文件中添加两个事件处理程序(注意:添加时要写到View类里去),一个线段绘制,一个线段裁剪

     

     因为画线是通过鼠标左键来实现的,所以在View类里要添加一个消息(WM_LBUTTONDOWN),并加上代码

     之前不是添加了两个事件处理程序吗,所以在第一个,也就是线段绘制函数添加代码(这里我把函数名改成了DrawLine)

     最后在cpp文件中的OnDraw函数中添加划线的代码

     现在启动应用,点击绘制线段应该是可以画出直线的

    Cohen-Southerland算法

    在cpp文件里最上面定义下

    #define LEFT 1 //0001
    #define RIGHT 2 //0010
    #define BOTTOM 4//0100
    #define TOP 8 //1000

     接着编写编码函数

     为了能够裁剪成功,并重新画出裁剪后的直线,所以要绘制一个矩形框

    int XL = 100, XR = 300, YB = 100, YT = 200;
    //(x1,y1)、(x2,y2)为直线段的端点,XL为左边界,XR为右边界,YB为下边界,YT为上边

    同时在OnDraw函数中绘制出矩形框(写在OnDraw函数里)

      CPen newpen(PS_SOLID, 3, RGB(0, 255, 0));
        CPen *old = pDC->SelectObject(&newpen);
        pDC->MoveTo(100, 100);
        pDC->LineTo(100, 200);
    
        pDC->MoveTo(100, 200);
        pDC->LineTo(300, 200);
    
        pDC->MoveTo(300, 200);
        pDC->LineTo(300, 100);
    
        pDC->MoveTo(300, 100);
        pDC->LineTo(100, 100);
        pDC->SelectObject(old);

    接下来到了最关键的Cohen-Southerland算法

    在第二个事件处理程序,也就是线段裁剪的函数里添加代码(函数名称没改,就是默认的ID号)

    void CCGTestView::On32786() //线段裁剪
    {
        // TODO: 在此添加命令处理程序代码
        int code1, code2, code;
        int x, y;
        int i;
        int x1, y1, x2, y2;
        for (int i = 0; i < LineSet.GetSize(); i++) //绘制多条直线时,一条一条得实现
        {
            x1 = LineSet.GetAt(i).startpoint.x;
            y1 = LineSet.GetAt(i).startpoint.y;
            x2 = LineSet.GetAt(i).endpoint.x;
            y2 = LineSet.GetAt(i).endpoint.y;
            encode(x1, y1, code1); //分别求出端点所在的区号
            encode(x2, y2, code2);
    
            while (code1 != 0 || code2 != 0)//只有两个端点全在中心区内(直接保留完整线端,否则进入循环)
            {
                if (code1 &code2) //说明两个端点全在非中心区的区域,直接不画)
                    return;
                if (code1 != 0) //如果端点1不在中心区
                    code = code1; //使端点1与边界交换
                else  //说明端点1在中心区,端点2不在中心区
                    code = code2;  //使端点2与边界交点交换
    
                if (code & LEFT)  //线端与左边界相交,条件成立,点必定在左边界左侧
                {
                    x = XL; //求为与左边界相交的点的x值
                    y = y1 + (y2 - y1)*(XL - x1) / (x2 - x1); //斜率((y2 - y1)/(x2 - x1))
                }
                else if (code & RIGHT)//线段与右边界相交,条件成立,点必定在右边界右侧
                {
                    x = XR; //求出右边界的交点x值
                    y = y1 + (y2 - y1)*(XR - x1) / (x2 - x1);
                }
                else if (code & BOTTOM) //线段与下边界相交
                {
                    y = YB;
                    x = x1 + (x2 - x1)*(YB - y1) / (y2 - y1);
                }
                else if (code & TOP) //线段与上边界相交
                {
                    y = YT;
                    x = x1 + (x2 - x1)*(YT - y1) / (y2 - y1);
                }
    
                //将端点与边界交点转换
                if (code == code1)
                {
                    x1 = x;
                    y1 = y;
                    encode(x1, y1, code1);//如果交换成功,新编码为0000
                }
                else
                {
                    x2 = x;
                    y2 = y;
                    encode(x2, y2, code2); //交换成功,新编码为0000
                }
    
    
    
            }
            //绘制线段
            CDC *pDC = this->GetDC();
            CPen newpen(PS_SOLID, 3, RGB(255, 255, 0));
            CPen *old = pDC->SelectObject(&newpen);
            pDC->MoveTo(x1, y1);
            pDC->LineTo(x2, y2);
            pDC->SelectObject(old);
            ReleaseDC(pDC);
            
    
        }
        
    
    }

    运行结果:

     

    ------------------------------------------------------------------------

    (在下写博客,是记下平时学习程中常遇到的问题,代码中若有不合理之处,还望各位大佬指正)

  • 相关阅读:
    大数据面试题题库
    IDEA下通过Git实现代码管理
    使用QJM实现HDFS的HA配置
    1、HDFS分布式文件系统
    分析system_call中断处理过程
    由一段代码解析系统调用的原理
    从linux内核代码分析操作系统启动过程
    一个简单的时间片轮转多道程序内核
    从一段代码的汇编看计算机的工作原理
    九度OJ1468
  • 原文地址:https://www.cnblogs.com/djlobster/p/12937735.html
Copyright © 2011-2022 走看看