在Qt环境下用中点法做直线裁剪

在Qt环境下用中点法做直线裁剪

又是很水的一次实验报告呢 在老师和学长学姐的帮助下 用了三次课才做出了一份直线裁剪 【其实主要还是学姐把实验报告给我了】直接上代码叭
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void paintEvent(QPaintEvent *);

private:
    Ui::MainWindow *ui;


    int xLeft;
    int xRight;
    int yTop;
    int yBottom;

    int borderx;
    int bordery;

    void calculateBorderPoint(int x0, int y0, int x1, int y1);
    int calculateCode(int x, int y);
};

#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include"QTextCodec"

int main(int argc, char *argv[])
{
    QTextCodec::setCodecForLocale( QTextCodec::codecForName("utf8"));
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

这里有一行代码是为了提供中文环境的 具体的上篇博客里面有 这里是为了设置窗口标题而引用的 下面会体现

mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"


#include <stdio.h>
#include <QMessageBox>
#include <math.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("直线裁剪");


    xLeft = 100;//裁剪左边界
    xRight = 300;//裁剪右边界
    yTop = 100;//裁剪上边界
    yBottom = 300;//裁剪下边界

    borderx = 0;//计算出的线段与裁剪区域交点横坐标
    bordery = 0;//计算出的线段与裁剪区域交点纵坐标
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::paintEvent(QPaintEvent *)
{
    //初始化画笔参数
    QPainter painter(this);
    QPen pen;
    pen.setColor(Qt::black);
    painter.setPen(pen);
    //填充裁剪区域
    painter.fillRect(QRect(xLeft, yTop, (xRight - xLeft), (yBottom - yTop)), Qt::yellow);


    //随机线段端点
    int x0,y0,x1,y1;
    x0=24;
    y0=100;
    x1=321;
    y1=456;

    //画直线
    float dx, dy, m;
    dx = x1 - x0;
    dy = y1 - y0;
    m = dy / dx;
    float y = y0;
    for (int x = x0 ; x <= x1 ; x++)
    {
        painter.drawPoint(x, (int)(y + 0.5));
        y += m;
    }

    //计算线段端点的编码
    int code0 = calculateCode(x0, y0);
    int code1 = calculateCode(x1, y1);

    if (code0 == 0 && code1 == 0)
    {
        //如果两个端点都在区域内,不处理
    }
    else if ((code0 & code1) != 0)
    {
        //如果两个端点都在区域同一侧外,则说明线段与区域没交点
        x0 = 0;
        y0 = 0;
        x1 = 0;
        y1 = 0;
    }
    else if (code0 == 0)
    {
        //如果x0y0在区域内,则算出交点,设置为x1y1
        calculateBorderPoint(x0, y0, x1, y1);
        x1 = borderx;
        y1 = bordery;
    }
    else if (code1 == 0)
    {
        //如果x1y1在区域内,则算出交点,设置为x0y0
        calculateBorderPoint(x0, y0, x1, y1);
        x0 = borderx;
        y0 = bordery;
    }
    else
    {
        //如果两个端点都在外面且与区域有两个交点
        bool repeating = true;
        while (repeating)
        {
            //循环求中点的坐标与编码
            int midx = (int)((x0 + x1) / 2.0 + 0.5);
            int midy = (int)((y0 + y1) / 2.0 + 0.5);
            int codemid = calculateCode(midx, midy);
            if (codemid == 0)//如果中点在区域内
            {
                //先算出x0y0与中点的交点坐标,设置为x0y0
                calculateBorderPoint(x0, y0, midx, midy);
                x0 = borderx;
                y0 = bordery;
                //再算出x1y1与中点的交点坐标,设置为x1y1
                calculateBorderPoint(midx, midy, x1, y1);
                x1 = borderx;
                y1 = bordery;
                //停止循环
                repeating = false;
            }
            else if ((code0 & codemid) != 0)
            {
                //如果中点与x0y0都在区域外将中点设置为x0y0继续循环
                x0 = midx;
                y0 = midy;
            }
            else if ((code1 & codemid) != 0)
            {
                //如果中点与x1y1都在区域外将中点设置为x1y1继续循环
                x1 = midx;
                y1 = midy;
            }
        }
    }

    //画出截取的线段
    //设置画笔颜色,宽度
    painter.setPen(QPen(Qt::black, 3));

    //中点法画截取的线段
    dx = x1 - x0;
    dy = y1 - y0;
    m = dy / dx;
    y = y0;
    for (int x = x0 ; x <= x1 ; x++)
    {
        painter.drawPoint(x, (int)(y + 0.5));
        y += m;
    }


}

//计算线段与裁剪区域的交点坐标
void MainWindow::calculateBorderPoint(int x0, int y0, int x1, int y1)
{
    int code0 = calculateCode(x0, y0);
    int code1 = calculateCode(x1, y1);
    if (fabs(x0 - x1) <= 1)
    {
        //如果线段横坐标距离小于等于1,取在区域里的点为边界坐标点
        if (code0 == 0)
        {
            borderx = x0;
            bordery = y0;
        }
        else if (code1 == 0)
        {
            borderx = x1;
            bordery = y1;
        }
        else
        {
            borderx = 0;
            bordery = 0;
        }
    }
    else
    {
        //否则递归继续取中点
        int midx = (int)((x0 + x1) / 2.0 + 0.5);
        int midy = (int)((y0 + y1) / 2.0 + 0.5);
        int codemid = calculateCode(midx, midy);

        if (((code0 & codemid) != 0) || (code0 == 0 && codemid == 0))
        {
            calculateBorderPoint(midx, midy, x1, y1);
        }
        else if (((code1 & codemid) != 0) || (code1 == 0 && codemid == 0))
        {
            calculateBorderPoint(x0, y0, midx, midy);
        }
    }
}

//计算编码
int MainWindow::calculateCode(int x, int y)
{
    //初始化临时code为二进制0
    int code = 0b0000;
    //分别判断上下左右,加上对应的值
    code |= y < yTop ? 0b1000 : 0;
    code |= y > yBottom ? 0b0100 : 0;
    code |= x > xRight ? 0b0010 : 0;
    code |= x < xLeft ? 0b0001 : 0;
    return code;
}

画直线的方法在我的第一篇博客里面有详细介绍哦

接下来是运行结果

这是直线与裁剪区域有两个交点的
在这里插入图片描述
这是只有一个交点的
在这里插入图片描述
这是没有交点的
在这里插入图片描述
直线的相关数据是要在这里手动设置的哦在这里插入图片描述
因为这里用到了矩形 所以要补充一下Qt的绘图机制
在这里插入图片描述
这个图片是在一位大佬的博客上找的 侵权必删致歉

  • 13
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值