Click here to Skip to main content
15,887,822 members
Articles / Desktop Programming / MFC

A Matrix-Based 2-D Polygon Clipping Class

Rate me:
Please Sign up or sign in to vote.
3.50/5 (40 votes)
28 Mar 2003CDDL8 min read 199.9K   4.7K   58  
An article on 2-D Polygon Clipping
// PolyClipDemoView.cpp : implementation of the CPolyClipDemoView class
//

#include "stdafx.h"
#include "PolyClipDemo.h"

#include "PolyClipDemoDoc.h"
#include "PolyClipDemoView.h"

#include "PolygonClip.h"

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

#define NumberOfLines 10
#define NumberOfVerticies 9		// one more than the actual number (See below)
	
/////////////////////////////////////////////////////////////////////////////
// CPolyClipDemoView

IMPLEMENT_DYNCREATE(CPolyClipDemoView, CView)

BEGIN_MESSAGE_MAP(CPolyClipDemoView, CView)
	//{{AFX_MSG_MAP(CPolyClipDemoView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}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()

/////////////////////////////////////////////////////////////////////////////
// CPolyClipDemoView construction/destruction

CPolyClipDemoView::CPolyClipDemoView()
{
	// TODO: add construction code here
	m_pPolygonClip = 0;

}

CPolyClipDemoView::~CPolyClipDemoView()
{
}

BOOL CPolyClipDemoView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CPolyClipDemoView drawing

