CXTPChartDeviceCommand* CXTPChartRadarAxisXView::CreateDeviceCommand(CXTPChartDeviceContext* pDC)
{
	CXTPChartDeviceCommand* pAxisCommand = new CXTPChartPolygonAntialiasingDeviceCommand(TRUE);

	CXTPChartColor clrAxis = m_pAxis->GetActualColor();

	int nThickness = m_pAxis->GetThickness();

	if (m_pAxis->IsVisible())
	{
		if (nThickness > 0)
		{
			if (IsPolygonDiagramStyle())
			{
				CXTPChartLineStyle lineStyle(NULL);
				lineStyle.SetThickness(nThickness);

				pAxisCommand->AddChildCommand(GetDiagramView()->CreatePolygonLineDeviceCommand(pDC, m_nRadius, clrAxis, &lineStyle));
			}
			else
			{
				pAxisCommand->AddChildCommand(new CXTPChartBoundedCircleDeviceCommand(m_ptCenter, m_nRadius, clrAxis, nThickness));
			}
		}

		pAxisCommand->AddChildCommand(CreateTickMarksDeviceCommand(pDC));
		pAxisCommand->AddChildCommand(CreateLabelsDeviceCommand(pDC));
	}


	return pAxisCommand;
}
CXTPChartDeviceCommand* CXTPChartRadarAxisYView::CreateConstantLinesDeviceCommand(CXTPChartDeviceContext* pDC, BOOL bBehind)
{
	CXTPChartAxisConstantLines* pConstantLines = m_pAxis->GetConstantLines();
	if (pConstantLines->GetCount() == 0)
		return NULL;

	CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();


	for (int i = 0; i < pConstantLines->GetCount(); i++)
	{
		CXTPChartAxisConstantLine* pConstantLine = pConstantLines->GetAt(i);
		if (!pConstantLine->IsVisible())
			continue;

		if (pConstantLine->IsShowBehind() != bBehind)
			continue;

		double dMark = !pConstantLine->GetAxisValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pConstantLine->GetAxisValue()) :
			pConstantLine->GetAxisValueInternal();

		double dRad = ValueToRadius(dMark);

		if (IsPolygonDiagramStyle())
			pCommands->AddChildCommand(GetDiagramView()->CreatePolygonLineDeviceCommand(pDC, dRad, pConstantLine->GetActualColor(), pConstantLine->GetLineStyle()));
		else
			pCommands->AddChildCommand(new CXTPChartBoundedCircleDeviceCommand(m_ptCenter, dRad, pConstantLine->GetActualColor(),
				pConstantLine->GetLineStyle()->GetThickness()));
	}

	return pCommands;
}
CXTPChartDeviceCommand* CXTPChartRadarAxisYView::CreateGridLinesDeviceCommand(CXTPChartDeviceContext* pDC)
{
	UNREFERENCED_PARAMETER(pDC);

	CXTPChartAxisGridLines* pGridLines = m_pAxis->GetGridLines();

	if (!pGridLines->IsVisible())
		return NULL;

	CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();

	CXTPChartColor clrGridLines = pGridLines->GetColor();
	CXTPChartColor clrMinorGridLines = pGridLines->GetMinorColor();
	BOOL bMinorVisible = pGridLines->IsMinorVisible();

	for (int i = 0; i < m_arrTicks.GetSize(); i++)
	{
		double dRadius = ValueToRadius(m_arrTicks[i].m_dValue);

		if (IsPolygonDiagramStyle())
			pCommands->AddChildCommand(GetDiagramView()->CreatePolygonLineDeviceCommand(pDC, dRadius, clrGridLines, pGridLines->GetLineStyle()));
		else
			pCommands->AddChildCommand(new CXTPChartBoundedCircleDeviceCommand(m_ptCenter, dRadius, clrGridLines, pGridLines->GetLineStyle()->GetThickness()));
	}

	if (bMinorVisible)
	{
		for (int i = 0; i < m_arrMinorTicks.GetSize(); i++)
		{
			double dRadius = ValueToRadius(m_arrMinorTicks[i]);

			if (IsPolygonDiagramStyle())
				pCommands->AddChildCommand(GetDiagramView()->CreatePolygonLineDeviceCommand(pDC, dRadius, clrMinorGridLines, pGridLines->GetMinorLineStyle()));
			else
				pCommands->AddChildCommand(new CXTPChartBoundedCircleDeviceCommand(m_ptCenter, dRadius, clrMinorGridLines, pGridLines->GetMinorLineStyle()->GetThickness()));
		}
	}

	return pCommands;
}
CXTPChartDeviceCommand* CXTPChartRadarAxisYView::CreateStripsDeviceCommand(CXTPChartDeviceContext* pDC)
{
	UNREFERENCED_PARAMETER(pDC);
	CXTPChartAxisStrips* pStrips = m_pAxis->GetStrips();
	if (pStrips->GetCount() == 0)
		return NULL;

	CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();

	for (int i = 0; i < pStrips->GetCount(); i++)
	{
		CXTPChartAxisStrip* pStrip = pStrips->GetAt(i);
		if (!pStrip->IsVisible())
			continue;

		double dMarkLeft = !pStrip->GetAxisMinValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pStrip->GetAxisMinValue()) :
			pStrip->GetAxisMinValueInternal();

		double dMarkRight = !pStrip->GetAxisMaxValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pStrip->GetAxisMaxValue()) :
			pStrip->GetAxisMaxValueInternal();


		double dRFrom = ValueToRadius(dMarkLeft);
		double dRTo = ValueToRadius(dMarkRight);

		if (IsPolygonDiagramStyle())
		{
			pCommands->AddChildCommand(GetDiagramView()->CreatePolygonStripDeviceCommand(pDC, dRFrom, dRTo,
				pStrip->GetActualColor(), pStrip->GetActualColor2(), pStrip->GetFillStyle()));
		}
		else
		{
			pCommands->AddChildCommand(new CXTPChartGradientPieDeviceCommand(CXTPPoint3d(m_ptCenter), dRTo, dRTo,
				0, 360, 0, dRFrom / dRTo * 100, m_rcPaneBounds, pStrip->GetActualColor(), pStrip->GetActualColor2()));
		}
	}

	return pCommands;
}
CXTPChartDeviceCommand* CXTPChartRadarAxisYView::CreateInterlacedDeviceCommand(CXTPChartDeviceContext* pDC)
{
	UNREFERENCED_PARAMETER(pDC);

	if (!m_pAxis->IsInterlaced())
		return NULL;

	if (m_arrTicks.GetSize() < 1)
		return NULL;


	CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();

	CXTPChartColor color1 = m_pAxis->GetActualInterlacedColor();
	CXTPChartColor color2 = m_pAxis->GetActualInterlacedColor2();

	for (int i = 0; i < m_arrTicks.GetSize(); i += 2)
	{

		double dRFrom = ValueToRadius(m_arrTicks[i].m_dValue);
		double dRTo = i + 1 == m_arrTicks.GetSize() ? m_nRadius : ValueToRadius(m_arrTicks[i + 1].m_dValue);

		if (IsPolygonDiagramStyle())
		{
			CXTPChartRadarDiagramView* pDiagramView = GetDiagramView();

			pCommands->AddChildCommand(pDiagramView->CreatePolygonStripDeviceCommand(pDC, dRFrom, dRTo, color1, color2, m_pAxis->GetInterlacedFillStyle()));
		}
		else
		{
			pCommands->AddChildCommand(new CXTPChartGradientPieDeviceCommand(CXTPPoint3d(m_ptCenter), dRTo, dRTo,
				0, 360, 0, dRFrom / dRTo * 100, m_rcPaneBounds, color1, color2));
		}

	}


	return pCommands;
}
void CXTPChartRadarAxisXView::CreateTickMarks(CXTPChartDeviceContext* pDC)
{
	UNREFERENCED_PARAMETER(pDC);

	m_arrTicks.RemoveAll();
	m_arrMinorTicks.RemoveAll();

	double dAxisMinValue = m_dMinValue;
	double dAxisMaxValue = m_dMaxValue;
	double dGridSpacing = GetGridSpacing();
	int nOffset = m_pAxis->GetThickness() + (m_pAxis->GetTickMarks()->IsVisible() ? m_pAxis->GetTickMarks()->GetLength() : 0);

	if (m_pAxis->GetCustomLabels()->GetCount() > 0)
	{
		CXTPChartAxisCustomLabels* pCustomLabels = m_pAxis->GetCustomLabels();
		int nCount = pCustomLabels->GetCount();


		for (int i = 0; i < nCount; i++)
		{
			CXTPChartAxisCustomLabel* pLabel = pCustomLabels->GetAt(i);

			CXTPChartRadarAxisXViewTick tick;
			tick.m_dValue = !pLabel->GetAxisValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pLabel->GetAxisValue()) :
				pLabel->GetAxisValueInternal();

			if (tick.m_dValue >= dAxisMinValue && tick.m_dValue <= dAxisMaxValue)
			{
				tick.m_strLabel = pLabel->GetText();

				CXTPChartTextPainter painter(pDC, tick.m_strLabel, m_pAxis->GetLabel());

				tick.m_szLabel = painter.GetSize();

				tick.m_szBounds = painter.GetRoundedBounds().Size();


				double lineAngle = ValueToAngle(tick.m_dValue);

				CXTPChartSizeF size = painter.GetSize();

				CXTPChartPointF startPoint(m_ptCenter.X + m_nRadius * cos(lineAngle), m_ptCenter.Y - m_nRadius * sin(lineAngle));
				CXTPChartPointF finishPoint(startPoint.X + (float)(cos(lineAngle) * nOffset), startPoint.Y - (float)(sin(lineAngle) * nOffset));

				CXTPChartRectF innerBounds;
				CXTPChartSeriesLabelConnectorPainterBase::CalcBorderBoundsForTangentDrawing(finishPoint, lineAngle, size, 0, innerBounds);
				innerBounds.Round();

				tick.m_ptLocation = innerBounds.GetLocation();

				m_arrTicks.Add(tick);
			}
		}

	}
	else
	{
		double dMark = m_dMinValue;

		while (dMark < dAxisMaxValue - CXTPChartMathUtils::m_dEPS)
		{
			CXTPChartRadarAxisXViewTick tick;
			tick.m_dValue = AxisToValue(dMark);

			tick.m_strLabel = m_pAxis->GetScaleTypeMap()->InternalToValue(m_pAxis->GetLabel()->GetFormat(), tick.m_dValue);

			CXTPChartTextPainter painter(pDC, tick.m_strLabel, m_pAxis->GetLabel());

			tick.m_szLabel = painter.GetSize();

			tick.m_szBounds = painter.GetRoundedBounds().Size();

			double lineAngle = ValueToAngle(tick.m_dValue);

			CXTPChartSizeF size = painter.GetSize();

			CXTPChartPointF startPoint(m_ptCenter.X + m_nRadius * cos(lineAngle), m_ptCenter.Y - m_nRadius * sin(lineAngle));
			CXTPChartPointF finishPoint(startPoint.X + (float)(cos(lineAngle) * nOffset), startPoint.Y - (float)(sin(lineAngle) * nOffset));

			CXTPChartRectF innerBounds;
			CXTPChartSeriesLabelConnectorPainterBase::CalcBorderBoundsForTangentDrawing(finishPoint, lineAngle, size, 0, innerBounds);
			innerBounds.Round();

			tick.m_ptLocation = innerBounds.GetLocation();

			m_arrTicks.Add(tick);

			dMark += dGridSpacing;
		}


		int nMinorCount = m_pAxis->GetMinorCount();

		if (m_arrTicks.GetSize() > 0 && nMinorCount > 0)
		{
			double cur, prev;

			for (int i = 0; i <= m_arrTicks.GetSize(); i++)
			{
				if (m_pAxis->IsLogarithmic())
				{
					cur = i == m_arrTicks.GetSize() ? m_arrTicks[i - 1].m_dValue * m_pAxis->GetLogarithmicBase() :
						m_arrTicks[i].m_dValue;

					prev = i == 0 ? m_arrTicks[0].m_dValue / m_pAxis->GetLogarithmicBase() : m_arrTicks[i - 1].m_dValue;
				}
				else
				{
					cur = i == m_arrTicks.GetSize() ? m_arrTicks[i - 1].m_dValue + dGridSpacing : m_arrTicks[i].m_dValue;
					prev = i == 0 ? cur - dGridSpacing : m_arrTicks[i - 1].m_dValue;
				}

				for (int j = 0; j < nMinorCount; j++)
				{
					double dValue = prev + (cur - prev) * (j + 1) / (nMinorCount + 1);

					if (dValue >= dAxisMinValue && dValue <= dAxisMaxValue)
					{
						m_arrMinorTicks.Add(dValue);
					}
				}

			}
		}
	}

	if (GetAxis()->IsVisible() && GetAxis()->GetLabel()->IsVisible())
	{
		CXTPChartRadarDiagramView* pDiagramView = GetDiagramView();

		for (int i = 0; i < m_arrTicks.GetSize(); i++)
		{
			CXTPChartRectF rc(m_arrTicks[i].m_ptLocation, m_arrTicks[i].m_szLabel);
			pDiagramView->CheckLabelBounds(rc);

		}
	}
}
void CXTPChartStackedBarSeriesView::UpdateRange(CXTPChartDeviceContext* pDC)
{
	CXTPChartBarSeriesView::UpdateRange(pDC);

	CXTPChartDiagramView* pDiagramView = GetDiagramView();

	BOOL bFound = FALSE;

	for (int i = 0; i < pDiagramView->GetSeriesView()->GetCount(); i++)
	{
		CXTPChartSeriesView* pView = (CXTPChartSeriesView*)pDiagramView->GetSeriesView()->GetAt(i);

		if (DYNAMIC_DOWNCAST(CXTPChartStackedBarSeriesStyle, pView->GetSeries()->GetStyle()))
		{
			CXTPChartStackedBarSeriesView* pStackedBarSeriesView = (CXTPChartStackedBarSeriesView*)pView;

			if (pStackedBarSeriesView->m_bFirstStack && pView == this)
			{
				bFound = TRUE;
				break;
			}
		}
	}
	if (!bFound)
		return;

	CMap<double, double, double, double> mapValues;

	for (int j = 0; j < pDiagramView->GetSeriesView()->GetCount(); j++)
	{
		CXTPChartSeriesView* pView = (CXTPChartSeriesView*)pDiagramView->GetSeriesView()->GetAt(j);

		if (DYNAMIC_DOWNCAST(CXTPChartStackedBarSeriesStyle, pView->GetSeries()->GetStyle()))
		{
			CXTPChartStackedBarSeriesView* pStackedBarSeriesView = (CXTPChartStackedBarSeriesView*)pView;
			if (pStackedBarSeriesView->m_nBarIndex != m_nBarIndex)
				continue;

			for (int i = 0; i < pStackedBarSeriesView->m_pPointsView->GetCount(); i++)
			{
				CXTPChartStackedBarSeriesPointView* pPointView = (CXTPChartStackedBarSeriesPointView*)pStackedBarSeriesView->m_pPointsView->GetAt(i);

				double dValue = pPointView->GetPoint()->GetValue(0);

				pPointView->m_dValueFrom = mapValues[pPointView->GetPoint()->GetInternalArgumentValue()];
				pPointView->m_dInternalValue = pPointView->m_dValueTo = pPointView->m_dValueFrom + dValue;

				mapValues[pPointView->GetPoint()->GetInternalArgumentValue()] = pPointView->m_dValueTo;
			}
		}
	}

	double dStackHeight = ((CXTPChartStackedBarSeriesStyle*)GetStyle())->GetStackHeight();
	if (dStackHeight != 0)
	{
		for (int j = 0; j < pDiagramView->GetSeriesView()->GetCount(); j++)
		{
			CXTPChartSeriesView* pView = (CXTPChartSeriesView*)pDiagramView->GetSeriesView()->GetAt(j);

			if (DYNAMIC_DOWNCAST(CXTPChartStackedBarSeriesStyle, pView->GetSeries()->GetStyle()))
			{
				CXTPChartStackedBarSeriesView* pStackedBarSeriesView = (CXTPChartStackedBarSeriesView*)pView;
				if (pStackedBarSeriesView->m_nBarIndex != m_nBarIndex)
					continue;

				for (int i = 0; i < pStackedBarSeriesView->m_pPointsView->GetCount(); i++)
				{
					CXTPChartStackedBarSeriesPointView* pPointView = (CXTPChartStackedBarSeriesPointView*)pStackedBarSeriesView->m_pPointsView->GetAt(i);

					double dLimit = mapValues[pPointView->GetPoint()->GetInternalArgumentValue()];

					pPointView->m_dValueFrom = pPointView->m_dValueFrom * dStackHeight / dLimit;
					pPointView->m_dInternalValue = pPointView->m_dValueTo = pPointView->m_dValueTo * dStackHeight / dLimit;
				}
			}
		}
	}
}