Liang-Barsky 裁剪算法

该博客详细介绍了如何使用直线裁剪算法对指定矩形区域进行裁剪,通过计算直线与矩形边框延长线的交点,确定裁剪后的直线段。算法涉及到图形学中的线段裁剪问题,采用Bresenham算法绘制直线,并结合几何相似原理求解交点坐标。此外,还提供了OpenGL实现的示例代码,允许用户通过鼠标交互定义直线起点和终点,动态展示裁剪效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法原理:
分别计算原直线与四条边框延长线的四个交点,在中间的两个交点即为裁剪完成的两个点。
p1-p2黑色直线为原直线;
红色矩形为裁剪边框;
绿色线为裁剪边框的延长线;
紫色为原直线的延长线;
ABCD分别为原直线与四条边框的延长线的交点;
在这里插入图片描述

以求B点为例:
B点横坐标已知,若求出BF的长度,则可以用p1坐标表示B点坐标;
在这里插入图片描述

BF可用黄色三角形和小三角形 相似三角形求解;
求出系数u,即可求出点坐标。

#include<GL/glut.h>
#include<math.h>
#include<iostream>
#include<algorithm>
float startx = 0, starty = 0, endx = 0, endy = 0;
float xL = 100, xR = 400, yB = 400, yT = 100;
float u1, u2;
using namespace std;

void Breshham(int x0, int y0, int x1, int y1) {
	double dx = x1 - x0, dy = y1 - y0;
	//绘制垂线
	if (fabs(x0 - x1) < 1e-6) {
		if (y0 > y1) {
			swap(y0, y1);
			swap(x0, x1);
		}
		int x = round(x0), y = round(y0);
		for (y = round(y0); y < round(y1); y++) {
			glVertex2f(x, y);
		}
	}
	double k, d;
	k = dy / dx;
	if (k >= 0.0 && k <= 1.0) {
		if (x0 > x1) {
			swap(x0, x1);
			swap(y0, y1);
		}
		int x = round(x0), y = round(y0);
		d = 0.5 - k;
		for (x = round(x0); x < round(x1); x++) {
			glVertex2f(x, y);
			if (d < 0) {
				y++;
				d += 1 - k;
			}
			else {
				d -= k;
			}
		}

	}
	else if (k > 1) {

		if (y0 > y1) {
			swap(y0, y1);
			swap(x0, x1);
		}
		int x = round(x0), y = round(y0);
		d = 1 - 0.5*k;
		for (y = round(y0); y < round(y1); y++) {
			glVertex2f(x, y);
			if (d >= 0) {
				x++;
				d += 1 - k;
			}
			else {
				d += 1;
			}
		}

	}
	else if (k >= -1.0 && k <= 0.0) {

		if (x0 < x1) {
			swap(x0, x1);
			swap(y0, y1);
		}
		int x = round(x0), y = round(y0);
		k = -k;
		d = 0.5 - k;
		for (x = round(x0); x > round(x1); x--) {
			glVertex2f(x, y);
			if (d < 0) {
				y++;
				d += 1 + k;
			}
			else {
				d -= k;
			}
		}

	}
	else if (k < -1.0) {

		if (y0 > y1) {
			swap(x0, x1);
			swap(y0, y1);
		}
		int x = round(x0), y = round(y0);
		k = -k;
		d = 1 - 0.5*k;
		for (y = round(y0); y < round(y1); y++) {
			glVertex2f(x, y);
			if (d >= 0) {
				x--;
				d += 1 - k;
			}
			else {
				d += 1;
			}

		}
	}
}

void rectangle()
{
	glColor4f(1.0, 1.0, 0.0, 0.75);
	glBegin(GL_POLYGON);
	glVertex2f(xL, yB);
	glVertex2f(xR, yB);
	glVertex2f(xR, yT);
	glVertex2f(xL, yT);
	glEnd();
}


bool ClipT(float p, float q)
{
	float r;
	if (p < 0)
	{
		r = q / p;
		if (r > u2)
			return false;
		u1 = max(u1, r);
	}
	else if (p > 0)
	{
		r = q / p;
		if (r < u1)
			return false;
		u2 = min(u2, r);
	}
	else return (q >= 0);
	return true;
}


void L_B_lineClip(float x1, float y1, float x2, float y2)
{
	float dx = x2 - x1, dy = y2 - y1;
	u1 = 0, u2 = 1;
	if (ClipT(-dx, x1 - xL))
		if (ClipT(dx, xR - x1))
			if (ClipT(-dy, y1 - yT))
				if (ClipT(dy, yB - y1))
				{
					cout << u1 <<"  "<< u2<<endl;
					Breshham(x1 + u1 * dx, y1 + u1 * dy, x1 + u2 * dx, y1 + u2 * dy);
				}
}


void solve() {
	glColor3f(0.0, 0.0, 0.0);
	glBegin(GL_POINTS);
		L_B_lineClip(startx, starty, endx, endy);
	glEnd();
	glFlush();
	cout << "初始" << startx << " " << starty << endl << "末尾" << endx << " " << endy << endl << endl;
}


void mouseFunc(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
		endx = x;
		endy = y;
		solve();
	}
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		startx = x;
		starty = y;
	}
}


void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	rectangle();
	glFlush();
}



int main(int argc, char *argv[]) {
	glutInit(&argc, argv);
	glutInitWindowPosition(600, 250);
	glutInitWindowSize(500, 500);
	glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
	glutCreateWindow("jxl");
	glClearColor(1.0, 1.0, 1.0, 1.0);
	gluOrtho2D(0, 500, 500, 0);
	glutDisplayFunc(&display);
	glutMouseFunc(mouseFunc);
	glutMainLoop();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值