void CPolyClipDemoView::OnDraw(CDC* pDC)
{
	CPolyClipDemoDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	// The code below is far from fancy, but it serves
	// to illustrate the idea...most of this shouldn't be
	// in OnDraw() -> Lines and polygons shouldn't be
	// generated here (slows things down during drawing)
	// but I'm lazy and all the important stuff can be found here
	// so it makes it easier to see what's happenin'
	double *pLineX1, *pLineX2, *pLineY1, *pLineY2;	
	double *pPolyVertsX, *pPolyVertsY;

	pLineX1 = new double[NumberOfLines];
	pLineX2 = new double[NumberOfLines];

	pLineY1 = new double[NumberOfLines];
	pLineY2 = new double[NumberOfLines];

	pPolyVertsX = new double[NumberOfVerticies];
	pPolyVertsY = new double[NumberOfVerticies];

	// Arbitrary origin for the lines
	double LineOrigin(/*100*/80);

	// Generate some line coordinates and fill arrays
	for (unsigned int LineIndex = 0; LineIndex < 10; LineIndex++)
	{
		ASSERT(LineIndex < NumberOfLines);

		if (LineIndex < 5)		// Make horizontal lines
		{
			*(pLineX1 + LineIndex) = 100;
			*(pLineY1 + LineIndex) = LineOrigin + 53;

			*(pLineX2 + LineIndex) = GetSystemMetrics(SM_CXSCREEN) - 1000;
			*(pLineY2 + LineIndex) = LineOrigin;
		}
		else					// Make vertical lines
		{
			*(pLineX1 + LineIndex) = LineOrigin - 120;
			*(pLineY1 + LineIndex) = 100;

			*(pLineX2 + LineIndex) = LineOrigin - 167;
			*(pLineY2 + LineIndex) = GetSystemMetrics(SM_CYSCREEN) - 650;
		}

		LineOrigin += 50;
		
		pDC->MoveTo(*(pLineX1 + LineIndex), *(pLineY1 + LineIndex));
		pDC->LineTo(*(pLineX2 + LineIndex), *(pLineY2 + LineIndex));
	}
	
	// And now the polygon...
	for (unsigned int VertexIndex = 0; VertexIndex < 9; VertexIndex++)
	{
		ASSERT(VertexIndex < NumberOfVerticies);
		switch (VertexIndex) 
		{
			case 0:		// Vertex 1
				*(pPolyVertsX + VertexIndex) = 160;
				*(pPolyVertsY + VertexIndex) = /*160*/220;
				break;
			case 1:		// Vertex 2
				*(pPolyVertsX + VertexIndex) = 190;
				*(pPolyVertsY + VertexIndex) = /*160*/220;
				break;
			case 2:		// Vertex 3
				*(pPolyVertsX + VertexIndex) = 190;
				*(pPolyVertsY + VertexIndex) = 220;
				break;
			case 3:		// Vertex 4
				*(pPolyVertsX + VertexIndex) = /*225*/155;
				*(pPolyVertsY + VertexIndex) = 220;
				break;
			case 4:		// etc...
				*(pPolyVertsX + VertexIndex) = /*225*/155;
				*(pPolyVertsY + VertexIndex) = 160;
				break;
			case 5:		
				*(pPolyVertsX + VertexIndex) = GetSystemMetrics(SM_CXSCREEN) - 1200;
				*(pPolyVertsY + VertexIndex) = 160;
				break;
			case 6:		
				*(pPolyVertsX + VertexIndex) = GetSystemMetrics(SM_CXSCREEN) - 1200;
				*(pPolyVertsY + VertexIndex) = 600;
				break;
			case 7:		
				*(pPolyVertsX + VertexIndex) = /*160*/240;
				*(pPolyVertsY + VertexIndex) = /*600*/400;
				break;
			case 8:		// Close the polygon by ending up at the 1st point
				*(pPolyVertsX + VertexIndex) = 160;
				*(pPolyVertsY + VertexIndex) = 160;
				break;
			default:	// Error
				AfxMessageBox("Error.\n Cannot assign vertex.");		
				AfxAbort();  // Cheesy bail-out
		}
	}
	
	CPen aPen;
	aPen.CreatePen(PS_SOLID, PenSize, RGB(255, 0, 0));	
	CPen* pOldPen = pDC->SelectObject(&aPen);
	
	// Draw the polygon lines so we can see it
	for (unsigned int i = 0; i < (NumberOfVerticies - 1); i++)
	{
		ASSERT(i < VertexIndex);
		
		pDC->MoveTo(*(pPolyVertsX + i), *(pPolyVertsY + i));
		pDC->LineTo(*(pPolyVertsX + (i + 1)), *(pPolyVertsY + (i + 1)));
	}
	
	pDC->SelectObject(pOldPen);

	//////////////////////////////////
	//    BEGIN POLYGON CLIPPING	//
	//////////////////////////////////
	m_pPolygonClip = new CPolygonClip(NumberOfVerticies, NumberOfLines);
	ASSERT(m_pPolygonClip != NULL);

	unsigned int* pnSignChanges = 0;
	
	// Calculate the determinants
	pnSignChanges = m_pPolygonClip->CalcSiDeterm(pLineX1, pLineY1, 
												 pLineX2, pLineY2, 
												 pPolyVertsX, pPolyVertsY);

	// Find maximum number of intersections
	unsigned int nNumChanges = m_pPolygonClip->FindArrayMax(pnSignChanges);

	// Calculate line/polygon intersections
	bool bSuccess = m_pPolygonClip->CalculateIntersections(pLineX1, pLineX2,
														   pLineY1, pLineY2, 
														   pPolyVertsX, pPolyVertsY,
														   nNumChanges);
	// should include some other error 
	// handling routine...try/catch, etc...
	ASSERT(bSuccess);		

	// Draw the intersection points
	m_pPolygonClip->Draw(pDC);
	//////////////////////////////////
	//    END POLYGON CLIPPING		//
	//////////////////////////////////


	// Free the heap
	delete[] pLineX1;
	delete[] pLineX2;
	delete[] pLineY1;
	delete[] pLineY2;
	delete[] pPolyVertsX;
	delete[] pPolyVertsY;

	// Don't forget...
	delete m_pPolygonClip;

}

/////////////////////////////////////////////////////////////////////////////
// CPolyClipDemoView printing

BOOL CPolyClipDemoView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CPolyClipDemoView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CPolyClipDemoView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CPolyClipDemoView diagnostics

#ifdef _DEBUG
void CPolyClipDemoView::AssertValid() const
{
	CView::AssertValid();
}

void CPolyClipDemoView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CPolyClipDemoDoc* CPolyClipDemoView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPolyClipDemoDoc)));
	return (CPolyClipDemoDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CPolyClipDemoView message handlers

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Other
Anonymous Proxy Anonymous Proxy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions