You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
7.8 KiB
C++
238 lines
7.8 KiB
C++
// XTPChartPieDeviceCommand.cpp
|
|
//
|
|
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "GraphicLibrary/GdiPlus/GdiPlus.h"
|
|
|
|
#include "../Types/XTPChartTypes.h"
|
|
#include "Common/Base/Types/XTPPoint3.h"
|
|
|
|
|
|
#include <Common/XTPMathUtils.h>
|
|
#include "XTPChartDeviceContext.h"
|
|
#include "XTPChartDeviceCommand.h"
|
|
|
|
#include "../Types/XTPChartPie.h"
|
|
#include "XTPChartPieDeviceCommand.h"
|
|
|
|
#include <math.h>
|
|
|
|
using namespace Gdiplus;
|
|
using namespace Gdiplus::DllExports;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPChartPieDeviceCommand
|
|
|
|
CXTPChartPieDeviceCommand::CXTPChartPieDeviceCommand(const CXTPPoint3d& center, double dMajorSemiAxis, double dMinorSemiAxis, double dStartAngle, double dSweepAngle, double depth, double nHolePercent)
|
|
{
|
|
m_ptCenter = center;
|
|
m_dMajorSemiAxis = dMajorSemiAxis;
|
|
m_dMinorSemiAxis = dMinorSemiAxis;
|
|
m_dStartAngle = dStartAngle;
|
|
m_dSweepAngle = dSweepAngle;
|
|
m_dDepth = depth;
|
|
m_dHolePercent = nHolePercent / 100.0;
|
|
|
|
m_dFacetSize = 0;
|
|
|
|
m_dInnerMajorSemiAxis = 0;
|
|
m_dInnerMinorSemiAxis = 0;
|
|
|
|
m_dCorrectedDepth = 0;
|
|
|
|
m_dInnerRadius = 0;
|
|
|
|
m_bDoughnut = nHolePercent > CXTPMathUtils::m_dEPS;
|
|
|
|
if (m_bDoughnut)
|
|
{
|
|
double doughnutThickness = dMinorSemiAxis * (1.0 - m_dHolePercent);
|
|
m_dInnerMajorSemiAxis = dMajorSemiAxis - doughnutThickness;
|
|
m_dInnerMinorSemiAxis = dMinorSemiAxis - doughnutThickness;
|
|
}
|
|
|
|
if (depth > 0.0f)
|
|
{
|
|
m_dFacetSize = dMajorSemiAxis * 0.02f;
|
|
m_dFacetSize = 0;
|
|
|
|
if (m_dFacetSize > depth / 2.0f)
|
|
m_dFacetSize = depth / 2.0f;
|
|
m_dRadius = dMajorSemiAxis - m_dFacetSize;
|
|
float diff = float(m_dRadius - m_dInnerMajorSemiAxis);
|
|
if (diff < 0.0f) {
|
|
m_dRadius -= diff;
|
|
m_dFacetSize += diff;
|
|
}
|
|
|
|
m_dCorrectedDepth = depth - m_dFacetSize * 2;
|
|
|
|
if (m_bDoughnut) {
|
|
m_dInnerRadius = m_dInnerMajorSemiAxis;
|
|
if (m_dInnerRadius > m_dRadius)
|
|
m_dInnerRadius = m_dRadius;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void CXTPChartPieDeviceCommand::CalculateStartFinishPoints(const CXTPPoint3d& center, double majorSemiaxis, double minorSemiaxis, double dStartAngle, double dSweepAngle, CXTPChartPointF& startPoint, CXTPChartPointF& finishPoint) const
|
|
{
|
|
CXTPChartEllipse ellipse(center, majorSemiaxis, minorSemiaxis);
|
|
startPoint = (CXTPChartPointF)ellipse.CalcEllipsePoint(-CXTPMathUtils::Degree2Radian(dStartAngle));
|
|
finishPoint = (CXTPChartPointF)ellipse.CalcEllipsePoint(-CXTPMathUtils::Degree2Radian(dStartAngle + dSweepAngle));
|
|
}
|
|
|
|
CXTPChartElement* CXTPChartPieDeviceCommand::HitTest(CPoint point, CXTPChartElement* pParent) const
|
|
{
|
|
GpPath* pGpPath = CreatePieGraphicsPath(m_ptCenter, m_dMajorSemiAxis, m_dMinorSemiAxis, m_dHolePercent, m_dStartAngle, m_dSweepAngle);
|
|
|
|
BOOL bResult = FALSE;
|
|
|
|
GdipIsVisiblePathPointI(pGpPath, point.x, point.y, NULL, &bResult);
|
|
|
|
GdipDeletePath(pGpPath);
|
|
|
|
return bResult ? pParent : NULL;
|
|
}
|
|
|
|
GpPath* CXTPChartPieDeviceCommand::CreatePieGraphicsPath(const CXTPPoint3d& center, double majorSemiaxis, double minorSemiaxis, double holePercent, double dStartAngle, double dSweepAngle) const
|
|
{
|
|
GpPath* pGpPath = NULL;
|
|
GdipCreatePath(FillModeAlternate, &pGpPath);
|
|
|
|
CRect rect(int(center.X - majorSemiaxis), int(center.Y - minorSemiaxis), int(center.X + majorSemiaxis), int(center.Y + minorSemiaxis));
|
|
|
|
BOOL bShouldAddLines = CXTPMathUtils::Compare(dSweepAngle, -360.0) != 0;
|
|
float dInnerMajorSemiaxis = (float)(majorSemiaxis * holePercent);
|
|
float dInnerMinorSemiaxis = (float)(minorSemiaxis * holePercent);
|
|
if (dInnerMajorSemiaxis >= 1.0f && dInnerMinorSemiaxis >= 1.0f)
|
|
{
|
|
CRect innerRect(int(center.X - dInnerMajorSemiaxis), int(center.Y - dInnerMinorSemiaxis), int(center.X + dInnerMajorSemiaxis), int(center.Y + dInnerMinorSemiaxis));
|
|
|
|
CXTPChartPointF startPoint, finishPoint, innerStartPoint, innerFinishPoint;
|
|
|
|
if (bShouldAddLines)
|
|
{
|
|
CalculateStartFinishPoints(center, majorSemiaxis, minorSemiaxis, dStartAngle, dSweepAngle, startPoint, finishPoint);
|
|
CalculateStartFinishPoints(center, dInnerMajorSemiaxis, dInnerMinorSemiaxis, dStartAngle, dSweepAngle, innerStartPoint, innerFinishPoint);
|
|
}
|
|
|
|
GdipAddPathArc(pGpPath, (REAL)rect.left, (REAL)rect.top, (REAL)rect.Width(), (REAL)rect.Height(), (REAL)dStartAngle, (REAL)dSweepAngle);
|
|
|
|
if (bShouldAddLines)
|
|
{
|
|
GdipAddPathLine(pGpPath, finishPoint.X, finishPoint.Y, innerFinishPoint.X, innerFinishPoint.Y);
|
|
}
|
|
GdipAddPathArc(pGpPath, (REAL)innerRect.left, (REAL)innerRect.top, (REAL)innerRect.Width(), (REAL)innerRect.Height(), (REAL)(dStartAngle + dSweepAngle), (REAL)(-dSweepAngle));
|
|
|
|
if (bShouldAddLines)
|
|
GdipAddPathLine(pGpPath, innerStartPoint.X, innerStartPoint.Y, startPoint.X, startPoint.Y);
|
|
|
|
}
|
|
else if (bShouldAddLines)
|
|
{
|
|
GdipAddPathPie(pGpPath, (REAL)rect.left, (REAL)rect.top, (REAL)rect.Width(), (REAL)rect.Height(), (REAL)dStartAngle, (REAL)dSweepAngle);
|
|
|
|
}
|
|
else
|
|
{
|
|
GdipAddPathEllipse(pGpPath, (REAL)rect.left, (REAL)rect.top, (REAL)rect.Width(), (REAL)rect.Height());
|
|
|
|
}
|
|
|
|
return pGpPath;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPChartGradientPieDeviceCommand
|
|
|
|
CXTPChartGradientPieDeviceCommand::CXTPChartGradientPieDeviceCommand(const CXTPPoint3d& center, double dMajorSemiAxis, double dMinorSemiAxis,
|
|
double dStartAngle, double dSweepAngle, double depth, double holePercent, const CXTPChartRectF& gradientBounds, const CXTPChartColor& color, const CXTPChartColor& color2)
|
|
: CXTPChartPieDeviceCommand(center, dMajorSemiAxis, dMinorSemiAxis, dStartAngle, dSweepAngle, depth, holePercent)
|
|
{
|
|
m_rcGradientBounds = gradientBounds;
|
|
m_color = color;
|
|
m_color2 = color2;
|
|
}
|
|
|
|
|
|
GpBrush* CXTPChartGradientPieDeviceCommand::CreateBrush()
|
|
{
|
|
GpLineGradient* pGpBrush = NULL;
|
|
|
|
PointF ptGradient[2];
|
|
ptGradient[0] = PointF((REAL)m_rcGradientBounds.X, (REAL)m_ptCenter.Y);
|
|
ptGradient[1] = PointF((REAL)(m_rcGradientBounds.X + m_rcGradientBounds.Width), (REAL)m_ptCenter.Y);
|
|
|
|
|
|
GdipCreateLineBrush(&ptGradient[0], &ptGradient[1], m_color.GetValue(), m_color2.GetValue(), WrapModeTile, &pGpBrush);
|
|
|
|
return pGpBrush;
|
|
}
|
|
|
|
void CXTPChartGradientPieDeviceCommand::ExecuteOverride(CXTPChartDeviceContext* pDC)
|
|
{
|
|
|
|
GpBrush* pGpBrush = CreateBrush();
|
|
|
|
|
|
GpPath* pGpPath = CreatePieGraphicsPath(m_ptCenter, m_dMajorSemiAxis, m_dMinorSemiAxis, m_dHolePercent, m_dStartAngle, m_dSweepAngle);
|
|
|
|
GdipFillPath(pDC->GetGraphics(), pGpBrush, pGpPath);
|
|
|
|
GdipDeletePath(pGpPath);
|
|
|
|
GdipDeleteBrush(pGpBrush);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPChartBoundedPieDeviceCommand
|
|
|
|
|
|
CXTPChartBoundedPieDeviceCommand::CXTPChartBoundedPieDeviceCommand(const CXTPPoint3d& center, double dMajorSemiAxis, double dMinorSemiAxis, double dStartAngle, double dSweepAngle, double depth, int holePercent, const CXTPChartColor& color, int nThickness)
|
|
: CXTPChartPieDeviceCommand(center, dMajorSemiAxis, dMinorSemiAxis, dStartAngle, dSweepAngle, depth, holePercent)
|
|
{
|
|
m_color = color;
|
|
m_nThickness = nThickness;
|
|
}
|
|
|
|
void CXTPChartBoundedPieDeviceCommand::ExecuteOverride(CXTPChartDeviceContext* pDC)
|
|
{
|
|
|
|
GpPen* pGpPen = NULL;
|
|
GdipCreatePen1(m_color.GetValue(), (REAL)m_nThickness, UnitWorld, &pGpPen);
|
|
|
|
|
|
GpPath* pGpPath = CreatePieGraphicsPath(m_ptCenter, m_dMajorSemiAxis, m_dMinorSemiAxis, m_dHolePercent, m_dStartAngle, m_dSweepAngle);
|
|
|
|
GdipDrawPath(pDC->GetGraphics(), pGpPen, pGpPath);
|
|
|
|
GdipDeletePath(pGpPath);
|
|
|
|
GdipDeletePen(pGpPen);
|
|
}
|