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

📄 convexhullview.cpp

📁 Gramham法求解凸包。从最基本数据结构定义开始实现
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ConvexHullView.cpp : implementation of the CConvexHullView class
//

#include "stdafx.h"
#include "ConvexHull.h"

#include "MainFrm.h"
#include "ConvexHullDoc.h"
#include "ConvexHullView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CConvexHullView

IMPLEMENT_DYNCREATE(CConvexHullView, CView)

BEGIN_MESSAGE_MAP(CConvexHullView, CView)
	//{{AFX_MSG_MAP(CConvexHullView)
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEWHEEL()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_TIMER()
	ON_WM_RBUTTONDOWN()
	ON_WM_SETCURSOR()
	ON_WM_SIZE()
	ON_WM_DESTROY()
	//}}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()

/////////////////////////////////////////////////////////////////////////////
// CConvexHullView construction/destruction

//##ModelId=443378C802AC
CConvexHullView::CConvexHullView()
{
	// TODO: add construction code here
    m_AxisXOffset = 0;
    m_AxisYOffset = 0;
    m_ZoomRatio = 10;
    m_IsDragging = FALSE;
    m_ClientStatus = CLIENT_STATUS_NONE;
    m_IsDemoPaused = FALSE;

    m_BufferDCReady = FALSE;
    m_pBufferOldBitmap = NULL;

    m_BufferDC.CreateCompatibleDC(NULL);

    m_ScaleFont.CreateFont(
       12,                        // nHeight
       0,                         // nWidth
       0,                         // nEscapement
       0,                         // nOrientation
       FW_NORMAL,                 // nWeight
       FALSE,                     // bItalic
       FALSE,                     // bUnderline
       0,                         // cStrikeOut
       ANSI_CHARSET,              // nCharSet
       OUT_DEFAULT_PRECIS,        // nOutPrecision
       CLIP_DEFAULT_PRECIS,       // nClipPrecision
       DEFAULT_QUALITY,           // nQuality
       DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
       "宋体");                   // lpszFacename

}

//##ModelId=443378C803B0
CConvexHullView::~CConvexHullView()
{
}

//##ModelId=443378C8036D
BOOL CConvexHullView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CConvexHullView drawing

//##ModelId=443378C8036A
void CConvexHullView::OnDraw(CDC* pDC)
{
    CRect r;
    GetClientRect(r);
    DrawView(&m_BufferDC, r);
    pDC->BitBlt(0, 0, r.Width(), r.Height(), &m_BufferDC, 0, 0, SRCCOPY);
}

//##ModelId=443378C80357
void CConvexHullView::DrawView(CDC* pDC, CRect &r)
{

	CConvexHullDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

    dse::point2d p, p1;
    CString s, fmtString;
    CPen *oldPen;
    CPen pen;
    CBrush *oldBrush;
    CBrush brush;
    CFont *oldFont;
    
    int scale_i;

    dse::size_t i, count;
    dse::vector<dse::pair<int, double> > clientScaleXs, clientScaleYs;

    brush.CreateSolidBrush(0xffffff);
    pDC->FillRect(r, &brush);
    brush.DeleteObject();


    pDC->SetBkMode(TRANSPARENT);

    //计算主坐标轴在客户区的位置
    AxisPointToClientPoint(dse::point2d(0,0), r, p);
    double clientAxisX = p.x, clientAxisY = p.y;

    //计算刻度所需的数据
    ClientPointToAxisPoint(dse::point2d(0,0), r, p);
    double axisLeft = p.x, axisTop = p.y;   //可见坐标范围
    ClientPointToAxisPoint(dse::point2d(r.Width(), r.Height()), r, p);
    double axisRight = p.x, axisBottom = p.y;  //可见坐标范围
    ClientPointToAxisPoint(dse::point2d(60, 0), r, p);
    double axisScale = p.x - axisLeft;  //坐标刻度长度,以客户区的60个像素左右作为一个刻度
    

    //对刻度长度进行修正,保证整的刻度
    double n;
    if(axisScale < 1)
    {
        for(n = 1; axisScale < 1; n *= 10)
            axisScale *= 10;
        axisScale = (int)axisScale;
        axisScale /= n;
        fmtString.Format("%%.%dlf", (int)log10(n));
    }
    else
    {
        for(n = 1; axisScale >= 10; n *= 10)
            axisScale /= 10;
        axisScale = (int)axisScale;
        axisScale *= n;
        fmtString.Format("%%.0lf");
    }
    
    //计算坐标刻度反映在客户区实际的实际长度
    AxisPointToClientPoint(dse::point2d(axisScale, 0.0), r, p);
    AxisPointToClientPoint(dse::point2d(0.0, 0.0), r, p1);
    double clientScaleStep = p.x - p1.x;

    //计算各个坐标在屏幕上对应的位置(pair.first),以及刻度(pair.second),并保存
    for(scale_i = (int)((0 - clientAxisX) / clientScaleStep - 1); scale_i < ((double)r.Width() - clientAxisX) / clientScaleStep + 1; scale_i++)
        clientScaleXs.push_back(dse::make_pair(
                                                (int)(clientAxisX + clientScaleStep * scale_i),
                                                axisScale * scale_i
                                                )
                               );
    for(scale_i = (int)((0 - clientAxisY) / clientScaleStep - 1); scale_i < ((double)r.Height() - clientAxisY) / clientScaleStep + 1; scale_i++)
        clientScaleYs.push_back(dse::make_pair(
                                                (int)(clientAxisY + clientScaleStep * scale_i),
                                                - axisScale * scale_i
                                                )
                               );


    //绘制辅助坐标轴
    pen.CreatePen(PS_SOLID, 1, 0x00e0e0e0);
    oldPen = pDC->SelectObject(&pen);
    for(i = 0; i < clientScaleYs.size(); i++)
    { 
        pDC->MoveTo(0 , clientScaleYs[i].first);
        pDC->LineTo(r.Width(), clientScaleYs[i].first);
    }
    for(i = 0; i < clientScaleXs.size(); i++)
    {
        pDC->MoveTo(clientScaleXs[i].first, 0);
        pDC->LineTo(clientScaleXs[i].first, r.Height());
    }
    pDC->SelectObject(oldPen);
    pen.DeleteObject();


    //绘制主坐标轴和刻度
    pen.CreatePen(PS_SOLID, 1, (ULONG)0x00000000);
    oldFont = pDC->SelectObject(&m_ScaleFont);
    oldPen = pDC->SelectObject(&pen);
    if(0 <= clientAxisY && clientAxisY < r.Height())
    {
        pDC->MoveTo(0, (int)clientAxisY);
        pDC->LineTo(r.Width(), (int)clientAxisY);

        for(i = 0; i < clientScaleXs.size(); i++)
        {
            pDC->MoveTo(clientScaleXs[i].first, (int)clientAxisY);
            pDC->LineTo(clientScaleXs[i].first, (int)clientAxisY + 10);

            s.Format(fmtString, clientScaleXs[i].second);
            pDC->TextOut(clientScaleXs[i].first - 2, (int)clientAxisY + 12, s);
        }
    }

    if(0 <= clientAxisX && clientAxisX < r.Width())
    {
        pDC->MoveTo((int)clientAxisX, 0);
        pDC->LineTo((int)clientAxisX, r.Height());

        for(i = 0; i < clientScaleYs.size(); i++)
        { 
            pDC->MoveTo((int)clientAxisX , clientScaleYs[i].first);
            pDC->LineTo((int)clientAxisX - 10, clientScaleYs[i].first);

            if(IS_ZERO(clientScaleYs[i].second))
                continue;
            s.Format(fmtString  , clientScaleYs[i].second);
            pDC->TextOut((int)clientAxisX - 40, clientScaleYs[i].first + 2, s);
        }

    }
    pDC->SelectObject(oldPen);
    pDC->SelectObject(oldFont);
    pen.DeleteObject();

    //凸包的点
    dse::convex_hull &ch = pDoc->GetConvexHull();
    
    //pen.CreatePen(PS_SOLID, 1, 0x00ffff);
    pen.CreatePen(PS_SOLID, 1, 0x0000ff);
    brush.CreateSolidBrush(0x0000ff);
    oldBrush = pDC->SelectObject(&brush);
    oldPen = pDC->SelectObject(&pen);
    count = ch.get_points_count();
    for(i = 0; i < count; i++)
    {
        AxisPointToClientPoint(ch.get_point(i), r, p);
        pDC->Ellipse((int)p.x-3, (int)p.y-3, (int)p.x+3, (int)p.y+3);
    }
    pDC->SelectObject(oldBrush);
    pDC->SelectObject(oldPen);
    brush.DeleteObject();
    pen.DeleteObject();


    //凸包的边
    pen.CreatePen(PS_SOLID, 1, 0xff0000);
    oldPen = pDC->SelectObject(&pen);
    count = ch.get_convex_points_count();
    for(i = 1; i <= count; i++)
    {

        AxisPointToClientPoint(ch.get_convex_point(i-1), r, p);
        pDC->MoveTo((int)p.x, (int)p.y);

        if(i == count)
        {
            if(!ch.finished())  //如果没有完成,不必画最后一条边
                break;  
            AxisPointToClientPoint(ch.get_convex_point(0), r, p);
        }
        else
            AxisPointToClientPoint(ch.get_convex_point(i), r, p);
        pDC->LineTo((int)p.x, (int)p.y);
    }
    pDC->SelectObject(oldPen);
    pen.DeleteObject();


    //如果是演示状态,并且有点需要处理,则用特殊颜色把当前处理的过程显示出来
    if(IsClientStatus_Demo() && ch.has_next_point())
    {
        pen.CreatePen(PS_SOLID, 1, 0xff00ff);
        brush.CreateSolidBrush(0x00ff00);
        oldPen = pDC->SelectObject(&pen);
        oldBrush = pDC->SelectObject(&brush);
        count = ch.get_convex_points_count();
        
        AxisPointToClientPoint(ch.get_convex_point(count - 1), r, p);
        pDC->Ellipse((int)p.x-4, (int)p.y-4, (int)p.x+4, (int)p.y+4);
        pDC->MoveTo((int)p.x, (int)p.y);
        AxisPointToClientPoint(ch.get_point(ch.get_next_point_index()), r, p);
        pDC->LineTo((int)p.x, (int)p.y);
        pDC->Ellipse((int)p.x-4, (int)p.y-4, (int)p.x+4, (int)p.y+4);

        pDC->SelectObject(oldBrush);
        pDC->SelectObject(oldPen);
        pen.DeleteObject();
        brush.DeleteObject();
    }
}

/////////////////////////////////////////////////////////////////////////////
// CConvexHullView printing

//##ModelId=443378C80393
BOOL CConvexHullView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

//##ModelId=443378C8039C
void CConvexHullView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

//##ModelId=443378C803A6
void CConvexHullView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CConvexHullView diagnostics

#ifdef _DEBUG
//##ModelId=443378C803B2
void CConvexHullView::AssertValid() const
{
	CView::AssertValid();
}

//##ModelId=443378C803BB
void CConvexHullView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

//##ModelId=443378C8030B
CConvexHullDoc* CConvexHullView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CConvexHullDoc)));
	return (CConvexHullDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CConvexHullView message handlers

//##ModelId=443378C80376
BOOL CConvexHullView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	// TODO: Add your specialized code here and/or call the base class
	
	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}

//##ModelId=443378C8038B
void CConvexHullView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
    SetClientStatus(CLIENT_STATUS_NONE);
    ZoomAdjust();
}

/*
坐标变换,从客户端窗口坐标变换到坐标轴坐标
*/
//##ModelId=443378C80342
VOID CConvexHullView::ClientPointToAxisPoint(dse::point2d &p, CRect &clientRect, dse::point2d &out)
{
    double cmX, cmY;
    cmX = clientRect.left + clientRect.Width() / 2;
    cmY = clientRect.top + clientRect.Height() / 2;
    double sX, sY;
    sX = p.x - cmX;
    sY = -(p.y - cmY);
    sX /= m_ZoomRatio;
    sY /= m_ZoomRatio;
    sX -= m_AxisXOffset;
    sY -= m_AxisYOffset;

    out.x = sX;

⌨️ 快捷键说明

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