在MFC++6.0中用鼠标选择圆心实现椭圆的扫描转换的代码
时间: 2023-06-19 22:08:27 浏览: 109
以下是一个简单的例子,演示如何使用鼠标选择椭圆的中心,并实现椭圆的扫描转换。
首先,创建一个MFC项目,新建一个类名为CEllipseScan的类,并将其继承自CView。
CEllipseScan类的头文件中包含以下代码:
```cpp
class CEllipseScan : public CView
{
protected: // create from serialization only
CEllipseScan();
DECLARE_DYNCREATE(CEllipseScan)
// Attributes
public:
CEllipseScanDoc* GetDocument();
// Operations
public:
// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// Implementation
public:
virtual ~CEllipseScan();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
CPoint m_center; // 椭圆中心坐标
BOOL m_bDragging; // 是否正在拖动鼠标
int m_radiusX, m_radiusY; // 椭圆的半径
BOOL m_bDrawEllipse; // 是否绘制椭圆
void DrawEllipse(CDC* pDC, int x0, int y0, int a, int b); // 绘制椭圆
void ScanConvertEllipse(CDC* pDC, int x0, int y0, int a, int b); // 扫描转换椭圆
void ScanConvertLine(CDC* pDC, int x0, int y0, int x1, int y1); // 扫描转换直线
void DrawPixel(CDC* pDC, int x, int y, COLORREF color); // 绘制像素点
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};
```
CEllipseScan类的实现文件中包含以下代码:
```cpp
// CEllipseScan.cpp : implementation file
//
#include "stdafx.h"
#include "EllipseScan.h"
#include "EllipseScanDoc.h"
#include "EllipseScanView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CEllipseScan
IMPLEMENT_DYNCREATE(CEllipseScan, CView)
BEGIN_MESSAGE_MAP(CEllipseScan, CView)
//{{AFX_MSG_MAP(CEllipseScan)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CEllipseScan construction/destruction
CEllipseScan::CEllipseScan()
{
m_bDragging = FALSE;
m_bDrawEllipse = FALSE;
}
CEllipseScan::~CEllipseScan()
{
}
BOOL CEllipseScan::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CEllipseScan drawing
void CEllipseScan::OnDraw(CDC* pDC)
{
CEllipseScanDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if (m_bDrawEllipse)
{
DrawEllipse(pDC, m_center.x, m_center.y, m_radiusX, m_radiusY);
}
}
/////////////////////////////////////////////////////////////////////////////
// CEllipseScan printing
BOOL CEllipseScan::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CEllipseScan::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CEllipseScan::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CEllipseScan diagnostics
#ifdef _DEBUG
void CEllipseScan::AssertValid() const
{
CView::AssertValid();
}
void CEllipseScan::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CEllipseScanDoc* CEllipseScan::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEllipseScanDoc)));
return (CEllipseScanDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CEllipseScan message handlers
void CEllipseScan::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bDragging = TRUE;
m_center = point;
CClientDC dc(this);
dc.SetROP2(R2_NOTXORPEN);
dc.Ellipse(m_center.x - 2, m_center.y - 2, m_center.x + 2, m_center.y + 2);
CView::OnLButtonDown(nFlags, point);
}
void CEllipseScan::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bDragging)
{
m_bDragging = FALSE;
CClientDC dc(this);
dc.SetROP2(R2_NOTXORPEN);
dc.Ellipse(m_center.x - 2, m_center.y - 2, m_center.x + 2, m_center.y + 2);
m_radiusX = abs(point.x - m_center.x);
m_radiusY = abs(point.y - m_center.y);
m_bDrawEllipse = TRUE;
Invalidate();
}
CView::OnLButtonUp(nFlags, point);
}
void CEllipseScan::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bDragging)
{
CClientDC dc(this);
dc.SetROP2(R2_NOTXORPEN);
dc.Ellipse(m_center.x - 2, m_center.y - 2, m_center.x + 2, m_center.y + 2);
m_radiusX = abs(point.x - m_center.x);
m_radiusY = abs(point.y - m_center.y);
dc.Ellipse(m_center.x - m_radiusX, m_center.y - m_radiusY, m_center.x + m_radiusX, m_center.y + m_radiusY);
}
CView::OnMouseMove(nFlags, point);
}
void CEllipseScan::DrawEllipse(CDC* pDC, int x0, int y0, int a, int b)
{
int x, y, d;
x = 0;
y = b;
d = 4 * b * b + a * a * (1 - 4 * b);
ScanConvertLine(pDC, x0 + x, y0 + y, x0 + x, y0 - y);
ScanConvertLine(pDC, x0 - x, y0 + y, x0 - x, y0 - y);
ScanConvertLine(pDC, x0 + x, y0 + y, x0 - x, y0 + y);
ScanConvertLine(pDC, x0 + x, y0 - y, x0 - x, y0 - y);
while (b * b * (x + 1) < a * a * (y - 0.5))
{
if (d < 0)
{
d += 4 * b * b * (2 * x + 3);
}
else
{
d += 4 * b * b * (2 * x + 3) + 4 * a * a * (-2 * y + 2);
y--;
}
x++;
ScanConvertLine(pDC, x0 + x, y0 + y, x0 + x, y0 - y);
ScanConvertLine(pDC, x0 - x, y0 + y, x0 - x, y0 - y);
ScanConvertLine(pDC, x0 + x, y0 + y, x0 - x, y0 + y);
ScanConvertLine(pDC, x0 + x, y0 - y, x0 - x, y0 - y);
}
d = b * b * (2 * x + 1) * (2 * x + 1) + 4 * a * a * (y - 1) * (y - 1) - 4 * a * a * b * b;
while (y > 0)
{
if (d < 0)
{
d += 4 * b * b * (2 * x + 2) + 4 * a * a * (-2 * y + 3);
x++;
}
else
{
d += 4 * a * a * (-2 * y + 3);
}
y--;
ScanConvertLine(pDC, x0 + x, y0 + y, x0 + x, y0 - y);
ScanConvertLine(pDC, x0 - x, y0 + y, x0 - x, y0 - y);
ScanConvertLine(pDC, x0 + x, y0 + y, x0 - x, y0 + y);
ScanConvertLine(pDC, x0 + x, y0 - y, x0 - x, y0 - y);
}
}
void CEllipseScan::ScanConvertEllipse(CDC* pDC, int x0, int y0, int a, int b)
{
int x, y, d;
x = 0;
y = b;
d = 4 * b * b + a * a * (1 - 4 * b);
DrawPixel(pDC, x0 + x, y0 + y, RGB(255, 0, 0));
DrawPixel(pDC, x0 + x, y0 - y, RGB(255, 0, 0));
DrawPixel(pDC, x0 - x, y0 + y, RGB(255, 0, 0));
DrawPixel(pDC, x0 - x, y0 - y, RGB(255, 0, 0));
while (b * b * (x + 1) < a * a * (y - 0.5))
{
if (d < 0)
{
d += 4 * b * b * (2 * x + 3);
}
else
{
d += 4 * b * b * (2 * x + 3) + 4 * a * a * (-2 * y + 2);
y--;
}
x++;
DrawPixel(pDC, x0 + x, y0 + y, RGB(255, 0, 0));
DrawPixel(pDC, x0 + x, y0 - y, RGB(255, 0, 0));
DrawPixel(pDC, x0 - x, y0 + y, RGB(255, 0, 0));
DrawPixel(pDC, x0 - x, y0 - y, RGB(255, 0, 0));
}
d = b * b * (2 * x + 1) * (2 * x + 1) + 4 * a * a * (y - 1) * (y - 1) - 4 * a * a * b * b;
while (y > 0)
{
if (d < 0)
{
d += 4 * b * b * (2 * x + 2) + 4 * a * a * (-2 * y + 3);
x++;
}
else
{
d += 4 * a * a * (-2 * y + 3);
}
y--;
DrawPixel(pDC, x0 + x, y0 + y, RGB(255, 0, 0));
DrawPixel(pDC, x0 + x, y0 - y, RGB(255, 0, 0));
DrawPixel(pDC, x0 - x, y0 + y, RGB(255, 0, 0));
DrawPixel(pDC, x0 - x, y0 - y, RGB(255, 0, 0));
}
}
void CEllipseScan::ScanConvertLine(CDC* pDC, int x0, int y0, int x1, int y1)
{
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
int sx = (x0 < x1 ? 1 : -1);
int sy = (y0 < y1 ? 1 : -1);
int err = dx - dy;
while (TRUE)
{
DrawPixel(pDC, x0, y0, RGB(255, 0, 0));
if (x0 == x1 && y0 == y1)
{
break;
}
int e2 = 2 * err;
if (e2 > -dy)
{
err -= dy;
x0 += sx;
}
if (e2 < dx)
{
err += dx;
y0 += sy;
}
}
}
void CEllipseScan::DrawPixel(CDC* pDC, int x, int y, COLORREF color)
{
pDC->SetPixel(x, y, color);
}
```
现在,运行该应用程序,单击并拖动鼠标,选择椭圆的中心和半径。完成选择后,椭圆将被绘制,并使用扫描转换算法将其转换为像素。
阅读全文