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);
            
    
        }
        
    
    }

    运行结果:

     

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

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

  • 相关阅读:
    FEniCS 1.1.0 发布,计算算术模型
    Piwik 1.10 发布,增加社交网站统计
    淘宝褚霸谈做技术的心态
    CyanogenMod 10.1 M1 发布
    Druid 发布 0.2.11 版本,数据库连接池
    GNU Gatekeeper 3.2 发布
    Phalcon 0.9.0 BETA版本发布,新增大量功能
    EUGene 2.6.1 发布,UML 模型操作工具
    CVSps 3.10 发布,CVS 资料库更改收集
    Opera 移动版将采用 WebKit 引擎
  • 原文地址:https://www.cnblogs.com/djlobster/p/12937735.html
Copyright © 2011-2022 走看看