Подскажите пожалуиста алгоритм не могу ничего придумать(С/C++)
Задание:
Разработать программу построения круговой диаграммы по данным.
По результатам опроса на тему: "Какой протокол вы предпочитаете для личного и рабочего общения?" получены следующие результаты:
Jabber - 2278 (37,06%)
ICQ - 1598 (26,00%)
Google Talk - 741 (12,05%)
Skype - 739 (12,02%)
Предпочитаю общаться лично - 598 (9,73%)
Другая - 132 (2,15%)
Windows Live Messenger - 54 (0,88%)
AIM - 7 (0,11%)
Код:
#include <graphics.h>
#include <stdio.h>
main()
{
int graphdriver=DETECT, graphmode;
int z;
float s=0,a[8] = {37.06,26,12.05,12.02,9.73,2.15,0.88,0.11};
initgraph(&graphdriver, &graphmode, "");
for(z=0;z<8;z++)
{
s = (360*a[z]/100);
setfillstyle(1,z);
sector(300,300,0,s,100,100); /* ???*/
}
getch();
}
#include <stdio.h>
main()
{
int graphdriver=DETECT, graphmode;
int z;
float s=0,a[8] = {37.06,26,12.05,12.02,9.73,2.15,0.88,0.11};
initgraph(&graphdriver, &graphmode, "");
for(z=0;z<8;z++)
{
s = (360*a[z]/100);
setfillstyle(1,z);
sector(300,300,0,s,100,100); /* ???*/
}
getch();
}
GDI и сообщение WM_PAINT обрабатываемое для каждого окна созданного при помощи
CreateWindow или потомка СWnd в MFC.
Среди этих функций можно найти функции Pie и Arc. Они такие же как ф-ция sector в библиотеке graphics.h.
Pie(x1,y1,x2,y2,xr1,yr1,xr2,yr2) - рисует круговой сегмент
Arc(x1,y1,x2,y2,xr1,yr1,xr2,yr2) - рисует дугу окружности
Вообще-то, работать с этими функциями сложно. Для задания величины угла дуги, необходимо рассчитывать
"хорду" так называемое расстояние между точками xr1 и xr2, yr1 и yr2.
Но как всегда есть идея как решить данную проблему (см. исходник ниже)
Код:
// ChildView.cpp : implementation of the CChildView class
//
#include "stdafx.h"
#include "RDiagram.h"
#include "ChildView.h"
#include <cmath>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define PI 3.14159265
typedef struct tagUsageData
{
LPTSTR m_lpszProtocolName;
int m_nUsers;
double m_nPercent;
COLORREF m_clr;
} USAGEDATA, NEAR *PUSAGEDATA, FAR *LPUSAGEDATA;
static USAGEDATA g_lpUsageData[] = { { TEXT("Jabber"), 2278, 37.06, RGB(10,110,56) },
{ TEXT("ICQ"), 1598, 26.00, RGB(50,60,110) },
{ TEXT("Google Talk"), 741, 12.05, RGB(130,110,16) },
{ TEXT("Skype"), 739, 12.02, RGB(60,85,156) },
{ TEXT("Предпочитаю общаться лично"), 598, 9.73, RGB(200,137,97) },
{ TEXT("Другая"), 132, 2.15, RGB(110,110,56) },
{ TEXT("Windows Live Messanger"), 54, 0.88, RGB(15,15,165) },
{ TEXT("AIM"), 7, 0.11, RGB(38,192,141) },
{ NULL, 0, 0.00, RGB(0,0,0) } };
// CChildView
CChildView::CChildView()
{
}
CChildView::~CChildView()
{
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_MESSAGE(WM_PAINT, OnPaint)
END_MESSAGE_MAP()
// CChildView message handlers
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CWnd::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle |= WS_EX_CLIENTEDGE;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);
return TRUE;
}
// TODO: Add your message handler code here
LRESULT CChildView::OnPaint(WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hPaintDC = NULL;
if ((hPaintDC = ::BeginPaint(m_hWnd, &ps)) != NULL)
{
RECT rcChart;
rcChart.left = 100; rcChart.top = 100;
rcChart.right = 500; rcChart.bottom = 500;
double nRadius = 0;
if ((nRadius = GetSliceRadius(rcChart)) > 0 &&
IsQuadrant(rcChart))
{
POINT ptSliceStart, ptSliceEnd;
ptSliceStart.x = rcChart.right;
ptSliceStart.y = rcChart.top + nRadius;
double nTotalPercent = 0;
for (int iIndex = 0; g_lpUsageData[iIndex].m_nUsers != 0; iIndex++)
{
if ((g_lpUsageData[iIndex].m_nPercent > 0) &&
(g_lpUsageData[iIndex].m_clr != 0))
{
HBRUSH hOldBrush = NULL;
HBRUSH hFillBrush = ::CreateSolidBrush(g_lpUsageData[iIndex].m_clr);
if (hFillBrush != NULL)
hOldBrush = (HBRUSH)::SelectObject(hPaintDC, hFillBrush);
nTotalPercent+=g_lpUsageData[iIndex].m_nPercent;
GetSliceCoord(rcChart, GetSliceRadius(rcChart), nTotalPercent, &ptSliceEnd);
::Pie(hPaintDC,rcChart.left, rcChart.top, rcChart.right, rcChart.bottom,
ptSliceStart.x, ptSliceStart.y, ptSliceEnd.x, ptSliceEnd.y);
::SelectObject(hPaintDC, hOldBrush);
ptSliceStart = ptSliceEnd;
}
}
}
::EndPaint(m_hWnd, &ps);
}
return 0;
}
void CChildView::GetSliceCoord(const RECT& rcChart, const double& nRadius,
const double& nPercent, POINT* pptSlice)
{
ASSERT(pptSlice != NULL);
pptSlice->x = (rcChart.right - nRadius) +
nRadius * cos(double((3.6 * nPercent) * PI / 180));
pptSlice->y = (rcChart.bottom - nRadius) -
nRadius * sin(double((3.6 * nPercent) * PI / 180));
}
double CChildView::GetSliceRadius(const RECT& rcChart)
{ return double((rcChart.bottom - rcChart.top) / 2); }
bool CChildView::IsQuadrant(const RECT& rcChart)
{ return ((rcChart.bottom - rcChart.top) ==
(rcChart.right - rcChart.left)); }
//
#include "stdafx.h"
#include "RDiagram.h"
#include "ChildView.h"
#include <cmath>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define PI 3.14159265
typedef struct tagUsageData
{
LPTSTR m_lpszProtocolName;
int m_nUsers;
double m_nPercent;
COLORREF m_clr;
} USAGEDATA, NEAR *PUSAGEDATA, FAR *LPUSAGEDATA;
static USAGEDATA g_lpUsageData[] = { { TEXT("Jabber"), 2278, 37.06, RGB(10,110,56) },
{ TEXT("ICQ"), 1598, 26.00, RGB(50,60,110) },
{ TEXT("Google Talk"), 741, 12.05, RGB(130,110,16) },
{ TEXT("Skype"), 739, 12.02, RGB(60,85,156) },
{ TEXT("Предпочитаю общаться лично"), 598, 9.73, RGB(200,137,97) },
{ TEXT("Другая"), 132, 2.15, RGB(110,110,56) },
{ TEXT("Windows Live Messanger"), 54, 0.88, RGB(15,15,165) },
{ TEXT("AIM"), 7, 0.11, RGB(38,192,141) },
{ NULL, 0, 0.00, RGB(0,0,0) } };
// CChildView
CChildView::CChildView()
{
}
CChildView::~CChildView()
{
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_MESSAGE(WM_PAINT, OnPaint)
END_MESSAGE_MAP()
// CChildView message handlers
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CWnd::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle |= WS_EX_CLIENTEDGE;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);
return TRUE;
}
// TODO: Add your message handler code here
LRESULT CChildView::OnPaint(WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hPaintDC = NULL;
if ((hPaintDC = ::BeginPaint(m_hWnd, &ps)) != NULL)
{
RECT rcChart;
rcChart.left = 100; rcChart.top = 100;
rcChart.right = 500; rcChart.bottom = 500;
double nRadius = 0;
if ((nRadius = GetSliceRadius(rcChart)) > 0 &&
IsQuadrant(rcChart))
{
POINT ptSliceStart, ptSliceEnd;
ptSliceStart.x = rcChart.right;
ptSliceStart.y = rcChart.top + nRadius;
double nTotalPercent = 0;
for (int iIndex = 0; g_lpUsageData[iIndex].m_nUsers != 0; iIndex++)
{
if ((g_lpUsageData[iIndex].m_nPercent > 0) &&
(g_lpUsageData[iIndex].m_clr != 0))
{
HBRUSH hOldBrush = NULL;
HBRUSH hFillBrush = ::CreateSolidBrush(g_lpUsageData[iIndex].m_clr);
if (hFillBrush != NULL)
hOldBrush = (HBRUSH)::SelectObject(hPaintDC, hFillBrush);
nTotalPercent+=g_lpUsageData[iIndex].m_nPercent;
GetSliceCoord(rcChart, GetSliceRadius(rcChart), nTotalPercent, &ptSliceEnd);
::Pie(hPaintDC,rcChart.left, rcChart.top, rcChart.right, rcChart.bottom,
ptSliceStart.x, ptSliceStart.y, ptSliceEnd.x, ptSliceEnd.y);
::SelectObject(hPaintDC, hOldBrush);
ptSliceStart = ptSliceEnd;
}
}
}
::EndPaint(m_hWnd, &ps);
}
return 0;
}
void CChildView::GetSliceCoord(const RECT& rcChart, const double& nRadius,
const double& nPercent, POINT* pptSlice)
{
ASSERT(pptSlice != NULL);
pptSlice->x = (rcChart.right - nRadius) +
nRadius * cos(double((3.6 * nPercent) * PI / 180));
pptSlice->y = (rcChart.bottom - nRadius) -
nRadius * sin(double((3.6 * nPercent) * PI / 180));
}
double CChildView::GetSliceRadius(const RECT& rcChart)
{ return double((rcChart.bottom - rcChart.top) / 2); }
bool CChildView::IsQuadrant(const RECT& rcChart)
{ return ((rcChart.bottom - rcChart.top) ==
(rcChart.right - rcChart.left)); }
В класс CChildView добавить все функции относящиеся к проекту.
Также можно попробовать перенести это все под BGI #include <graphics.h>, в том случае если
функция sector делает то же самое, что и Pie в Win32API GDI. Смотри сам, я специально не
смотрел.