⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bezierdlg.cpp

📁 VC++三次样条插值和贝塞尔曲线
💻 CPP
字号:
// BezierDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Bezier.h"
#include "BezierDlg.h"

#include "CubicSplineInterpolation.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CBezierDlg dialog

CBezierDlg::CBezierDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CBezierDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CBezierDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_dbBS = 0.5f;
}

void CBezierDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CBezierDlg)
	DDX_Control(pDX, IDC_LINK, m_ctrlLink);
	DDX_Control(pDX, IDC_CHECK4, m_ctrlPT);
	DDX_Control(pDX, IDC_CHECK3, m_ctrlGdi);
	DDX_Control(pDX, IDC_CHECK2, m_ctrlBezier);
	DDX_Control(pDX, IDC_CHECK1, m_ctrlCul);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CBezierDlg, CDialog)
	//{{AFX_MSG_MAP(CBezierDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_BN_CLICKED(IDC_RADIO1, OnAdd)
	ON_BN_CLICKED(IDC_RADIO2, OnMove)
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_VSCROLL()
	ON_BN_CLICKED(IDC_CHECK3, OnCheck3)
	ON_BN_CLICKED(IDC_CHECK2, OnCheck2)
	ON_BN_CLICKED(IDC_CHECK1, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK4, OnCheck4)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBezierDlg message handlers

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

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	n = -1;
	current2 = -1;
	current = -1;
	AddorMove =1;


	CString strValue; 	 
	strValue.Format("%3.1f", m_dbBS ); 
	SetDlgItemText(IDC_EDIT1,strValue);

    CSpinButtonCtrl* pScrollBar = (CSpinButtonCtrl*)GetDlgItem(IDC_SPIN1);
    pScrollBar->SetRange(0,30);

	m_ctrlBezier.SetCheck(1);
	m_ctrlCul.SetCheck(1);
	m_ctrlGdi.SetCheck(1);
	m_ctrlPT.SetCheck(1);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CBezierDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		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;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		pDC = new CPaintDC(this);
		if(n>=0) 
		{
			if (m_ctrlPT.GetCheck())
			{
				pDC->MoveTo(points[0].x, points[0].y);
				for(int i = 0; i<=n; i++)
				{
					CPen penStroke(PS_SOLID,1,0x007700);
					CPen *ppenPrevious=pDC->SelectObject(&penStroke);
					pDC->LineTo(points[i].x,points[i].y);
					pDC->SelectObject(ppenPrevious);
					CPen penStroke2(PS_SOLID,1,0xff0000);
					CPen *ppenPrevious2=pDC->SelectObject(&penStroke2);
					pDC->Rectangle(points[i].x - 5, points[i].y -5 ,points[i].x + 5 ,points[i].y + 5);
					pDC->SelectObject(ppenPrevious2);
				}
			}
			
			
			////////////三次样条插值 画线/////////////////////////////////////
			
			DrawCubicSpline(pDC);
			
			////////////用GDI+平滑曲线///////////////////////////////////////////////////
			
			DrawBYGDIP(pDC);
			////////贝塞尔曲线 画线///////////////////////////////////////////
			
			
			DPOINT p[100];
			memcpy(p, points, sizeof(p));
			MyDraw(p);//
			
			
		}
		CDialog::OnPaint();
		delete pDC;
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CBezierDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CBezierDlg::MyDraw(DPOINT * p)
{

	if (!m_ctrlBezier.GetCheck())
	{
		return;
	}

	if (n <= 0) return;
	if((p[n].x < p[0].x+1) && (p[n].x > p[0].x-1) && (p[n].y < p[0].y+1) && (p[n].y > p[0].y-1))
	{
		pDC->SetPixel(p[0].x, p[0].y, RGB(255,0,0));//0x0000ff
		return;
	}
	DPOINT *p1;
	p1 = new DPOINT[n+1];
	int i, j;
	p1[0] = p[0];
	for(i=1; i<=n; i++)
	{
		for(j=0; j<=n-i;j++)
		{
			p[j].x = (p[j].x + p[j+1].x)/2;
			p[j].y = (p[j].y + p[j+1].y)/2;
		}
		p1[i] = p[0];
	}
	MyDraw(p);
	MyDraw(p1);
	delete p1;
}

void CBezierDlg::OnButton2() 
{
	// TODO: Add your control notification handler code here
	n = -1;
	RedrawWindow();
}

void CBezierDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if(AddorMove == 1)
	{
		if(n>=99) 
		{
			AfxMessageBox("Too many points.");
			return;
		}
		n++;
		points[n].x = point.x;
		points[n].y = point.y;
		RedrawWindow();
	}
	else if(AddorMove == -1)
	{
		double x, y;
		current = -1;
		double t=50;
		for(int i = 0; i <= n; i++)
		{
			x = points[i].x - point.x, y = points[i].y - point.y;
			x*=x; y*=y;
			if(x + y < t)
				// {current = i; break;}
			{	current = i;	t=x+y;	}

		}
	}
	CDialog::OnLButtonDown(nFlags, point);
}

