📄 chart.cpp
字号:
// ********************************************************// This is demo code. You may derive from, use, modify, and// distribute it without limitation for any purpose.// Obviously you don't get a warranty or an assurance of// fitness for a particular purpose with this code. Your// welcome to remove this header and claim original// authorship. I really don't care.// ********************************************************#include "Chart.h"#ifdef WIN32#else // WIN32#include <unistd.h>#endif // !WIN32#include "../GClasses/GArff.h"#include "../GClasses/GBits.h"#include "../GClasses/GFile.h"#include "../GClasses/GTime.h"#include "../GClasses/GMacros.h"#include "../GClasses/GThread.h"#include "../GClasses/GGreedySearch.h"#include <math.h>class ChartDialog : public GWidgetDialog{friend class ChartController;protected: ChartController* m_pController; GWidgetFileSystemBrowser* m_pFileSystemBrowser; GWidgetTextButton* m_pLineGraphButton; GWidgetTextButton* m_pLogLineGraphButton; GWidgetTextButton* m_pComputeBigOButton;public: ChartDialog(ChartController* pController, int w, int h) : GWidgetDialog(w, h, 0xff338822) { m_pController = pController; GString s; s.Copy(L"Begin"); m_pFileSystemBrowser = new GWidgetFileSystemBrowser(this, 100, 100, 500, 190, ".arff"); m_pFileSystemBrowser->Draw(this); m_pLineGraphButton = NULL; m_pLogLineGraphButton = NULL; m_pComputeBigOButton = NULL; } virtual ~ChartDialog() { } virtual void OnReleaseTextButton(GWidgetTextButton* pButton) { if(pButton == m_pLineGraphButton) m_pController->MakeLineGraphChart(false); else if(pButton == m_pLogLineGraphButton) m_pController->MakeLineGraphChart(true); else if(pButton == m_pComputeBigOButton) m_pController->ComputeBigO(); } void ShowChartButtons() { GString s; s.Copy(L"Line Graph"); m_pLineGraphButton = new GWidgetTextButton(this, 100, 400, 150, 24, &s); s.Copy(L"Log Line Graph"); m_pLogLineGraphButton = new GWidgetTextButton(this, 100, 450, 150, 24, &s); s.Copy(L"Compute Big-O"); m_pComputeBigOButton = new GWidgetTextButton(this, 300, 400, 150, 24, &s); } virtual void OnSelectFilename(GWidgetFileSystemBrowser* pBrowser, const char* szFilename) { m_pController->OnSelectFile(szFilename); ShowChartButtons(); }};// ----------------------------------------------------------------------------ChartView::ChartView(ChartController* pController): ViewBase(){ m_pDialog = new ChartDialog(pController, m_screenRect.w, m_screenRect.h); m_pImage = NULL;}ChartView::~ChartView(){ delete(m_pDialog);}/*virtual*/ void ChartView::Draw(SDL_Surface *pScreen){ GRect r; GImage* pCanvas = m_pDialog->GetImage(&r); BlitImage(pScreen, m_screenRect.x, m_screenRect.y, pCanvas);}void ChartView::OnChar(char c){ m_pDialog->HandleChar(c);}void ChartView::OnMouseDown(int x, int y){ x -= m_screenRect.x; y -= m_screenRect.y; GWidgetAtomic* pNewWidget = m_pDialog->FindAtomicWidget(x, y); m_pDialog->GrabWidget(pNewWidget, x, y);}void ChartView::OnMouseUp(int x, int y){ m_pDialog->ReleaseWidget();}bool ChartView::OnMousePos(int x, int y){ return m_pDialog->HandleMousePos(x - m_screenRect.x, y - m_screenRect.y);}// -------------------------------------------------------------------------------ChartController::ChartController(): ControllerBase(){ m_pView = new ChartView(this); m_pData = NULL; m_pRelation = NULL;}ChartController::~ChartController(){ delete(m_pView); delete(m_pRelation); delete(m_pData);}void ChartController::OnSelectFile(const char* szFilename){ int nLen; Holder<char*> hFile = GFile::LoadFileToBuffer(szFilename, &nLen); if(!hFile.Get()) throw "File not found"; m_pRelation = GArffRelation::ParseFile(&m_pData, hFile.Get(), nLen); if(!m_pRelation) throw "Failed to parse ARFF file";}void ChartController::RunModal(){ double timeOld = GTime::GetTime(); double time; double timeUpdate = 0; m_pView->Update(); while(m_bKeepRunning) { time = GTime::GetTime(); if(HandleEvents(time - timeOld)) // HandleEvents returns true if it thinks the view needs to be updated { m_pView->Update(); timeUpdate = time; } else { GThread::sleep(10); } timeOld = time; }}void ChartController::MakeLineGraphChart(bool bLogarithmic){int j;for(j = 1; j < m_pRelation->GetAttributeCount(); j++) m_pRelation->GetAttribute(j)->SetIsInput(false); // Compute the size of the image int nBorderSize = 20; int nChartWidth = 440; int nChartHeight = 440; if(m_pRelation->GetOutputCount() <= 0) { GAssert(m_pRelation->GetOutputCount() > 0, "There are no output values to chart"); throw "There are no output values to chart"; } GImage image; image.SetSize(2 * nBorderSize + nChartWidth, nBorderSize + m_pRelation->GetInputCount() * (nChartHeight + nBorderSize)); image.Clear(0xffaaaaaa); // Make a chart for each input attribute int nInput, nOutput, i; for(nInput = 0; nInput < m_pRelation->GetInputCount(); nInput++) { // Compute the chart ranges double dInputMin, dInputRange, dOutputMin, dOutputRange, dTmpMin, dTmpRange; m_pData->GetMinAndRange(m_pRelation->GetInputIndex(nInput), &dInputMin, &dInputRange); m_pData->GetMinAndRange(m_pRelation->GetOutputIndex(0), &dOutputMin, &dOutputRange); for(nOutput = 1; nOutput < m_pRelation->GetOutputCount(); nOutput++) { m_pData->GetMinAndRange(m_pRelation->GetOutputIndex(nOutput), &dTmpMin, &dTmpRange); if(dTmpMin < dOutputMin) { dOutputRange += (dOutputMin - dTmpMin); dOutputMin = dTmpMin; } if(dTmpRange > dOutputRange) dOutputRange = dTmpRange; } if(bLogarithmic) { dInputRange = log(dInputMin + dInputRange); dInputMin = log(dInputMin); dInputRange -= dInputMin; dOutputRange = log(dOutputMin + dOutputRange); dOutputMin = log(dOutputMin); dOutputRange -= dOutputMin; } // Clear the chart background int left = nBorderSize; int bottom = nBorderSize + nInput * (nChartHeight + nBorderSize) + nChartHeight - 1; image.DrawBox(left, bottom - nChartHeight + 1, left + nChartWidth - 1, bottom, 0xffffffff, true); // Plot the grid lines double x, y, gridbase; int xx, yy; if(bLogarithmic) { int n = GBits::RoundDown((float)(dInputMin / log(10))); bool bDone = false; while(!bDone) { gridbase = pow(10, n); for(i = 1; i < 10; i++) { x = log(gridbase * i); xx = left + (int)((x - dInputMin) * .9999999 * nChartWidth / dInputRange); if(xx < left) continue; if(xx >= left + nChartWidth) { bDone = true; break; } image.DrawLine(xx, bottom, xx, bottom - nChartHeight + 1, 0xff888888); } n++; } n = GBits::RoundDown((float)(dOutputMin / log(10))); bDone = false; while(!bDone) { gridbase = pow(10, n); for(i = 1; i < 10; i++) { y = log(gridbase * i); yy = bottom - (int)((y - dOutputMin) * .9999999 * nChartHeight / dOutputRange); if(yy > bottom) continue; if(yy <= bottom - nChartHeight) { bDone = true; break; } image.DrawLine(left, yy, left + nChartWidth - 1, yy, 0xff888888); } n++; } } else { // todo: write me } // todo: Label the grid lines // Plot the data int xxPrev = 0, yyPrev = 0; for(nOutput = 0; nOutput < m_pRelation->GetOutputCount(); nOutput++) { GColor color = GetSpectrumColor((float)nOutput / m_pRelation->GetOutputCount() + (float).75); double* pVector; for(i = 0; i < m_pData->GetSize(); i++) { // Compute chart coordinates pVector = m_pData->GetVector(i); x = pVector[m_pRelation->GetInputIndex(nInput)]; y = pVector[m_pRelation->GetOutputIndex(nOutput)]; if(bLogarithmic) { x = log(x); y = log(y); } xx = left + (int)((x - dInputMin) * .9999999 * nChartWidth / dInputRange); yy = bottom - (int)((y - dOutputMin) * .9999999 * nChartHeight / dOutputRange); // Plot the point image.DrawCircle(xx, yy, 4, color); if(i > 0) image.DrawLine(xxPrev, yyPrev, xx, yy, color); // Store the previous point xxPrev = xx; yyPrev = yy; } } }#ifdef WIN32 image.SaveBMPFile("chart.bmp"); OpenFile("chart.bmp");#else // WIN32 image.SavePNGFile("chart.png"); OpenFile("chart.png");#endif // !WIN32}class MyRegressCritic : public GArffDataRegressCritic{ public: MyRegressCritic(GArffData* pData, int nVariables, int nAttrX, int nAttrY) : GArffDataRegressCritic(pData, nVariables, nAttrX, nAttrY) { } virtual ~MyRegressCritic() {} protected: virtual double ApplyVariables(double dX, double* pVariables) { return pVariables[0] * pow(dX, pVariables[1]) + pVariables[2]; }};// defined in Test.cppbool IsPrettyClose(double a, double b);void ChartController::ComputeBigO(){int j;for(j = 1; j < m_pRelation->GetAttributeCount(); j++) m_pRelation->GetAttribute(j)->SetIsInput(false); // Regress it MyRegressCritic critic(m_pData, /*numVars*/3, /*attrX*/m_pRelation->GetInputIndex(0), /*attrY*/m_pRelation->GetOutputIndex(0)); GMomentumGreedySearch search(&critic); double* pVariables; double a = -1; double b = -1; double c = -1; int i; while(true) { for(i = 0; i < 50000; i++) search.Iterate(); pVariables = critic.GetBestYet(); printf("Crunching... (t=A(n^B)+c A=%f B=%f C=%f)\n", a, b, c); if(IsPrettyClose(pVariables[0], a) && IsPrettyClose(pVariables[1], b) && IsPrettyClose(pVariables[2], c)) break; a = pVariables[0]; b = pVariables[1]; c = pVariables[2]; } printf("t=A(n^B)+c A=%f B=%f C=%f\n", a, b, c);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -