1
回答
用矩形框裁剪线段的一个问题
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

#include "stdafx.h"
#include "3120100039SX7.h"
#include "3120100039SX7Dlg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#endif




// 用于应用程序“关于”菜单项的 CAboutDlg 对话框


class CAboutDlg : public CDialog
{
public:
CAboutDlg();


// 对话框数据
enum { IDD = IDD_ABOUTBOX };


protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
DECLARE_MESSAGE_MAP()
};


CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()




// CMy3120100039SX7Dlg 对话框








CMy3120100039SX7Dlg::CMy3120100039SX7Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CMy3120100039SX7Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}


void CMy3120100039SX7Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CMy3120100039SX7Dlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
//ON_BN_CLICKED(IDCANCEL, &CMy3120100039SX7Dlg::OnBnClickedCancel)
//ON_BN_CLICKED(IDOK, &CMy3120100039SX7Dlg::OnBnClickedOk)
ON_BN_CLICKED(ID_BUTTON_RECT, &CMy3120100039SX7Dlg::OnBnClickedButtonRect)
ON_BN_CLICKED(ID_BUTTON_LINE, &CMy3120100039SX7Dlg::OnBnClickedButtonLine)
ON_BN_CLICKED(ID_BUTTON_CLIP, &CMy3120100039SX7Dlg::OnBnClickedButtonClip)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()




// CMy3120100039SX7Dlg 消息处理程序


BOOL CMy3120100039SX7Dlg::OnInitDialog()
{
CDialog::OnInitDialog();


// 将“关于...”菜单项添加到系统菜单中。


// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);


CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}


// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
pDC=(CClientDC*)GetDC();
xmax=0;
ymax=0;
xmin=0;
ymin=0;
rect_coor1=0;
rect_coor2=0;
rect_coor3=0;
rect_coor4=0;
 x1=0;
 y1=0;
 x2=0;
 y2=0;
is_rect_comp=false;
is_line_comp=false;
ptoldline=(0,0);
btndoen=oldline=oldrect=false;
istatus=0;
GetDlgItem(ID_BUTTON_RECT)->EnableWindow(true);// TODO: 在此添加额外的初始化代码
GetDlgItem(ID_BUTTON_LINE)->EnableWindow(false);
GetDlgItem(ID_BUTTON_CLIP)->EnableWindow(false);
return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
void CMy3120100039SX7Dlg::drawrect(){
int oldrop=pDC->SetROP2(R2_NOT);
xmax=rect_coor1>rect_coor2?rect_coor1:rect_coor2;
xmin=rect_coor1<rect_coor2?rect_coor1:rect_coor2;
ymax=rect_coor3>rect_coor4?rect_coor3:rect_coor4;
ymin=rect_coor3<rect_coor4?rect_coor3:rect_coor4;
pDC->MoveTo(xmin,ymin);
 
pDC->LineTo(xmax,ymin);
pDC->LineTo(xmax,ymax);
pDC->LineTo(xmin,ymax);
  
pDC->LineTo(xmin,ymin);
 
pDC->SetROP2(oldrop);


}
void CMy3120100039SX7Dlg::clearrect(){
if(oldrect){
drawrect();
oldrect=false;
}
}
void CMy3120100039SX7Dlg::drawline(){
int nOldRop=pDC->SetROP2(R2_NOT);
pDC->MoveTo (x1,y1);
pDC->LineTo (x2,y2);
pDC->SetROP2 (nOldRop);
oldline=true;


}
void CMy3120100039SX7Dlg::clearline(){
int nOldRop=pDC->SetROP2(R2_NOT);
pDC->MoveTo (x1,y1);
pDC->LineTo (ptoldline);
pDC->SetROP2 (nOldRop);
oldline=false;


}
void CMy3120100039SX7Dlg::clearclip(){
GetDlgItem(ID_BUTTON_RECT)->EnableWindow(true);// TODO: 在此添加额外的初始化代码
GetDlgItem(ID_BUTTON_LINE)->EnableWindow(false);
GetDlgItem(ID_BUTTON_CLIP)->EnableWindow(false);
is_rect_comp=false;
is_line_comp=false;


}
void CMy3120100039SX7Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}


// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。


void CMy3120100039SX7Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文


SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);


// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;


// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}


//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMy3120100039SX7Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}




void CMy3120100039SX7Dlg::OnBnClickedButtonRect()
{
Invalidate(true);
rect_coor1=0;
rect_coor2=0;
rect_coor3=0;
rect_coor4=0;
x1=y1=x2=y2=0;
btndoen=oldline=oldrect=false;
istatus=1;// TODO: 在此添加控件通知处理程序代码
}
void CMy3120100039SX7Dlg::OnBnClickedButtonLine()
{
istatus=2;
// TODO: 在此添加控件通知处理程序代码
}


void CMy3120100039SX7Dlg::OnBnClickedButtonClip()
{
istatus=0;
clearline();
clip(xmax,ymax,xmin,ymin);
clearclip();


// TODO: 在此添加控件通知处理程序代码
}


