using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using Steema.TeeChart.Drawing;
namespace DelftTools.Controls.Swf.Charting.Series
{
///
/// TeeChart wrapper class to fix PolygonSeries when drawn into a 2D axes (was meant for drawing on a Map).
///
internal class PolygonSeries : Steema.TeeChart.Styles.PolygonSeries
{
private bool autoClose;
///
/// Closes the polygon automatically when true.
///
public bool AutoClose
{
get
{
return autoClose;
}
set
{
autoClose = value;
Repaint();
}
}
///
/// Override Draw method and use the TeeChart Graphics3D object to draw the polygon shape
///
public override void Draw()
{
if (XValues.Count < 2)
{
return;
}
if (XValues.Count != YValues.Count)
{
// Just to be sure. I think TeeChart already accounts for this in Add methods.
throw new Exception("Number of X values should be equal to the number of Y values");
}
var g = Chart.Graphics3D;
PrepareGraphics3D(g);
g.ClipRectangle(Chart.ChartBounds);
// Draw polygon groups:
foreach (var pointList in GetDrawingPoints())
{
g.Polygon(pointList);
}
g.UnClip();
}
///
/// Override DrawLegendShape because it includes a call to Polygon().ParentShape.... which is null if we do not use Polygon to create it.
///
///
///
///
protected override void DrawLegendShape(Graphics3D g, int valueIndex, Rectangle rect)
{
PrepareGraphics3D(g);
var oldWidth = 1;
if (g.Pen.Visible)
{
oldWidth = g.Pen.Width;
g.Pen.Width = 1;
}
base.DrawLegendShape(g, valueIndex, rect);
if (g.Pen.Visible)
{
g.Pen.Width = oldWidth;
}
}
///
/// Override SetActive because it includes a call to Polygon().ParentShape.... which is null if we do not use Polygon to create it.
///
///
protected override void SetActive(bool value)
{
SetBooleanProperty(ref bActive, value);
}
///
/// Override PrepareLegendCanvas because it includes a call to Polygon().ParentShape.... which is null if we do not use Polygon to create it.
///
///
///
///
///
protected override void PrepareLegendCanvas(Graphics3D g, int valueIndex, ref Color backColor, ref ChartBrush aBrush) {}
private void PrepareGraphics3D(Graphics3D g)
{
g.Pen = Pen;
g.Brush = bBrush;
g.Pen.DrawingPen.LineJoin = LineJoin.Round;
}
private IEnumerable GetDrawingPoints()
{
var pointGroupsToRender = new List();
var currentPointsGroup = new List();
for (int i = 0; i < XValues.Count; i++)
{
var xValue = XValues[i];
var yValue = YValues[i];
if (double.IsNaN(xValue) || double.IsNaN(yValue))
{
continue;
}
// TODO: How to distinguish null??
// Can cause collision when a regular value has the same value!
if (xValue == DefaultNullValue || yValue == DefaultNullValue)
{
AddToPointsList(pointGroupsToRender, currentPointsGroup);
continue;
}
currentPointsGroup.Add(new Point(CalcXPosValue(xValue), CalcYPosValue(yValue)));
}
AddToPointsList(pointGroupsToRender, currentPointsGroup);
return pointGroupsToRender;
}
private void AddToPointsList(ICollection pointGroupsToRender, List currentPointsGroup)
{
if (!currentPointsGroup.Any())
{
return; // Do nothing for empty list
}
if (autoClose && (currentPointsGroup[0].X != currentPointsGroup.Last().X || currentPointsGroup[0].Y != currentPointsGroup.Last().Y))
{
currentPointsGroup.Add(currentPointsGroup[0]);
}
pointGroupsToRender.Add(currentPointsGroup.ToArray());
currentPointsGroup.Clear();
}
}
}