直线裁剪算法

此算法 就是Cyrus-Beck裁剪算法


1.判断dx,dy是否为零作相应的简单处理,并返回


2.下面通过例子说明第2步的原理,现在先给出原理
如果P1P2与裁剪区域有交点,那么P1P2与裁剪区域存在交集,使得交集中的任一元素t同时满足下列不等式


xmin <= x1 + dx*t <= xmax (1)
ymin <= y1 + dy*t <= ymax (2)


其中,dx = x2 - x1, dy = y2 - y1,若(1)∩(2)= 空集  则说明t不能同时满足方程(1),(2),
亦即P1P2不需要被裁剪




为什么“如果P1P2与裁剪区域有交点,那么P1P2与裁剪区域存在交集,使得交集中的任一元素t同时满足下列不等式”?
答:根据直线参数方程P = P1 + DP*t ,P表示直线段P1P2上的任一点,因此如果P满足不等式(1),(2)就说明P在P1P2上且在裁剪区域内。




又∵0<= t <= 1,因此可以得到新的不等式方程组
(xmin - x)/dx <= t <= (xmax - x1)/dx  (3)
(ymin - y1)/dy <= t <= (ymax - y1)/dy (4)
0<=t<=1      (5)




如图,p1(x1,y1), p2(x2,y2)
x1 = 2   x2 = 7
y1 = -2   y2 = 2


裁剪区域为:
xmin = -4, ymin = -4
xmax = 6,  ymax = 4




(xmin - x)/dx = (-4 - 2) / (7 - 2) = - 6/5
(xmax - x1)/dx = (6 - 2 ) / 5 = 4 / 5


(ymin - y1)/dy = (-4 - 2)/(2 - (-2)) = -2 /4 = -1/2
(ymax - y1)/dy = (4 - (-2))/4 = 3 / 2


代入不等式组得
-6/5 <= t <= 4/5
-1/2 <= t <= 3/2
0 <= t <= 1
解不等式方程组得
0 <= t <= 4/5
令t1 = 0, t2 = 4/5,则t1, t2是P1P2被裁剪后的两个点P1',P2'对应的两个t值


因为t1 = 0,又根据直线的参数方程P = P1 + DP*t ,得P1' = P1 + DP*0 = P1


x2' = x1 + dx*t2 = 2 + 5*4 / 5 = 6
y2' = y1 + dy*t2 = -2 + 4*4 / 5 = 1.2
则p2' = (6,1.2)


P1'(2, - 2), P2'(6,1.2)就是P1P2被裁剪区域裁剪后的两个点
因为P1在裁剪区域内,所以P1' = P1是合理的

// 线段裁剪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、付费专栏及课程。

余额充值