void CMy3120100039SX7Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(istatus==1&&!is_rect_comp){
rect_coor1=point.x ;
rect_coor3=point.y ;
}
if(istatus==2&&!is_line_comp){
x1=point.x ;
y1=point.y;
}
btndoen=true;
CDialog::OnLButtonDown(nFlags, point);
}


void CMy3120100039SX7Dlg::OnLButtonUp(UINT nFlags, CPoint point)
{
btndoen=false;
if(istatus==1){
GetDlgItem(ID_BUTTON_RECT)->EnableWindow(false);// TODO: 在此添加额外的初始化代码
GetDlgItem(ID_BUTTON_LINE)->EnableWindow(true);
GetDlgItem(ID_BUTTON_CLIP)->EnableWindow(false);
is_rect_comp=true;


}// TODO: 在此添加消息处理程序代码和/或调用默认值
if(istatus==2){
GetDlgItem(ID_BUTTON_RECT)->EnableWindow(false);// TODO: 在此添加额外的初始化代码
GetDlgItem(ID_BUTTON_LINE)->EnableWindow(false);
GetDlgItem(ID_BUTTON_CLIP)->EnableWindow(true);
is_line_comp=true;}


CDialog::OnLButtonUp(nFlags, point);
}


void CMy3120100039SX7Dlg::OnMouseMove(UINT nFlags, CPoint point)
{


// TODO: 在此添加消息处理程序代码和/或调用默认值
if(istatus==1&&!is_rect_comp&&btndoen){
if(oldrect)
clearrect();
rect_coor2=point.x;
rect_coor4=point.y;
drawrect();
oldrect=true;
}
if(istatus==2&&btndoen&&!is_line_comp){
if(oldline)
clearline();
x2=point.x;
y2=point.y;
drawline();
ptoldline=point;
}
CDialog::OnMouseMove(nFlags, point);
}
void CMy3120100039SX7Dlg::clip(int xmax, int ymax, int xmin, int ymin){
   bool accept=false,done=false;
   outcode outcode1,outcode2,*ptoutcode;
   int x,y;
   int t;
   if(x1<x2){
      t=x1;x1=x2;x2=t;t=y1;y1=y2;y2=t;
   }


   comoutcode(x1,y1,&outcode1);
   comoutcode(x2,y2,&outcode2);

 void CMy3120100039SX7Dlg::comoutcode(int x, int y, CMy3120100039SX7Dlg::outcode *outcode) {
outcode->all =0;
outcode->bottom =outcode->top =0;
if(y>ymax){
outcode->top=1;
outcode->all+=8;
}
else if(y<ymin){
outcode->bottom =1;
outcode->all+=4;
}
outcode->left =outcode->right =0;
if(x>xmax){
outcode->right =1;
outcode->all +=2;
}
else if(x<xmin){
outcode->left =1;
outcode->all+=1;
}


}

void CMy3120100039SX7Dlg::clip(int xmax, int ymax, int xmin, int ymin){

   bool accept=false,done=false;
   outcode outcode1,outcode2,*ptoutcode;
   int x,y;
   int t;
   if(x1<x2){
      t=x1;x1=x2;x2=t;t=y1;y1=y2;y2=t;
   }

   comoutcode(x1,y1,&outcode1);
   comoutcode(x2,y2,&outcode2);

  while(!done){
   if(outcode1.all==0&&outcode2.all==0){
   accept=true;
   done=true;
   }
 else if(outcode1.all&outcode2.all!=0){
   done=true;}
   else {
   if(outcode1.all!=0){
   ptoutcode=&outcode1;
   }
   else {
   ptoutcode=&outcode2;
   }
   if(ptoutcode->left){
   y=y1+(y2-y1)*(xmin-x1)/(x2-x1);
   x=xmin;
   }
   else if(ptoutcode->right){
   y=y1+(y2-y1)*(xmax-x1)/(x2-x1);
   x=xmax;
   }
   else if(ptoutcode->top){
   x=x1+(x2-x1)*(ymax-y1)/(y2-y1);
   y=ymax;
   }
   else if(ptoutcode->bottom){
   x=x1+(x2-x1)*(ymin-y1)/(y2-y1);
   y=ymin;
   }
   if(ptoutcode->all==outcode1.all){
   x1=x;
   y1=y;
   comoutcode(x1,y1,&outcode1);
   }
   else{
   x2=x;
   y2=y;
   comoutcode(x2,y2,&outcode1);
   }

   }
   } 

   if(accept)
{
  pDC->MoveTo((int)x1,(int)y1);
  pDC->LineTo((int)x2,(int)y2);
}

}
求助大神帮忙看一下这个编码裁剪的算法


这样的时候一运行就卡掉了


还有这样也是一样的情况
总之就是被裁减的线段不能通过矩形框的上边和左边
大神速救!! 

<无标签>
举报
顶部