在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的绘图机制
这个图片是在一位大佬的博客上找的 侵权必删致歉