void CBezierDlg::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	current = -1;
	CDialog::OnLButtonUp(nFlags, point);
}

void CBezierDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if(current >= 0 ) 
	{
		points[current].x = point.x;
		points[current].y = point.y;
		RedrawWindow();
	}
	if(current2 >= 0 ) 
	{
		points[current2].x = point.x;
		points[current2].y = point.y;
		RedrawWindow();
	}
	//CDialog::OnMouseMove(nFlags, point);
	CDialog::OnMouseMove(nFlags, point);
}

void CBezierDlg::OnAdd() 
{
	// TODO: Add your control notification handler code here
	AddorMove = 1;	
}

void CBezierDlg::OnMove() 
{
	// TODO: Add your control notification handler code here
	AddorMove = -1;
}

void CBezierDlg::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
		if(AddorMove == -1)
	{
		if(n>=99) 
		{
			AfxMessageBox("Too many points.");
			return;
		}
		n++;
		points[n].x = point.x;
		points[n].y = point.y;
		RedrawWindow();
	}
	else if(AddorMove == 1)
	{
		double x, y;
		double t=50;
		current2 = -1;
		for(int i = 0; i <= n; i++)
		{
			x = points[i].x - point.x, y = points[i].y - point.y;
			x*=x; y*=y;
			if(x + y < t) {current2 = i; t=x+y;}
		}
	}
	CDialog::OnRButtonDown(nFlags, point);
}

void CBezierDlg::OnRButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	current2 = -1;
	CDialog::OnRButtonUp(nFlags, point);
}


////////////三次样条插值 画线/////////////////////////////////////
void CBezierDlg::DrawCubicSpline(CDC *pDC)
{
	if (!m_ctrlCul.GetCheck())
	{
		return;
	}

	int nPtCount = n + 1;
	//控制点数组
	double* ctrlPtX = new double[nPtCount];
	double* ctrlPtY = new double[nPtCount];
	
	//填充数据
	for(int i = 0; i<=n; i++)
	{
		ctrlPtX[i] = points[i].x;
		ctrlPtY[i] = points[i].y;
	}	
	
	//要计算的插值点数组
	int nOutCount = 100; 
	double *ptx = new double[nOutCount];
	double *pty = new double[nOutCount];
	
	//构造三次样条对像
	CCubicSplineInterpolation SmoothCurve(ctrlPtX,ctrlPtY,nPtCount);
	
	//生成插值点数组
	if (SmoothCurve.GetInterpolationPts(nOutCount,ptx,pty))
	{
		pDC->MoveTo(ptx[0], pty[0]);
		for(int i = 0; i < nOutCount; i++)
		{
			CPen penStroke(PS_SOLID,1,RGB(0,255,0));
			CPen *ppenPrevious=pDC->SelectObject(&penStroke);
			pDC->LineTo(ptx[i],pty[i]);
			pDC->SelectObject(ppenPrevious);
		}
	}
	
	
	delete [] ctrlPtX;
	delete [] ctrlPtY;
	delete [] ptx;
	delete [] pty;
}

void CBezierDlg::DrawBYGDIP(CDC *pDC)
{

	if (!m_ctrlGdi.GetCheck())
	{
		return;
	}
	Graphics graphics( pDC->m_hDC );
	
	Point * ptArray = new Point[n + 1];
	
	for(int i = 0; i<=n ; i++)
	{
        ptArray[i].X = points[i].x;
		ptArray[i].Y = points[i].y;

	}

	Pen pen(Color(255, 0, 0, 0),1);

	graphics.DrawCurve(&pen,ptArray,n + 1,m_dbBS);


}

void CBezierDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	if ( nSBCode == SB_ENDSCROLL) 
    return; 


	   if ( pScrollBar->GetDlgCtrlID() == IDC_SPIN1) 
	   { 
		   CString strValue; 
		   m_dbBS  = (double) nPos/10;
		   strValue.Format("%3.1f", m_dbBS ); 
		   ((CSpinButtonCtrl*) pScrollBar)->GetBuddy()->SetWindowText(strValue); 

		   this->Invalidate();
	   } 

	CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CBezierDlg::OnCheck3() 
{
	// TODO: Add your control notification handler code here
	this->Invalidate();
}

void CBezierDlg::OnCheck2() 
{
	// TODO: Add your control notification handler code here
	this->Invalidate();
}

void CBezierDlg::OnCheck1() 
{
	// TODO: Add your control notification handler code here
	this->Invalidate();
}

void CBezierDlg::OnCheck4() 
{
	// TODO: Add your control notification handler code here
	this->Invalidate();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -