// PointInPolygonDlg.cpp : implementation file
//
#include "stdafx.h"
#include "PointInPolygon.h"
#include "PointInPolygonDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
inline int
isLeft( CPoint *P0, CPoint *P1, CPoint *P2 )
{
return ( (P1->x - P0->x) * (P2->y - P0->y)
- (P2->x - P0->x) * (P1->y - P0->y) );
}
bool CPointInPolygonDlg::PointPolygonAlgorithm(CPoint *pt)
{
int wn = 0; // the winding number counter
std::vector<CPoint *>::iterator it;
// loop through all edges of the polygon
for (it=vPolygon.begin(); it<vPolygon.end()-1; it++)// edge from V[i] to V[i+1]
{
if ((*(it))->y <= pt->y) { // start y <= pt->y
if ((*(it+1))->y > pt->y) // an upward crossing
if (isLeft( *it, *(it+1), pt) > 0) // P left of edge
++wn; // have a valid up intersect
}
else { // start y > P.y (no test needed)
if ((*(it+1))->y <= pt->y) // a downward crossing
if (isLeft( *it, *(it+1), pt) < 0) // P right of edge
--wn; // have a valid down intersect
}
}
if (wn==0)
return false;
return true;
}
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
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()
// CPointInPolygonDlg dialog
CPointInPolygonDlg::CPointInPolygonDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPointInPolygonDlg::IDD, pParent),
m_state(setpoints)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
CPointInPolygonDlg::~CPointInPolygonDlg()
{
if (m_state == testpoint)
vPolygon.erase(vPolygon.end()-1);
std::vector<CPoint *>::iterator it;
for(it=vPolygon.begin(); it<vPolygon.end(); ++it)
delete *it;
}
void CPointInPolygonDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPointInPolygonDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_WM_LBUTTONDOWN()
ON_BN_CLICKED(IDC_BTESTPOINT, OnBnClickedBtestpoint)
ON_BN_CLICKED(IDC_BDRAW, OnBnClickedBdraw)
END_MESSAGE_MAP()
// CPointInPolygonDlg message handlers
BOOL CPointInPolygonDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 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
return TRUE; // return TRUE unless you set the focus to a control
}
void CPointInPolygonDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 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 CPointInPolygonDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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
{
CPaintDC dc(this);
std::vector<CPoint *>::iterator it;
for (it=vPolygon.begin(); it<vPolygon.end();)
{
dc.MoveTo(**it);
++it;
if(it<vPolygon.end())
dc.LineTo(**it);
else
dc.LineTo(**vPolygon.begin());
}
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CPointInPolygonDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CPointInPolygonDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
if(((point.x<380) && (point.x>12)) && ((point.y<283) && (point.y>17)))
{
if(m_state==setpoints)
{
CPoint *p = new CPoint;
p->x = point.x;
p->y = point.y;
vPolygon.push_back(p);
InvalidateRect(CRect(12,17,380,283));
}
else
{
if (PointPolygonAlgorithm(&point))
MessageBox("This point IS INSIDE the polygon");
else
MessageBox("This point IS OUTSIDE the polygon");
}
}
CDialog::OnLButtonDown(nFlags, point);
}
void CPointInPolygonDlg::OnBnClickedBtestpoint()
{
if(vPolygon.size()<3)
MessageBox("Please draw a polygon, and then click on this button");
else
{
vPolygon.push_back(vPolygon.at(0));
m_state=testpoint;
}
}
void CPointInPolygonDlg::OnBnClickedBdraw()
{
if (m_state == testpoint)
vPolygon.erase(vPolygon.end()-1);
std::vector<CPoint *>::iterator it;
for(it=vPolygon.begin(); it<vPolygon.end(); ++it)
delete *it;
vPolygon.clear();
m_state = setpoints;
InvalidateRect(CRect(12,17,380,283));
}