CS直线裁剪算法_C++实现(计算机图形学作业)

#include<iostream>
#include<graphics.h>
#include<conio.h>
using namespace std;
//分别用四个符号常量记录四个边界的编号,相当于C语言中的define宏定义
const unsigned TOP = 8;
const unsigned BOTTOM = 4;
const unsigned RIGHT = 2;
const unsigned LEFT = 1;

static unsigned xl, yb, xr, yt;

unsigned short Region_Coding(const unsigned& x, const unsigned& y)
{
	unsigned short coding = 0;
	if (y > yt)
		coding += 8;
	else if (y < yb)
		coding += 4;
	if (x > xr)
		coding += 2;
	else if (x < xl)
		coding += 1;
	return coding;
}

void CS_LineClip(const unsigned& x1, const unsigned& y1, const unsigned& x2, const unsigned& y2)
{
	unsigned p1, p2;
	//通过区域码函数分别求出两个点的区域码
	p1 = Region_Coding(x1, y1);
	p2 = Region_Coding(x2, y2);

	//第一种情况:两点的区域码均在窗口内部,则直接画出该直线即可
	if (p1 == 0 && p2 == 0)
	{
		line(x1, y1, x2, y2);
		return;
	}
	//第二种情况,两点的区域码均不在窗口内部,则不绘制任何直线
	else if ((p1 & p2) != 0)
	{
		return;
	}
	//第三种情况:即排除之前两种情况后的剩余情况,此时进行分类讨论
	else
	{
		//首先处理斜率不存在的特殊情况,该情况下可以直接画出线
		if ((x1 == x2 && y1 <= yb && y2 >= yt) || (x1 == x2 && y1 >= yt && y2 <= yb))
		{
			line(x1, yb, x2, yt);
			return;
		}
		//求出直线的斜率。注意:此处一定要用到类型转换!否则求出的斜率很可能存在异常
		double k = (double(y2) - double(y1)) / (double(x2) - double(x1));
		if ((p1 & LEFT) != 0)//由于已经使得两点的横坐标升序排列,因此如果左边点在左边界的左边的话,则求出直线与左边界的交点,以交点代替第一个点递归执行函数
		{
			unsigned New_y1 = unsigned(k * (xl - x1) + y1 + 0.5);
			CS_LineClip(xl, New_y1, x2, y2);
			return;
		}
		if ((p2 & RIGHT) != 0)//运行到此处时直线左端点一定在左边界上或左边界的右边,此时对右端点进行类似检查:如果右端点在右边界的右边,则取直线与右边界的交点。
		{
			unsigned New_y2 = unsigned(k * (xr - x1) + y1 + 0.5);
			CS_LineClip(x1, y1, xr, New_y2);
			return;
		}
		//剩下的情况中只包含两点横坐标均在左右边界之间,但是纵坐标不在上下边界内的情况,需要分斜率正负进行讨论
		if (k >= 0)
		{
			if ((p2 & TOP) != 0)//斜率为正且右边的点在上边界以上时,求出直线与上边界的交点来代替上点,递归调用自身即可
			{
				unsigned New_x2 = unsigned(x1 + (yt - y1) / k + 0.5);
				CS_LineClip(x1, y1, New_x2, yt);
				return;
			}
			if ((p1 & BOTTOM) != 0)//斜率为正且左边的点在下边界以下时,求出直线与下边界的交点来代替下点,递归调用自身
			{
				unsigned New_x1 = unsigned(x1 + (yb - y1) / k + 0.5);
				CS_LineClip(New_x1, yb, x2, y2);
				return;
			}
		}
		if (k < 0)//斜率小于零的情况进行类似讨论即可
		{
			if ((p1 & TOP) != 0)
			{
				unsigned New_x1 = unsigned(x1 + (yt - y1) / k + 0.5);
				CS_LineClip(New_x1, yt, x2, y2);
				return;
			}
			if ((p2 & BOTTOM) != 0)
			{
				unsigned New_x2 = unsigned(x1 + (yb - y1) / k + 0.5);
				CS_LineClip(x1, y1, New_x2, yb);
				return;
			}
		}
	}
}

int main(void)
{
	int x1, y1, x2, y2;
	cout << "请分别输入原始直线两端点的横纵坐标:";
	cin >> x1 >> y1 >> x2 >> y2;
	cout << "请分别输入裁剪窗口左下角和右上角的横纵坐标:";
	cin >> xl >> yb >> xr >> yt;
	cout << "原始直线和裁剪窗口如下图所示:(按任意键查看,查看后按任意键裁剪)";
	_getch();
	initgraph(800, 640);
	line(x1, y1, x2, y2);//通过之前学过的Bresenham方法进行画线操作
	rectangle(xl, yt, xr, yb);
	_getch();
	closegraph();
	initgraph(800, 640);
	CS_LineClip(x1, y1, x2, y2);
	rectangle(xl, yt, xr, yb);
	_getch();
	closegraph();
	return 0;
}

备注:graphics.h包需要自行百度免费下载

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
// 线段裁剪CSView.cpp : implementation of the CCSView class // #include "stdafx.h" #include "线段裁剪CS.h" #include "线段裁剪CSDoc.h" #include "线段裁剪CSView.h" #define left 200 //默认图形窗口 #define right 400 #define bottom 100 #define top 300 #define l 1 //区域编码 #define r 2 #define b 4 #define t 8 #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CCSView IMPLEMENT_DYNCREATE(CCSView, CView) BEGIN_MESSAGE_MAP(CCSView, CView) //{{AFX_MSG_MAP(CCSView) ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCSView construction/destruction CCSView::CCSView() { // TODO: add construction code here } CCSView::~CCSView() { } BOOL CCSView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CCSView drawing void CCSView::OnDraw(CDC* pDC) { CCSDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->TextOut(150,1," 单击左键定线段起点,右击定线段终点"); pDC->TextOut(150,20,"线段的裁剪结果会自动显示"); // TODO: add draw code for native data here pDC->Rectangle(left,top,right,bottom); } ///////////////////////////////////////////////////////////////////////////// // CCSView printing BOOL CCSView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CCSView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CCSView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值