/// <summary> /// Draws the Vertical 3D Plank /// </summary> /// <param name="height">Height of the PlotArea canvas</param> /// <param name="plankDepth">PlankDepth</param> /// <param name="plankThickness">PlankThickness</param> /// <param name="plankOpacity">PlankOpacity</param> private void DrawVerticalPlank(Double height, Double plankDepth, Double plankThickness, Double plankOpacity, Boolean isPartialUpdate) { if (isPartialUpdate && _verticalPlank != null) { ColumnChart.Update3DPlank(plankThickness, height, plankDepth, _verticalPlank); CreateGridLinesOverPlank(height, _verticalPlank.Visual as Panel, plankDepth, plankThickness); return; } if (_verticalPlank != null && _verticalPlank.Visual != null && _verticalPlank.Visual.Parent != null) { Panel parent = _verticalPlank.Visual.Parent as Canvas; parent.Children.Remove(_verticalPlank.Visual); } List<Color> colors = new List<Color>(); //colors.Add(Color.FromArgb(255, 212, 212, 212)); //colors.Add(Color.FromArgb(255, 142, 125, 125)); colors.Add(Color.FromArgb(255, 240, 240, 240)); colors.Add(Color.FromArgb(255, 200, 200, 200)); Brush rightBrush = Graphics.CreateLinearGradientBrush(0, new Point(0, 0.5), new Point(1, 0.5), colors, new List<double>() { 0, 1 }); _verticalPlank = ColumnChart.Get3DPlank(plankThickness, height, plankDepth, null, null, rightBrush); Panel plank = _verticalPlank.Visual as Panel; #region Create grid lines over plank CreateGridLinesOverPlank(height, plank, plankDepth, plankThickness); #endregion plank.SetValue(Canvas.TopProperty, plankDepth); plank.SetValue(Canvas.ZIndexProperty, -1); plank.SetValue(Canvas.OpacityProperty, (Double)0.8); PlottingCanvas.Children.Add(plank); }
/// <summary> /// Return visual object for pie chart /// </summary> /// <param name="width">Width of the PlotArea</param> /// <param name="height">Height of the PlotArea</param> /// <param name="plotDetails">PlotDetails reference</param> /// <param name="seriesList">List of series list</param> /// <param name="chart">Chart reference</param> /// <param name="animationEnabled">Whether animation is enabled</param> /// <returns>Canvas</returns> internal static Canvas GetVisualObjectForPieChart(Double width, Double height, PlotDetails plotDetails, List<DataSeries> seriesList, Chart chart, bool isAnimationEnabled) { if (Double.IsNaN(width) || Double.IsNaN(height) || width <= 0 || height <= 0) return null; DataSeries currentDataSeries = null; // Debug.WriteLine("PieStart: " + DateTime.Now.ToLongTimeString()); Canvas visual = new Canvas() { Width = width, Height = height }; DataSeries series = seriesList[0]; if (series.Enabled == false) return visual; // List<DataPoint> enabledDataPoints = (from datapoint in series.InternalDataPoints where datapoint.Enabled == true && datapoint.InternalYValue != 0 && !Double.IsNaN(datapoint.InternalYValue) select datapoint).ToList(); List<DataPoint> enabledDataPoints = (from datapoint in series.InternalDataPoints where datapoint.Enabled == true && !Double.IsNaN(datapoint.InternalYValue) select datapoint).ToList(); if ((from dp in enabledDataPoints select dp.InternalYValue).Sum() == 0) enabledDataPoints.Clear(); Double absoluteSum = plotDetails.GetAbsoluteSumOfDataPoints(enabledDataPoints); absoluteSum = (absoluteSum == 0) ? 1 : absoluteSum; Double centerX = width / 2; Double centerY = height / 2; Double offsetX = 0; Double offsetY = 0; Boolean IsLabelEnabled; Size pieSize = new Size(); Canvas labelCanvas = CreateAndPositionLabels(absoluteSum, enabledDataPoints, width, height, ((chart.View3D) ? 0.4 : 1), chart.View3D, ref pieSize); Debug.WriteLine("Labels Positioning over: " + DateTime.Now.ToLongTimeString()); if (labelCanvas == null) IsLabelEnabled = false; else { IsLabelEnabled = true; labelCanvas.SetValue(Canvas.ZIndexProperty, 50001); labelCanvas.IsHitTestVisible = false; } Double radius = Math.Min(pieSize.Width, pieSize.Height) / (chart.View3D ? 1 : 2); Double startAngle = series.InternalStartAngle; Double endAngle = 0; Double angle; Double absoluteYValue; Double meanAngle = 0; Int32 zindex = 0; if (chart.View3D) _elementPositionData = new List<ElementPositionData>(); if (series.Storyboard == null) series.Storyboard = new Storyboard(); currentDataSeries = series; SectorChartShapeParams pieParams = null; Int32 labelStateCounter = 0; if (!chart.View3D) { foreach (DataPoint dataPoint in enabledDataPoints) { if (dataPoint.LabelStyle == LabelStyles.Inside || !(Boolean)dataPoint.LabelEnabled) labelStateCounter++; } } foreach (DataPoint dataPoint in enabledDataPoints) { if (Double.IsNaN(dataPoint.InternalYValue))// || dataPoint.InternalYValue == 0) continue; absoluteYValue = Math.Abs(dataPoint.InternalYValue); angle = (absoluteYValue / absoluteSum) * Math.PI * 2; endAngle = startAngle + angle; meanAngle = (startAngle + endAngle) / 2; pieParams = new SectorChartShapeParams(); dataPoint.VisualParams = pieParams; pieParams.Storyboard = series.Storyboard; pieParams.AnimationEnabled = isAnimationEnabled; pieParams.Center = new Point(centerX, centerY); pieParams.ExplodeRatio = chart.View3D ? 0.2 : 0.1; pieParams.InnerRadius = 0; pieParams.OuterRadius = radius; pieParams.DataPoint = dataPoint; if (chart.View3D) { pieParams.StartAngle = pieParams.FixAngle((startAngle) % (Math.PI * 2)); pieParams.StopAngle = pieParams.FixAngle((endAngle) % (Math.PI * 2)); } else { pieParams.StartAngle = startAngle; pieParams.StopAngle = endAngle; } pieParams.Lighting = (Boolean)dataPoint.LightingEnabled; pieParams.Bevel = series.Bevel; pieParams.IsLargerArc = (angle / (Math.PI)) > 1; pieParams.Background = dataPoint.Color; pieParams.Width = width; pieParams.Height = height; pieParams.TiltAngle = Math.Asin(0.4); pieParams.Depth = 20 / pieParams.YAxisScaling; pieParams.MeanAngle = meanAngle; pieParams.LabelLineEnabled = (Boolean)dataPoint.LabelLineEnabled; pieParams.LabelLineColor = dataPoint.LabelLineColor; pieParams.LabelLineThickness = (Double)dataPoint.LabelLineThickness; pieParams.LabelLineStyle = ExtendedGraphics.GetDashArray((LineStyles)dataPoint.LabelLineStyle); pieParams.IsZero = (dataPoint.InternalYValue == 0); offsetX = radius * pieParams.ExplodeRatio * Math.Cos(meanAngle); offsetY = radius * pieParams.ExplodeRatio * Math.Sin(meanAngle); pieParams.OffsetX = offsetX; pieParams.OffsetY = offsetY * (chart.View3D ? pieParams.YAxisScaling : 1); if (dataPoint.LabelVisual != null) { if (dataPoint.LabelVisual.Visibility == Visibility.Collapsed) pieParams.LabelLineEnabled = false; Double left = (Double)dataPoint.LabelVisual.GetValue(Canvas.LeftProperty); if (left < width / 2) { pieParams.LabelLineTargetToRight = true; // pieParams.LabelPoint = new Point((Double)dataPoint.LabelVisual.GetValue(Canvas.LeftProperty) + dataPoint.LabelVisual.DesiredSize.Width, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.DesiredSize.Height / 2); pieParams.LabelPoint = new Point(left + dataPoint.LabelVisual.Width + LabelPlacementHelper.LABEL_LINE_GAP, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.Height / 2); } else { pieParams.LabelLineTargetToRight = false; pieParams.LabelPoint = new Point(left - LabelPlacementHelper.LABEL_LINE_GAP, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.Height / 2); } // apply animation to the labels if (isAnimationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, dataPoint, series.Storyboard, dataPoint.LabelVisual, 2, dataPoint.InternalOpacity * dataPoint.Parent.InternalOpacity, 0.5); dataPoint.LabelVisual.Opacity = 0; } } if (dataPoint.LabelStyle == LabelStyles.Inside && dataPoint.InternalYValue == 0) pieParams.LabelLineEnabled = false; Faces faces = new Faces(); if (chart.View3D) { Create3DPie(currentDataSeries, width, height, series, enabledDataPoints, dataPoint, ref visual, ref faces, ref pieParams, ref offsetX, ref zindex, isAnimationEnabled); } else { Create2DPie(currentDataSeries, width, height, series, enabledDataPoints, dataPoint, ref visual, ref faces, ref pieParams, ref offsetX, ref offsetY, ref zindex, isAnimationEnabled, labelStateCounter); } Debug.WriteLine("Datapoint" + enabledDataPoints.IndexOf(dataPoint) + ": " + DateTime.Now.ToLongTimeString()); dataPoint.Faces = faces; startAngle = endAngle; if (!chart.AnimationEnabled || chart.IsInDesignMode || !chart.ChartArea._isFirstTimeRender) { if (dataPoint.Faces != null) { foreach (Shape shape in dataPoint.Faces.BorderElements) { InteractivityHelper.ApplyBorderEffect(shape, (BorderStyles)dataPoint.BorderStyle, dataPoint.InternalBorderThickness.Left, dataPoint.BorderColor); } } } } if (chart.View3D) { Int32 zindex1, zindex2; _elementPositionData.Sort(ElementPositionData.CompareAngle); zindex1 = 1000; zindex2 = -1000; for (Int32 i = 0; i < _elementPositionData.Count; i++) { SetZIndex(_elementPositionData[i].Element, ref zindex1, ref zindex2, _elementPositionData[i].StartAngle); } } if (IsLabelEnabled && labelCanvas != null) visual.Children.Add(labelCanvas); RectangleGeometry clipRectangle = new RectangleGeometry(); clipRectangle.Rect = new Rect(0, 0, width, height); visual.Clip = clipRectangle; return visual; }
/// <summary> /// Returns a pie in a canvas /// </summary> /// <param name="faces">Pie faces</param> /// <param name="pieParams">Pie parameters</param> /// <param name="unExplodedPoints">UnExploded dataPoints</param> /// <param name="explodedPoints">Exploded dataPoints</param> /// <param name="labelLinePath">Label line path</param> /// <param name="enabledDataPoints">List of enabled dataPoints</param> /// <returns>Canvas</returns> private static Canvas GetPie2D(DataSeries currentDataSeries, ref Faces faces, SectorChartShapeParams pieParams, ref PieDoughnut2DPoints unExplodedPoints, ref PieDoughnut2DPoints explodedPoints, ref Path labelLinePath, List<DataPoint> enabledDataPoints) { var noOfNonZeroDataPoint = (from dp in enabledDataPoints where dp.InternalYValue != 0 select dp); Canvas visual = new Canvas(); Double width = pieParams.OuterRadius * 2; Double height = pieParams.OuterRadius * 2; visual.Width = width; visual.Height = height; Point center = new Point(width / 2, height / 2); Double xOffset = pieParams.OuterRadius * pieParams.ExplodeRatio * Math.Cos(pieParams.MeanAngle); Double yOffset = pieParams.OuterRadius * pieParams.ExplodeRatio * Math.Sin(pieParams.MeanAngle); #region PieSlice if (pieParams.StartAngle != pieParams.StopAngle || !pieParams.IsZero) { Ellipse ellipse = new Ellipse() { Tag = new ElementData() { Element = pieParams.TagReference } }; ellipse.Width = width; ellipse.Height = height; ellipse.Fill = pieParams.Lighting ? Graphics.GetLightingEnabledBrush(pieParams.Background, "Radial", new Double[] { 0.99, 0.745 }) : pieParams.Background; Point start = new Point(); Point end = new Point(); Point arcMidPoint = new Point(); start.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StartAngle); start.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StartAngle); end.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StopAngle); end.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StopAngle); arcMidPoint.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.MeanAngle); arcMidPoint.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.MeanAngle); List<PathGeometryParams> clipPathGeometry = new List<PathGeometryParams>(); clipPathGeometry.Add(new LineSegmentParams(start)); clipPathGeometry.Add(new ArcSegmentParams(new Size(pieParams.OuterRadius, pieParams.OuterRadius), 0, ((pieParams.StopAngle - pieParams.StartAngle) > Math.PI) ? true : false, SweepDirection.Clockwise, pieParams.AnimationEnabled ? start : arcMidPoint)); clipPathGeometry.Add(new ArcSegmentParams(new Size(pieParams.OuterRadius, pieParams.OuterRadius), 0, ((pieParams.StopAngle - pieParams.StartAngle) > Math.PI) ? true : false, SweepDirection.Clockwise, pieParams.AnimationEnabled ? start : end)); clipPathGeometry.Add(new LineSegmentParams(center)); ellipse.Clip = GetPathGeometryFromList(FillRule.Nonzero, center, clipPathGeometry, true); PathSegmentCollection segments = (ellipse.Clip as PathGeometry).Figures[0].Segments; // apply animation to the individual points that for the pie slice if (pieParams.AnimationEnabled) { // apply animation to the points pieParams.Storyboard = CreatePathSegmentAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[1], center, pieParams.OuterRadius, currentDataSeries.InternalStartAngle, pieParams.MeanAngle); pieParams.Storyboard = CreatePathSegmentAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[2], center, pieParams.OuterRadius, currentDataSeries.InternalStartAngle, pieParams.StopAngle); pieParams.Storyboard = CreatePathSegmentAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[0], center, pieParams.OuterRadius, currentDataSeries.InternalStartAngle, pieParams.StartAngle); } faces.Parts.Add(ellipse); visual.Children.Add(ellipse); // set the un exploded points for interactivity unExplodedPoints.Center = center; unExplodedPoints.OuterArcStart = start; unExplodedPoints.OuterArcMid = arcMidPoint; unExplodedPoints.OuterArcEnd = end; // set the exploded points for interactivity explodedPoints.Center = new Point(center.X + xOffset, center.Y + yOffset); explodedPoints.OuterArcStart = new Point(start.X + xOffset, start.Y + yOffset); explodedPoints.OuterArcMid = new Point(arcMidPoint.X + xOffset, arcMidPoint.Y + yOffset); explodedPoints.OuterArcEnd = new Point(end.X + xOffset, end.Y + yOffset); if (enabledDataPoints.Count == 1 || noOfNonZeroDataPoint.Count() == 1) { Ellipse borderEllipse = new Ellipse() { IsHitTestVisible = false, Height = ellipse.Height, Width = ellipse.Width }; borderEllipse.SetValue(Canvas.ZIndexProperty, (Int32)10000); visual.Children.Add(borderEllipse); faces.BorderElements.Add(borderEllipse); } } #endregion PieSlice #region Lighting if ((pieParams.TagReference as DataPoint).InternalYValue != 0 && pieParams.Lighting && (pieParams.StartAngle != pieParams.StopAngle || !pieParams.IsZero)) { Ellipse lightingEllipse = new Ellipse() { Tag = new ElementData() { Element = pieParams.TagReference } }; lightingEllipse.Width = width; lightingEllipse.Height = height; lightingEllipse.IsHitTestVisible = false; lightingEllipse.Fill = GetPieGradianceBrush(); Point start = new Point(); Point end = new Point(); Point arcMidPoint = new Point(); start.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StartAngle); start.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StartAngle); end.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StopAngle); end.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StopAngle); arcMidPoint.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.MeanAngle); arcMidPoint.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.MeanAngle); List<PathGeometryParams> clipPathGeometry = new List<PathGeometryParams>(); clipPathGeometry.Add(new LineSegmentParams(start)); clipPathGeometry.Add(new ArcSegmentParams(new Size(pieParams.OuterRadius, pieParams.OuterRadius), 0, ((pieParams.StopAngle - pieParams.StartAngle) > Math.PI) ? true : false, SweepDirection.Clockwise, pieParams.AnimationEnabled ? start : arcMidPoint)); clipPathGeometry.Add(new ArcSegmentParams(new Size(pieParams.OuterRadius, pieParams.OuterRadius), 0, ((pieParams.StopAngle - pieParams.StartAngle) > Math.PI) ? true : false, SweepDirection.Clockwise, pieParams.AnimationEnabled ? start : end)); clipPathGeometry.Add(new LineSegmentParams(center)); lightingEllipse.Clip = GetPathGeometryFromList(FillRule.Nonzero, center, clipPathGeometry, true); PathSegmentCollection segments = (lightingEllipse.Clip as PathGeometry).Figures[0].Segments; // apply animation to the individual points that for the shape that // gives the lighting effect to the pie slice if (pieParams.AnimationEnabled) { // apply animation to the points pieParams.Storyboard = CreatePathSegmentAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[1], center, pieParams.OuterRadius, currentDataSeries.InternalStartAngle, pieParams.MeanAngle); pieParams.Storyboard = CreatePathSegmentAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[2], center, pieParams.OuterRadius, currentDataSeries.InternalStartAngle, pieParams.StopAngle); pieParams.Storyboard = CreatePathSegmentAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[0], center, pieParams.OuterRadius, currentDataSeries.InternalStartAngle, pieParams.StartAngle); } visual.Children.Add(lightingEllipse); } #endregion Lighting #region LabelLine if (pieParams.LabelLineEnabled) { Path labelLine = new Path() { Tag = new ElementData() { Element = pieParams.TagReference } }; Double meanAngle = pieParams.MeanAngle; labelLine.SetValue(Canvas.ZIndexProperty, -100000); Point piePoint = new Point(); piePoint.X = center.X + pieParams.OuterRadius * Math.Cos(meanAngle); piePoint.Y = center.Y + pieParams.OuterRadius * Math.Sin(meanAngle); Point labelPoint = new Point(); labelPoint.X = center.X + pieParams.LabelPoint.X - pieParams.Width / 2; labelPoint.Y = center.Y + pieParams.LabelPoint.Y - pieParams.Height / 2; Point midPoint = new Point(); // midPoint.X = (labelPoint.X < center.X) ? labelPoint.X + 10 : labelPoint.X - 10; if (pieParams.LabelLineTargetToRight) midPoint.X = labelPoint.X + 10; else midPoint.X = labelPoint.X - 10; midPoint.Y = labelPoint.Y; List<PathGeometryParams> labelLinePathGeometry = new List<PathGeometryParams>(); labelLinePathGeometry.Add(new LineSegmentParams(pieParams.AnimationEnabled ? piePoint : midPoint)); labelLinePathGeometry.Add(new LineSegmentParams(pieParams.AnimationEnabled ? piePoint : labelPoint)); labelLine.Data = GetPathGeometryFromList(FillRule.Nonzero, piePoint, labelLinePathGeometry, true); PathFigure figure = (labelLine.Data as PathGeometry).Figures[0]; PathSegmentCollection segments = figure.Segments; figure.IsClosed = false; figure.IsFilled = false; // animate the label lines of the individual pie slices if (pieParams.AnimationEnabled) { pieParams.Storyboard = CreateLabelLineAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[0], piePoint, midPoint); pieParams.Storyboard = CreateLabelLineAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, segments[1], piePoint, midPoint, labelPoint); } labelLine.Stroke = pieParams.LabelLineColor; labelLine.StrokeDashArray = pieParams.LabelLineStyle; labelLine.StrokeThickness = pieParams.LabelLineThickness; labelLinePath = labelLine; if ((pieParams.TagReference as DataPoint).InternalYValue == 0) { Line zeroLine = new Line(); zeroLine.X1 = center.X; zeroLine.Y1 = center.Y; zeroLine.X2 = piePoint.X; zeroLine.Y2 = piePoint.Y; zeroLine.Stroke = pieParams.LabelLineColor; zeroLine.StrokeThickness = 0.25; zeroLine.IsHitTestVisible = false; visual.Children.Add(zeroLine); if (pieParams.AnimationEnabled) { pieParams.Storyboard = CreateOpacityAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, zeroLine, 2, zeroLine.Opacity, 0.5); zeroLine.Opacity = 0; } } visual.Children.Add(labelLine); // set the un exploded points for interactivity unExplodedPoints.LabelLineEndPoint = labelPoint; unExplodedPoints.LabelLineMidPoint = midPoint; unExplodedPoints.LabelLineStartPoint = piePoint; // set the exploded points for interactivity explodedPoints.LabelLineEndPoint = new Point(labelPoint.X, labelPoint.Y - yOffset); explodedPoints.LabelLineMidPoint = new Point(midPoint.X, midPoint.Y - yOffset); explodedPoints.LabelLineStartPoint = new Point(piePoint.X + xOffset, piePoint.Y + yOffset); if ((pieParams.TagReference as DataPoint).InternalYValue == 0) labelLine.IsHitTestVisible = false; } #endregion LabelLine #region Create path for selecting a pie section Point startPoint = new Point(); Point endPoint = new Point(); startPoint.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StartAngle); startPoint.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StartAngle); endPoint.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StopAngle); endPoint.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StopAngle); List<PathGeometryParams> pathGeometry = new List<PathGeometryParams>(); pathGeometry.Add(new LineSegmentParams(center)); pathGeometry.Add(new LineSegmentParams(startPoint)); pathGeometry.Add(new ArcSegmentParams(new Size(pieParams.OuterRadius, pieParams.OuterRadius), 0, pieParams.IsLargerArc, SweepDirection.Clockwise, endPoint)); if ((pieParams.TagReference as DataPoint).InternalYValue != 0) { Path p = new Path() { IsHitTestVisible = false }; p.SetValue(Canvas.ZIndexProperty, (Int32)10000); p.Data = GetPathGeometryFromList(FillRule.Nonzero, center, pathGeometry, true); visual.Children.Add(p); faces.BorderElements.Add(p); } #endregion #region Bevel if (pieParams.Bevel && Math.Abs(pieParams.StartAngle - pieParams.StopAngle) > 0.03 && (pieParams.StartAngle != pieParams.StopAngle)) { //Point startPoint = new Point(); //Point endPoint = new Point(); //startPoint.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StartAngle); //startPoint.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StartAngle); //endPoint.X = center.X + pieParams.OuterRadius * Math.Cos(pieParams.StopAngle); //endPoint.Y = center.Y + pieParams.OuterRadius * Math.Sin(pieParams.StopAngle); Point bevelCenter = new Point(); Point bevelStart = new Point(); Point bevelEnd = new Point(); Double bevelLength = 4; Double bevelOuterRadius = Math.Abs(pieParams.OuterRadius - bevelLength); bevelCenter.X = center.X + bevelLength * Math.Cos(pieParams.MeanAngle); bevelCenter.Y = center.Y + bevelLength * Math.Sin(pieParams.MeanAngle); bevelStart.X = center.X + bevelOuterRadius * Math.Cos(pieParams.StartAngle + 0.03); bevelStart.Y = center.Y + bevelOuterRadius * Math.Sin(pieParams.StartAngle + 0.03); bevelEnd.X = center.X + bevelOuterRadius * Math.Cos(pieParams.StopAngle - 0.03); bevelEnd.Y = center.Y + bevelOuterRadius * Math.Sin(pieParams.StopAngle - 0.03); pathGeometry = new List<PathGeometryParams>(); pathGeometry.Add(new LineSegmentParams(center)); pathGeometry.Add(new LineSegmentParams(startPoint)); pathGeometry.Add(new LineSegmentParams(bevelStart)); pathGeometry.Add(new LineSegmentParams(bevelCenter)); Path path = new Path() { Tag = new ElementData() { Element = pieParams.TagReference } }; path.Data = GetPathGeometryFromList(FillRule.Nonzero, bevelCenter, pathGeometry, true); if (pieParams.StartAngle > Math.PI * 0.5 && pieParams.StartAngle <= Math.PI * 1.5) { path.Fill = GetDarkerBevelBrush(pieParams.Background, pieParams.StartAngle * 180 / Math.PI + 135); } else { path.Fill = GetLighterBevelBrush(pieParams.Background, -pieParams.StartAngle * 180 / Math.PI); } // Apply animation to the beveling path if (pieParams.AnimationEnabled) { pieParams.Storyboard = CreateOpacityAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, path, 1, 1, 1); path.Opacity = 0; } faces.Parts.Add(path); visual.Children.Add(path); pathGeometry = new List<PathGeometryParams>(); pathGeometry.Add(new LineSegmentParams(center)); pathGeometry.Add(new LineSegmentParams(endPoint)); pathGeometry.Add(new LineSegmentParams(bevelEnd)); pathGeometry.Add(new LineSegmentParams(bevelCenter)); path = new Path() { Tag = new ElementData() { Element = pieParams.TagReference } }; path.Data = GetPathGeometryFromList(FillRule.Nonzero, bevelCenter, pathGeometry, true); if (pieParams.StopAngle > Math.PI * 0.5 && pieParams.StopAngle <= Math.PI * 1.5) { path.Fill = GetLighterBevelBrush(pieParams.Background, pieParams.StopAngle * 180 / Math.PI + 135); } else { path.Fill = GetDarkerBevelBrush(pieParams.Background, -pieParams.StopAngle * 180 / Math.PI); } // Apply animation to the beveling path if (pieParams.AnimationEnabled) { pieParams.Storyboard = CreateOpacityAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, path, 1, 1, 1); path.Opacity = 0; } faces.Parts.Add(path); visual.Children.Add(path); #region "Outer Bevel" Shape outerBevel; if (enabledDataPoints.Count == 1 || noOfNonZeroDataPoint.Count() == 1) { outerBevel = new Ellipse() { Height = pieParams.OuterRadius * 2, Width = pieParams.OuterRadius * 2, Tag = new ElementData() { Element = pieParams.TagReference } }; GeometryGroup gg = new GeometryGroup(); gg.Children.Add(new EllipseGeometry() { Center = new Point(pieParams.OuterRadius, pieParams.OuterRadius), RadiusX = pieParams.OuterRadius, RadiusY = pieParams.OuterRadius }); gg.Children.Add(new EllipseGeometry() { Center = new Point(pieParams.OuterRadius, pieParams.OuterRadius), RadiusX = bevelOuterRadius, RadiusY = bevelOuterRadius }); outerBevel.Clip = gg; } else { pathGeometry = new List<PathGeometryParams>(); pathGeometry.Add(new LineSegmentParams(endPoint)); pathGeometry.Add(new ArcSegmentParams(new Size(pieParams.OuterRadius, pieParams.OuterRadius), 0, pieParams.IsLargerArc, SweepDirection.Counterclockwise, startPoint)); pathGeometry.Add(new LineSegmentParams(bevelStart)); pathGeometry.Add(new ArcSegmentParams(new Size(bevelOuterRadius, bevelOuterRadius), 0, pieParams.IsLargerArc, SweepDirection.Clockwise, bevelEnd)); outerBevel = new Path() { Tag = new ElementData() { Element = pieParams.TagReference } }; (outerBevel as Path).Data = GetPathGeometryFromList(FillRule.Nonzero, bevelEnd, pathGeometry, true); } if (pieParams.MeanAngle > 0 && pieParams.MeanAngle < Math.PI) { outerBevel.Fill = GetCurvedBevelBrush(pieParams.Background, pieParams.MeanAngle * 180 / Math.PI + 90, Graphics.GenerateDoubleCollection(-0.745, -0.85), Graphics.GenerateDoubleCollection(0, 1)); } else { outerBevel.Fill = GetCurvedBevelBrush(pieParams.Background, pieParams.MeanAngle * 180 / Math.PI + 90, Graphics.GenerateDoubleCollection(0.745, -0.99), Graphics.GenerateDoubleCollection(0, 1)); } // Apply animation to the beveling path if (pieParams.AnimationEnabled) { pieParams.Storyboard = CreateOpacityAnimation(currentDataSeries, pieParams.DataPoint, pieParams.Storyboard, outerBevel, 1, 1, 1); outerBevel.Opacity = 0; } #endregion faces.Parts.Add(outerBevel); visual.Children.Add(outerBevel); } else { faces.Parts.Add(null); faces.Parts.Add(null); faces.Parts.Add(null); } #endregion LabelLine return visual; }
/// <summary> /// Returns 3D Pie shapes /// </summary> /// <param name="faces">Pie faces</param> /// <param name="pieParams">Pie parameters</param> /// <param name="zindex">Zindex</param> /// <param name="unExplodedPoints">UnExploded dataPoints</param> /// <param name="explodedPoints">Exploded dataPoints</param> /// <param name="labelLinePath">Label line path</param> /// <param name="enabledDataPoints">List of enabled dataPoints</param> /// <returns>List of Shape</returns> private static List<Shape> GetPie3D(DataSeries currentDataSeries, ref Faces faces, SectorChartShapeParams pieParams, ref Int32 zindex, ref PieDoughnut3DPoints unExplodedPoints, ref PieDoughnut3DPoints explodedPoints, ref Path labelLinePath, List<DataPoint> enabledDataPoints) { List<Shape> pieFaces = new List<Shape>(); Shape topFace = null, bottomFace = null, rightFace = null, leftFace = null; Point center = new Point(); center.X = pieParams.Width / 2; center.Y = pieParams.Height / 2; // calculate 3d offsets Double yOffset = -pieParams.Depth / 2 * pieParams.ZAxisScaling; // calculate all points Point3D topFaceCenter = new Point3D(); topFaceCenter.X = center.X; topFaceCenter.Y = center.Y + yOffset; topFaceCenter.Z = pieParams.OffsetY * Math.Sin(pieParams.StartAngle) * Math.Cos(pieParams.TiltAngle) + pieParams.Depth * Math.Cos(Math.PI / 2 - pieParams.TiltAngle); Point3D topArcStart = new Point3D(); topArcStart.X = topFaceCenter.X + pieParams.OuterRadius * Math.Cos(pieParams.StartAngle); topArcStart.Y = topFaceCenter.Y + pieParams.OuterRadius * Math.Sin(pieParams.StartAngle) * pieParams.YAxisScaling; topArcStart.Z = (topFaceCenter.Y + pieParams.OuterRadius) * Math.Sin(pieParams.StartAngle) * Math.Cos(pieParams.TiltAngle) + pieParams.Depth * Math.Cos(Math.PI / 2 - pieParams.TiltAngle); Point3D topArcStop = new Point3D(); topArcStop.X = topFaceCenter.X + pieParams.OuterRadius * Math.Cos(pieParams.StopAngle); topArcStop.Y = topFaceCenter.Y + pieParams.OuterRadius * Math.Sin(pieParams.StopAngle) * pieParams.YAxisScaling; topArcStop.Z = (topFaceCenter.Y + pieParams.OuterRadius) * Math.Sin(pieParams.StopAngle) * Math.Cos(pieParams.TiltAngle) + pieParams.Depth * Math.Cos(Math.PI / 2 - pieParams.TiltAngle); Point3D bottomFaceCenter = new Point3D(); bottomFaceCenter.X = center.X; bottomFaceCenter.Y = center.Y - yOffset; bottomFaceCenter.Z = pieParams.OffsetY * Math.Sin(pieParams.StartAngle) * Math.Cos(pieParams.TiltAngle) - pieParams.Depth * Math.Cos(Math.PI / 2 - pieParams.TiltAngle); Point3D bottomArcStart = new Point3D(); bottomArcStart.X = bottomFaceCenter.X + pieParams.OuterRadius * Math.Cos(pieParams.StartAngle); bottomArcStart.Y = bottomFaceCenter.Y + pieParams.OuterRadius * Math.Sin(pieParams.StartAngle) * pieParams.YAxisScaling; bottomArcStart.Z = (bottomFaceCenter.Y + pieParams.OuterRadius) * Math.Sin(pieParams.StartAngle) * Math.Cos(pieParams.TiltAngle) - pieParams.Depth * Math.Cos(Math.PI / 2 - pieParams.TiltAngle); Point3D bottomArcStop = new Point3D(); bottomArcStop.X = bottomFaceCenter.X + pieParams.OuterRadius * Math.Cos(pieParams.StopAngle); bottomArcStop.Y = bottomFaceCenter.Y + pieParams.OuterRadius * Math.Sin(pieParams.StopAngle) * pieParams.YAxisScaling; bottomArcStop.Z = (bottomFaceCenter.Y + pieParams.OuterRadius) * Math.Sin(pieParams.StopAngle) * Math.Cos(pieParams.TiltAngle) - pieParams.Depth * Math.Cos(Math.PI / 2 - pieParams.TiltAngle); Point3D centroid = GetCentroid(topFaceCenter, topArcStart, topArcStop, bottomFaceCenter, bottomArcStart, bottomArcStop); UpdatePositionLabelInsidePie(pieParams, yOffset); if (pieParams.StartAngle == pieParams.StopAngle && pieParams.IsLargerArc || enabledDataPoints.Count == 1) { // draw singleton pie here topFace = new Ellipse() { Tag = new ElementData() { Element = pieParams.TagReference } }; // topFace.Fill = pieParams.Lighting ? Graphics.GetLightingEnabledBrush(pieParams.Background, "Radial", new Double[] { 0.99, 0.745 }) : pieParams.Background; topFace.Fill = pieParams.Lighting ? Graphics.GetLightingEnabledBrush(pieParams.Background, "Linear", new Double[] { 0.99, 0.854 }) : pieParams.Background; topFace.Width = 2 * pieParams.OuterRadius; topFace.Height = 2 * pieParams.OuterRadius * pieParams.YAxisScaling; topFace.SetValue(Canvas.LeftProperty, (Double)(pieParams.Center.X - topFace.Width / 2)); topFace.SetValue(Canvas.TopProperty, (Double)(pieParams.Center.Y - topFace.Height / 2 + yOffset)); pieFaces.Add(topFace); faces.Parts.Add(topFace); bottomFace = new Ellipse() { Tag = new ElementData() { Element = pieParams.TagReference } }; bottomFace.Fill = pieParams.Lighting ? Graphics.GetLightingEnabledBrush(pieParams.Background, "Radial", new Double[] { 0.99, 0.745 }) : pieParams.Background; bottomFace.Width = 2 * pieParams.OuterRadius; bottomFace.Height = 2 * pieParams.OuterRadius * pieParams.YAxisScaling; bottomFace.SetValue(Canvas.LeftProperty, (Double)(pieParams.Center.X - topFace.Width / 2)); bottomFace.SetValue(Canvas.TopProperty, (Double)(pieParams.Center.Y - topFace.Height / 2 + yOffset)); pieFaces.Add(bottomFace); faces.Parts.Add(bottomFace); } else { topFace = GetPieFace(pieParams, centroid, topFaceCenter, topArcStart, topArcStop); pieFaces.Add(topFace); faces.Parts.Add(topFace); bottomFace = GetPieFace(pieParams, centroid, bottomFaceCenter, bottomArcStart, bottomArcStop); pieFaces.Add(bottomFace); faces.Parts.Add(bottomFace); rightFace = GetPieSide(pieParams, centroid, topFaceCenter, bottomFaceCenter, topArcStart, bottomArcStart); pieFaces.Add(rightFace); faces.Parts.Add(rightFace); leftFace = GetPieSide(pieParams, centroid, topFaceCenter, bottomFaceCenter, topArcStop, bottomArcStop); pieFaces.Add(leftFace); faces.Parts.Add(leftFace); } labelLinePath = CreateLabelLine(currentDataSeries, pieParams, center, ref unExplodedPoints, ref explodedPoints); if ((pieParams.TagReference as DataPoint).InternalYValue == 0) return new List<Shape>(); List<Shape> curvedSurface = GetPieOuterCurvedFace(pieParams, centroid, topFaceCenter, bottomFaceCenter); pieFaces.InsertRange(pieFaces.Count, curvedSurface.ToList()); foreach (FrameworkElement fe in curvedSurface) faces.Parts.Add(fe); //Top face ZIndex topFace.SetValue(Canvas.ZIndexProperty, (Int32)(50000)); //BottomFace ZIndex bottomFace.SetValue(Canvas.ZIndexProperty, (Int32)(-50000)); if (pieParams.StartAngle == pieParams.StopAngle && pieParams.IsLargerArc) { } else { // ZIndex of curved face if (pieParams.StartAngle >= Math.PI && pieParams.StartAngle <= Math.PI * 2 && pieParams.StopAngle >= Math.PI && pieParams.StopAngle <= Math.PI * 2 && pieParams.IsLargerArc) { _elementPositionData.Add(new ElementPositionData(rightFace, pieParams.StartAngle, pieParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], 0, Math.PI)); _elementPositionData.Add(new ElementPositionData(leftFace, pieParams.StopAngle, pieParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, 0, Math.PI)); } else if (pieParams.StartAngle >= 0 && pieParams.StartAngle <= Math.PI && pieParams.StopAngle >= 0 && pieParams.StopAngle <= Math.PI && pieParams.IsLargerArc) { _elementPositionData.Add(new ElementPositionData(rightFace, pieParams.StartAngle, pieParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], pieParams.StartAngle, Math.PI)); _elementPositionData.Add(new ElementPositionData(curvedSurface[1], 0, pieParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(leftFace, pieParams.StopAngle, pieParams.StopAngle)); if (labelLinePath != null) labelLinePath.SetValue(Canvas.ZIndexProperty, -50000); } else if (pieParams.StartAngle >= 0 && pieParams.StartAngle <= Math.PI && pieParams.StopAngle >= Math.PI && pieParams.StopAngle <= Math.PI * 2) { _elementPositionData.Add(new ElementPositionData(rightFace, pieParams.StartAngle, pieParams.StartAngle)); // if (labelLinePath != null) // _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StartAngle, Math.PI)); //------------ if (labelLinePath != null) { if (pieParams.StartAngle >= Math.PI / 2 && pieParams.StopAngle <= Math.PI) labelLinePath.SetValue(Canvas.ZIndexProperty, 50000); else _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StartAngle, Math.PI)); } //------------ _elementPositionData.Add(new ElementPositionData(leftFace, pieParams.StopAngle, pieParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], pieParams.StartAngle, Math.PI)); } else if (pieParams.StartAngle >= Math.PI && pieParams.StartAngle <= Math.PI * 2 && pieParams.StopAngle >= 0 && pieParams.StopAngle <= Math.PI) { _elementPositionData.Add(new ElementPositionData(rightFace, pieParams.StartAngle, pieParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], 0, pieParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(leftFace, pieParams.StopAngle, pieParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StopAngle, pieParams.StopAngle)); } else { _elementPositionData.Add(new ElementPositionData(rightFace, pieParams.StartAngle, pieParams.StartAngle)); if (pieParams.StartAngle >= 0 && pieParams.StartAngle < Math.PI / 2 && pieParams.StopAngle >= 0 && pieParams.StopAngle < Math.PI / 2) { if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StopAngle, pieParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], pieParams.StartAngle, pieParams.StopAngle)); } else if (pieParams.StartAngle >= 0 && pieParams.StartAngle < Math.PI / 2 && pieParams.StopAngle >= Math.PI / 2 && pieParams.StopAngle < Math.PI) { if (labelLinePath != null) labelLinePath.SetValue(Canvas.ZIndexProperty, 40000); curvedSurface[0].SetValue(Canvas.ZIndexProperty, 35000); } else if (pieParams.StartAngle >= Math.PI / 2 && pieParams.StartAngle < Math.PI && pieParams.StopAngle >= Math.PI / 2 && pieParams.StopAngle < Math.PI) { if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StartAngle, pieParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], pieParams.StartAngle, pieParams.StopAngle)); } else if (pieParams.StartAngle >= Math.PI && pieParams.StartAngle < Math.PI * 1.5 && pieParams.StopAngle >= Math.PI && pieParams.StopAngle < Math.PI * 1.5) { _elementPositionData.Add(new ElementPositionData(curvedSurface[0], pieParams.StartAngle, pieParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StartAngle, pieParams.StartAngle)); } else if (pieParams.StartAngle >= Math.PI * 1.5 && pieParams.StartAngle < Math.PI * 2 && pieParams.StopAngle >= Math.PI * 1.5 && pieParams.StopAngle < Math.PI * 2) { _elementPositionData.Add(new ElementPositionData(curvedSurface[0], pieParams.StartAngle, pieParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StartAngle, pieParams.StopAngle)); } else { if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, pieParams.StartAngle, pieParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], pieParams.StartAngle, pieParams.StopAngle)); } _elementPositionData.Add(new ElementPositionData(leftFace, pieParams.StopAngle, pieParams.StopAngle)); } } return pieFaces; }
/// <summary> /// Create3DPie /// </summary> /// <param name="width">Visual width</param> /// <param name="height">Visual height</param> /// <param name="series">DataSeries</param> /// <param name="enabledDataPoints"> Enabled InternalDataPoints in the DataSeries</param> /// <param name="dataPoint">DataPoint reference</param> /// <param name="visual">visual canvas reference</param> /// <param name="faces">Visual faces</param> /// <param name="pieParams">Pie parameters</param> /// <param name="offsetX">X offset</param> /// <param name="zindex">Z index of the pie</param> /// <param name="isAnimationEnabled">Whether animation is enabled</param> private static void Create3DPie(DataSeries currentDataSeries, Double widthOfPlotArea, Double height, DataSeries series, List<DataPoint> enabledDataPoints, DataPoint dataPoint, ref Canvas visual, ref Faces faces, ref SectorChartShapeParams pieParams, ref Double offsetX, ref Int32 zindex, Boolean isAnimationEnabled) { #region 3D Pie PieDoughnut3DPoints unExplodedPoints = new PieDoughnut3DPoints(); PieDoughnut3DPoints explodedPoints = new PieDoughnut3DPoints(); pieParams.TagReference = dataPoint; List<Shape> pieFaces = GetPie3D(currentDataSeries, ref faces, pieParams, ref zindex, ref unExplodedPoints, ref explodedPoints, ref dataPoint.LabelLine, enabledDataPoints); foreach (Shape path in pieFaces) { if (path != null) { visual.Children.Add(path); faces.VisualComponents.Add(path); faces.BorderElements.Add(path); path.RenderTransform = new TranslateTransform(); // apply animation to the 3D sections if (isAnimationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, dataPoint, series.Storyboard, path, 1.0 / (series.InternalDataPoints.Count) * (series.InternalDataPoints.IndexOf(dataPoint)), dataPoint.InternalOpacity, 0.5); path.Opacity = 0; } } } if (dataPoint.LabelLine != null && pieParams.LabelLineEnabled) { dataPoint.LabelLine.RenderTransform = new TranslateTransform(); if (dataPoint.InternalYValue == 0) { Line zeroLine = new Line(); zeroLine.X1 = pieParams.Center.X; zeroLine.Y1 = pieParams.Center.Y; zeroLine.X2 = unExplodedPoints.LabelLineStartPoint.X; zeroLine.Y2 = unExplodedPoints.LabelLineStartPoint.Y; zeroLine.Stroke = pieParams.LabelLineColor; zeroLine.StrokeThickness = 0.25; zeroLine.IsHitTestVisible = false; visual.Children.Add(zeroLine); if (isAnimationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, dataPoint, series.Storyboard, zeroLine, 2, zeroLine.Opacity, 0.5); zeroLine.Opacity = 0; } } visual.Children.Add(dataPoint.LabelLine); faces.VisualComponents.Add(dataPoint.LabelLine); } faces.Visual = visual; UpdateExplodedPosition(pieParams, dataPoint, offsetX, unExplodedPoints, explodedPoints, widthOfPlotArea); dataPoint.ExplodeAnimation = new Storyboard(); dataPoint.ExplodeAnimation = CreateExplodingOut3DAnimation(currentDataSeries, dataPoint, dataPoint.ExplodeAnimation, pieFaces, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, unExplodedPoints, explodedPoints, pieParams.OffsetX, pieParams.OffsetY); dataPoint.UnExplodeAnimation = new Storyboard(); dataPoint.UnExplodeAnimation = CreateExplodingIn3DAnimation(currentDataSeries, dataPoint, dataPoint.UnExplodeAnimation, pieFaces, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, unExplodedPoints, explodedPoints, pieParams.OffsetX, pieParams.OffsetY); #endregion }
/// <summary> /// Create a slice of a funnel /// </summary> /// <param name="isLightingGradientLayer">Whether CreateFunnelSlice() function should create a layer for lighting</param> /// <param name="topRadius">Top Radius of the funnel</param> /// <param name="is3D">Whether the chart is a 3D Chart</param> /// <param name="funnelSlice">FunnelSlice canvas reference</param> /// <param name="yScaleTop">Top YScale for 3D view</param> /// <param name="yScaleBottom">Bottom YScale for 3D view</param> /// <param name="sideFillColor">Side surface fill color</param> /// <param name="topFillColor">Top surface fill color</param> /// <param name="topSurfaceStroke">Top surface stroke color</param> /// <param name="animationEnabled">Whether animation is enabled</param> /// <returns>Return funnel slice canvas</returns> private static Canvas CreateFunnelSlice(Boolean isLightingGradientLayer, Double topRadius, Boolean is3D, TriangularChartSliceParms funnelSlice, Double yScaleTop, Double yScaleBottom, Brush sideFillColor, Brush topFillColor, Brush topSurfaceStroke, Boolean animationEnabled) { Double SOLID_FUNNEL_EDGE_THICKNESS = 3; if (funnelSlice.Index == 0 && is3D && isLightingGradientLayer && (funnelSlice.FillType == FillType.Solid)) { funnelSlice.Height += SOLID_FUNNEL_EDGE_THICKNESS; } Canvas sliceCanvas = new Canvas() { Tag = new ElementData() { Element = funnelSlice.DataPoint } }; Canvas visual = new Canvas() { Width = topRadius * 2, Height = funnelSlice.Height, Tag = new ElementData() { Element = funnelSlice.DataPoint } }; // Canvas holds a slice of a funnel chart Faces faces = null; // GeometryGroup for for a funnel slice path GeometryGroup geometryGroup = new GeometryGroup(); // PathGeometry for for a funnel slice path PathGeometry pathGeometry = new PathGeometry(); // pathFigure for for a funnel slice path PathFigure pathFigure = new PathFigure() { StartPoint = new Point(topRadius - funnelSlice.TopRadius, 0) }; // PathFigure of a funnel slice // Path for for a funnel slice Path path4Slice = new Path() { Fill = sideFillColor }; path4Slice.Tag = new ElementData() { Element = funnelSlice.DataPoint }; // Add PathGeometry to GeometryGroup geometryGroup.Children.Add(pathGeometry); // Set path data path4Slice.Data = geometryGroup; // Set properties for path path4Slice.StrokeThickness = 0; path4Slice.Stroke = new SolidColorBrush(Colors.Black); // Add path elements to its parent canvas pathGeometry.Figures.Add(pathFigure); visual.Children.Add(path4Slice); if (is3D) { #region 3D geometryGroup.FillRule = FillRule.Nonzero; // Create top arc left ArcSegment arcSegment = new ArcSegment(); arcSegment.Point = new Point(topRadius, yScaleTop / 2); arcSegment.Size = new Size(funnelSlice.TopRadius, yScaleTop / 2); pathFigure.Segments.Add(arcSegment); // Create top arc right arcSegment = new ArcSegment(); arcSegment.Point = new Point(topRadius + funnelSlice.TopRadius, 0); arcSegment.Size = new Size(funnelSlice.TopRadius, yScaleTop / 2); pathFigure.Segments.Add(arcSegment); // Create right Plain LineSegment lineSegment = new LineSegment() { Point = new Point(topRadius + funnelSlice.BottomRadius, funnelSlice.Height) }; pathFigure.Segments.Add(lineSegment); lineSegment = new LineSegment() { Point = new Point(topRadius - funnelSlice.BottomRadius, funnelSlice.Height) }; pathFigure.Segments.Add(lineSegment); // Create left Plain lineSegment = new LineSegment() { Point = new Point(topRadius - funnelSlice.TopRadius, 0) }; pathFigure.Segments.Add(lineSegment); EllipseGeometry ellipseGeometry = new EllipseGeometry(); ellipseGeometry.Center = new Point(topRadius, funnelSlice.Height); ellipseGeometry.RadiusX = funnelSlice.BottomRadius; ellipseGeometry.RadiusY = yScaleBottom / 2; geometryGroup.Children.Add(ellipseGeometry); // Create ellips for the funnel top Ellipse funnelTopEllipse = new Ellipse() { Height = yScaleTop, Width = funnelSlice.TopRadius * 2, Fill = topFillColor, Tag = new ElementData() { Element = funnelSlice.DataPoint } }; funnelTopEllipse.SetValue(Canvas.TopProperty, -yScaleTop / 2); funnelTopEllipse.SetValue(Canvas.LeftProperty, topRadius - funnelSlice.TopRadius); //if (funnelSlice.DataPoint.Parent.Bevel) funnelTopEllipse.StrokeThickness = 1.24; //else // funnelTopEllipse.StrokeThickness = 0.24; funnelTopEllipse.Stroke = Graphics.GetBevelTopBrush(topSurfaceStroke, 0); visual.Children.Add(funnelTopEllipse); if (!isLightingGradientLayer) { // Update faces for the DataPoint faces = new Faces(); faces.VisualComponents.Add(path4Slice); faces.VisualComponents.Add(funnelTopEllipse); (path4Slice.Tag as ElementData).VisualElementName = "FunnelBase"; (funnelTopEllipse.Tag as ElementData).VisualElementName = "FunnelTop"; #region Creating Seperate BorderLine GeometryGroup borderGeometryGroup = new GeometryGroup(); // PathGeometry for for a funnel slice path PathGeometry leftRightBorderPathGeometry = new PathGeometry(); // LeftLine Border PathFigure leftBorderPathFigure = new PathFigure() { StartPoint = pathFigure.StartPoint }; LineSegment leftBorderLineSegment = new LineSegment() { Point = new Point(topRadius - funnelSlice.BottomRadius, funnelSlice.Height) }; leftBorderPathFigure.Segments.Add(leftBorderLineSegment); leftRightBorderPathGeometry.Figures.Add(leftBorderPathFigure); // RightLine Border PathGeometry rightRightBorderPathGeometry = new PathGeometry(); PathFigure rightBorderPathFigure = new PathFigure() { StartPoint = new Point(topRadius + funnelSlice.TopRadius, 0) }; LineSegment rightBorderLineSegment = new LineSegment() { Point = new Point(topRadius + funnelSlice.BottomRadius, funnelSlice.Height) }; rightBorderPathFigure.Segments.Add(rightBorderLineSegment); rightRightBorderPathGeometry.Figures.Add(rightBorderPathFigure); // Bottom _axisIndicatorBorderElement Ellipse EllipseGeometry ellipseGeometryBorder = new EllipseGeometry(); ellipseGeometryBorder.Center = new Point(topRadius, funnelSlice.Height); ellipseGeometryBorder.RadiusX = funnelSlice.BottomRadius; ellipseGeometryBorder.RadiusY = yScaleBottom / 2; borderGeometryGroup.Children.Add(ellipseGeometryBorder); // Bottom _axisIndicatorBorderElement Ellipse ellipseGeometryBorder = new EllipseGeometry(); ellipseGeometryBorder.Center = new Point(topRadius, 0); ellipseGeometryBorder.RadiusX = funnelSlice.TopRadius; ellipseGeometryBorder.RadiusY = yScaleTop / 2; borderGeometryGroup.Children.Add(ellipseGeometryBorder); borderGeometryGroup.Children.Add(leftRightBorderPathGeometry); borderGeometryGroup.Children.Add(rightRightBorderPathGeometry); Path borderPath = new Path() { Data = borderGeometryGroup, IsHitTestVisible = false }; borderPath.SetValue(Canvas.ZIndexProperty, (Int32)(-1)); visual.Children.Add(borderPath); faces.BorderElements.Add(borderPath); faces.BorderElements.Add(funnelTopEllipse); #endregion faces.Parts.Add(path4Slice); faces.Parts.Add(funnelTopEllipse); funnelSlice.DataPoint.Faces = faces; } else { if (funnelSlice.FillType == FillType.Solid && funnelSlice.Index == 0) { path4Slice.SetValue(Canvas.ZIndexProperty, 1); path4Slice.SetValue(Canvas.TopProperty, (-SOLID_FUNNEL_EDGE_THICKNESS)); funnelSlice.Height -= SOLID_FUNNEL_EDGE_THICKNESS; } path4Slice.IsHitTestVisible = false; funnelTopEllipse.IsHitTestVisible = false; funnelSlice.DataPoint.Faces.Parts.Add(path4Slice); funnelSlice.DataPoint.Faces.Parts.Add(funnelTopEllipse); funnelSlice.DataPoint.Faces.VisualComponents.Add(path4Slice); funnelSlice.DataPoint.Faces.VisualComponents.Add(funnelTopEllipse); (path4Slice.Tag as ElementData).VisualElementName = "Lighting"; (funnelTopEllipse.Tag as ElementData).VisualElementName = "FunnelTopLighting"; } // Apply animation for the 3D funnel slice if (animationEnabled) { funnelSlice.DataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(funnelTopEllipse, funnelSlice.DataPoint.Parent, funnelSlice.DataPoint.Parent.Storyboard, 0, funnelSlice.DataPoint.InternalOpacity, 0, 1); funnelSlice.DataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(path4Slice, funnelSlice.DataPoint.Parent, funnelSlice.DataPoint.Parent.Storyboard, 0, funnelSlice.DataPoint.InternalOpacity, 0, 1); } #endregion } else { // Points of a 2D funnel slice Point[] funnelCornerPoints = new Point[8]; // Top line LineSegment lineSegment = new LineSegment() { Point = new Point(topRadius - funnelSlice.BottomRadius, funnelSlice.Height) }; pathFigure.Segments.Add(lineSegment); funnelCornerPoints[3] = lineSegment.Point; // Right line lineSegment = new LineSegment() { Point = new Point(topRadius + funnelSlice.BottomRadius, funnelSlice.Height) }; pathFigure.Segments.Add(lineSegment); funnelCornerPoints[2] = lineSegment.Point; // Bottom line lineSegment = new LineSegment() { Point = new Point(topRadius + funnelSlice.TopRadius, 0) }; pathFigure.Segments.Add(lineSegment); funnelCornerPoints[1] = lineSegment.Point; // Left line lineSegment = new LineSegment() { Point = new Point(topRadius - funnelSlice.TopRadius, 0) }; pathFigure.Segments.Add(lineSegment); funnelCornerPoints[0] = lineSegment.Point; // Apply animation for the 2D funnel slice if (animationEnabled) funnelSlice.DataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(path4Slice, funnelSlice.DataPoint.Parent, funnelSlice.DataPoint.Parent.Storyboard, 0, funnelSlice.DataPoint.InternalOpacity, 0, 1); if (!isLightingGradientLayer) { // Update faces for the DataPoint faces = new Faces(); faces.VisualComponents.Add(path4Slice); (path4Slice.Tag as ElementData).VisualElementName = "FunnelBase"; faces.Parts.Add(path4Slice); faces.BorderElements.Add(path4Slice); funnelSlice.DataPoint.Faces = faces; // Apply bevel effect for the 2D funnel Slice if (funnelSlice.DataPoint.Parent.Bevel) { ApplyFunnelBevel(visual, funnelSlice, sideFillColor, funnelCornerPoints); } } else { path4Slice.IsHitTestVisible = false; funnelSlice.DataPoint.Faces.VisualComponents.Add(path4Slice); (path4Slice.Tag as ElementData).VisualElementName = "Lighting"; } } if (isLightingGradientLayer) { visual.IsHitTestVisible = false; } else { // Drawing LabelLine Canvas labelLineCanvas = CreateLabelLine(funnelSlice, topRadius, animationEnabled); if (labelLineCanvas != null) { sliceCanvas.Children.Add(labelLineCanvas); faces.VisualComponents.Add(labelLineCanvas); } // Add label visual to the visual if ((Boolean)funnelSlice.DataPoint.LabelEnabled) { Canvas labelCanvas = new Canvas(); labelCanvas.SetValue(Canvas.ZIndexProperty, (Int32)10); faces.VisualComponents.Add(funnelSlice.DataPoint.LabelVisual); // Label placement funnelSlice.DataPoint.LabelVisual.SetValue(Canvas.TopProperty, funnelSlice.LabelLineEndPoint.Y - funnelSlice.DataPoint.LabelVisual.Height / 2); if (funnelSlice.DataPoint.LabelStyle == LabelStyles.OutSide) { funnelSlice.DataPoint.LabelVisual.SetValue(Canvas.TopProperty, funnelSlice.LabelLineEndPoint.Y - funnelSlice.DataPoint.LabelVisual.Height / 2); funnelSlice.DataPoint.LabelVisual.SetValue(Canvas.LeftProperty, funnelSlice.LabelLineEndPoint.X); } else { funnelSlice.DataPoint.LabelVisual.SetValue(Canvas.TopProperty, funnelSlice.LabelLineEndPoint.Y - funnelSlice.DataPoint.LabelVisual.Height / 2 + (is3D ? yScaleTop / 2 : 0)); funnelSlice.DataPoint.LabelVisual.SetValue(Canvas.LeftProperty, topRadius - funnelSlice.DataPoint.LabelVisual.Width / 2); } if (animationEnabled) funnelSlice.DataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(funnelSlice.DataPoint.LabelVisual, funnelSlice.DataPoint.Parent, funnelSlice.DataPoint.Parent.Storyboard, 1.2, 0.5, 0, 1); labelCanvas.Children.Add(funnelSlice.DataPoint.LabelVisual); sliceCanvas.Children.Add(labelCanvas); } } // if (!isLightingGradientLayer) // faces.Visual = visual; sliceCanvas.Children.Add(visual); // sliceCanvas.Background = new SolidColorBrush(Color.FromArgb((byte)rand.Next(0,200),(byte)rand.Next(0,200),(byte)rand.Next(0,200),(byte)rand.Next(0,200))); return sliceCanvas; }
/// <summary> /// Draws the Vertical 3D Plank /// </summary> /// <param name="height">Height of the PlotArea canvas</param> /// <param name="plankDepth">PlankDepth</param> /// <param name="plankThickness">PlankThickness</param> /// <param name="plankOpacity">PlankOpacity</param> private void DrawVerticalPlank(Double height, Double plankDepth, Double plankThickness, Double plankOpacity, Boolean isPartialUpdate) { if (isPartialUpdate) { ColumnChart.Update3DPlank(plankThickness, height, plankDepth, _verticalPlank); return; } // RectangularChartShapeParams columnParams = new RectangularChartShapeParams(); // columnParams.BackgroundBrush = new SolidColorBrush(Color.FromArgb((Byte)255, (Byte)127, (Byte)127, (Byte)127)); // columnParams.Lighting = true; // columnParams.Size = new Size(plankThickness, height); // columnParams.Depth = plankDepth; if (_verticalPlank != null && _verticalPlank.Visual != null && _verticalPlank.Visual.Parent != null) { Panel parent = _verticalPlank.Visual.Parent as Canvas; parent.Children.Remove(_verticalPlank.Visual); } List<Color> colors = new List<Color>(); colors.Add(Color.FromArgb(255, 232, 232, 232)); colors.Add(Color.FromArgb(255, 142, 135, 135)); Brush rightBrush = Graphics.CreateLinearGradientBrush(0, new Point(0, 0.5), new Point(1, 0.5), colors, new List<double>() { 0, 1 }); _verticalPlank = ColumnChart.Get3DPlank(plankThickness, height, plankDepth, null, null, rightBrush); Panel plank = _verticalPlank.Visual as Panel; plank.SetValue(Canvas.TopProperty, plankDepth); plank.SetValue(Canvas.ZIndexProperty, -1); plank.SetValue(Canvas.OpacityProperty, plankOpacity); PlottingCanvas.Children.Add(plank); }
/// <summary> /// Get visual object for area chart /// </summary> /// <param name="width">Width of the PlotArea</param> /// <param name="height">Height of the PlotArea</param> /// <param name="plotDetails">PlotDetails</param> /// <param name="seriesList">List of DataSeries with render as area chart</param> /// <param name="chart">Chart</param> /// <param name="plankDepth">PlankDepth</param> /// <param name="animationEnabled">Whether animation is enabled for chart</param> /// <returns>Area chart canvas</returns> internal static Canvas GetVisualObjectForAreaChart(Panel preExistingPanel, Double width, Double height, PlotDetails plotDetails, List<DataSeries> seriesList, Chart chart, Double plankDepth, bool animationEnabled) { if (Double.IsNaN(width) || Double.IsNaN(height) || width <= 0 || height <= 0) return null; DataSeries series = seriesList[0] as DataSeries; if (animationEnabled) { if (series.Storyboard == null) series.Storyboard = new Storyboard(); } Canvas visual, labelCanvas, areaCanvas, areaFaceCanvas; RenderHelper.RepareCanvas4Drawing(preExistingPanel as Canvas, out visual, out labelCanvas, out areaCanvas, width, height); areaFaceCanvas = new Canvas() { Height = height, Width = width }; Double depth3d = plankDepth / plotDetails.Layer3DCount * (chart.View3D ? 1 : 0); Double visualOffset = depth3d * (plotDetails.SeriesDrawingIndex[series] + 1); visual.SetValue(Canvas.TopProperty, visualOffset); visual.SetValue(Canvas.LeftProperty, -visualOffset); labelCanvas.SetValue(Canvas.TopProperty, (Double)0); labelCanvas.SetValue(Canvas.LeftProperty, (Double)0); areaFaceCanvas.SetValue(Canvas.TopProperty, (Double)0); areaFaceCanvas.SetValue(Canvas.LeftProperty, (Double)0); //areaFaceCanvas.SetValue(Canvas.ZIndexProperty, (Int32)1); DataSeries currentDataSeries; Double minimumXValue = Double.MaxValue; Double maximumXValue = Double.MinValue; if ((Boolean)series.Enabled) { if (series.Storyboard == null) series.Storyboard = new Storyboard(); currentDataSeries = series; PlotGroup plotGroup = series.PlotGroup; Double limitingYValue = plotGroup.GetLimitingYValue(); minimumXValue = Math.Min(minimumXValue, plotGroup.MinimumX); maximumXValue = Math.Max(maximumXValue, plotGroup.MaximumX); //List<DataPoint> enabledDataPoints = (from datapoint in series.InternalDataPoints where datapoint.Enabled == true select datapoint).ToList(); Faces dataSeriesFaces = new Faces(); dataSeriesFaces.FrontFacePaths = new List<Path>(); dataSeriesFaces.Visual = areaFaceCanvas; dataSeriesFaces.LabelCanvas = labelCanvas; series.Faces = dataSeriesFaces; List<List<DataPoint>> brokenAreaDataPointsCollection = BrokenAreaDataPointsGroup(width, height, series); DataPoint currentDataPoint; DataPoint nextDataPoint; DataPoint previusDataPoint; Double plankYPos = Graphics.ValueToPixelPosition(height, 0, (Double)plotGroup.AxisY.InternalAxisMinimum, (Double)plotGroup.AxisY.InternalAxisMaximum, limitingYValue); foreach (List<DataPoint> dataPointList in brokenAreaDataPointsCollection) { if (dataPointList.Count <= 0) continue; currentDataPoint = dataPointList[0]; previusDataPoint = currentDataPoint; PointCollection points = new PointCollection(); List<DataPoint> dataPoints = new List<DataPoint>(); Path frontFacePath = null; PathGeometry frontFacePathGeometry; PathFigure frontFacePathFigure = null; Int32 maxZIndex = 0; for (Int32 i = 0; i < dataPointList.Count - 1; i++) { Path areaBase = new Path(); Faces dataPointFaces; Faces nextDataPointFaces = new Faces(); currentDataPoint = dataPointList[i]; currentDataPoint._parsedToolTipText = currentDataPoint.TextParser(currentDataPoint.ToolTipText); nextDataPoint = dataPointList[i + 1]; if (currentDataPoint.Faces == null) { dataPointFaces = new Faces(); currentDataPoint.Faces = dataPointFaces; } else dataPointFaces = currentDataPoint.Faces; nextDataPoint.Faces = nextDataPointFaces; dataPointFaces.PreviousDataPoint = previusDataPoint; dataPointFaces.NextDataPoint = nextDataPoint; if (i == 0) { // For the first DataPoint left and top face are drawn. Double xPosDataPoint = Graphics.ValueToPixelPosition(0, width, (Double)plotGroup.AxisX.InternalAxisMinimum, (Double)plotGroup.AxisX.InternalAxisMaximum, currentDataPoint.InternalXValue); if (chart.View3D) { // Set points for left face Area3DDataPointFace leftFace = new Area3DDataPointFace(depth3d); leftFace.FrontFacePoints.Add(new Point(xPosDataPoint, plankYPos)); // Bottom Point leftFace.FrontFacePoints.Add(currentDataPoint._visualPosition); // Top Point currentDataPoint.Faces.Area3DLeftFace = leftFace; // Set points for top left face Area3DDataPointFace topFace = new Area3DDataPointFace(depth3d); topFace.FrontFacePoints.Add(currentDataPoint._visualPosition); // Front Left Point topFace.FrontFacePoints.Add(nextDataPoint._visualPosition); // Front Right Point currentDataPoint.Faces.Area3DRightTopFace = topFace; nextDataPointFaces.Area3DLeftTopFace = topFace; } // Start creating front face of 3D area frontFacePath = new Path() { Opacity = currentDataPoint.Parent.Opacity }; //frontFacePath = new Path() { Opacity = 0.5 }; ApplyBorderProperties(frontFacePath, currentDataPoint.Parent); dataSeriesFaces.FrontFacePaths.Add(frontFacePath); frontFacePathGeometry = new PathGeometry(); frontFacePathFigure = new PathFigure() { StartPoint = new Point(xPosDataPoint, plankYPos), IsClosed = true }; frontFacePathGeometry.Figures.Add(frontFacePathFigure); frontFacePath.Data = frontFacePathGeometry; // Area front face Line path from end point to first LineSegment ls = new LineSegment() { Point = currentDataPoint._visualPosition }; frontFacePathFigure.Segments.Add(ls); dataPointFaces.AreaFrontFaceLineSegment = ls; } else { if (chart.View3D) { // DataPoint which has two different top faces at the left and right side of it position. Area3DDataPointFace topFace = new Area3DDataPointFace(depth3d); topFace.FrontFacePoints.Add(currentDataPoint._visualPosition); // Front Left Point topFace.FrontFacePoints.Add(nextDataPoint._visualPosition); // Front Right Point currentDataPoint.Faces.Area3DRightTopFace = topFace; nextDataPointFaces.Area3DLeftTopFace = topFace; } else { if(currentDataPoint.Parent.Bevel) CreateBevelFor2DArea(areaFaceCanvas, currentDataPoint, previusDataPoint,false, false); } // Area front face Line path LineSegment ls = new LineSegment() { Point = currentDataPoint._visualPosition }; frontFacePathFigure.Segments.Add(ls); dataPointFaces.AreaFrontFaceLineSegment = ls; } #region Create Marker if (nextDataPoint.MarkerEnabled == true || nextDataPoint.LabelEnabled == true) { Double xPos, yPos; // Create Marker Marker marker = LineChart.CreateMarkerAForLineDataPoint(currentDataPoint, width, height, ref labelCanvas, out xPos, out yPos); //if (marker != null) //{ // //LineChart.ApplyDefaultInteractivityForMarker(dataPoint); // //marker.AddToParent(labelCanvas, currentDataPoint._visualPosition.X, currentDataPoint._visualPosition.Y, new Point(0.5, 0.5)); // // Apply marker animation // if (animationEnabled) // { // if (currentDataPoint.Parent.Storyboard == null) // currentDataPoint.Parent.Storyboard = new Storyboard(); // // Apply marker animation // currentDataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(marker, CurrentDataSeries, currentDataPoint.Parent.Storyboard, 1, currentDataPoint.Opacity * currentDataPoint.Parent.Opacity); // } //} } #endregion if (chart.View3D) { Int32 zindex = Draw3DArea(areaFaceCanvas, previusDataPoint, currentDataPoint, nextDataPoint, ref dataSeriesFaces, ref dataPointFaces, currentDataPoint.Parent, plankYPos); maxZIndex = Math.Max(maxZIndex, zindex); } else { //areaCanvas.Children.Add(Get2DArea(ref faces, areaParams)); } if (i == dataPointList.Count - 2) // If next DataPoint is the last DataPoint { if (chart.View3D) { DataPoint lastDataPoint = nextDataPoint; Area3DDataPointFace rightFace = new Area3DDataPointFace(depth3d); rightFace.FrontFacePoints.Add(nextDataPoint._visualPosition); // Front top point rightFace.FrontFacePoints.Add(new Point(nextDataPoint._visualPosition.X, plankYPos)); nextDataPoint.Faces.Area3DRightFace = rightFace; // Draw base of the 3d area areaBase = new Path(); areaBase.Fill = (Boolean)dataPointList[0].Parent.LightingEnabled ? Graphics.GetTopFaceBrush(dataPointList[0].Parent.Color) : dataPointList[0].Parent.Color; PathGeometry pg = new PathGeometry(); PathFigure pf = new PathFigure() { StartPoint = new Point(dataPointList[0]._visualPosition.X, plankYPos) }; pg.Figures.Add(pf); pf.Segments.Add(new LineSegment() { Point = new Point(dataPointList[0]._visualPosition.X + depth3d, plankYPos - depth3d) }); pf.Segments.Add(new LineSegment() { Point = new Point(lastDataPoint._visualPosition.X + depth3d, plankYPos - depth3d) }); pf.Segments.Add(new LineSegment() { Point = new Point(lastDataPoint._visualPosition.X, plankYPos) }); areaBase.Data = pg; areaBase.SetValue(Canvas.ZIndexProperty, (Int32) 1); areaBase.Opacity = lastDataPoint.Parent.Opacity; areaCanvas.Children.Add(areaBase); dataSeriesFaces.FrontFacePaths.Add(areaBase); series.Faces.VisualComponents.Add(areaBase); // Animating AreaBase opacity if (animationEnabled) series.Storyboard = AnimationHelper.ApplyOpacityAnimation(areaBase, series, series.Storyboard, 0.25, 1, 0, 1); } else { if (nextDataPoint.Parent.Bevel) CreateBevelFor2DArea(areaFaceCanvas, nextDataPoint, currentDataPoint, false, false); } // Front face for 3D and 2D both LineSegment ls = new LineSegment() { Point = nextDataPoint._visualPosition }; frontFacePathFigure.Segments.Add(ls); nextDataPointFaces.AreaFrontFaceLineSegment = ls; ls = new LineSegment() { Point = new Point(nextDataPoint._visualPosition.X, plankYPos) }; frontFacePathFigure.Segments.Add(ls); nextDataPointFaces.AreaFrontFaceBaseLineSegment = ls; nextDataPointFaces.NextDataPoint = nextDataPoint; // Graphics.DrawPointAt(rightFace.FrontFacePoints[0], areaCanvas, Colors.Yellow); if (chart.View3D) { Int32 zindex = Draw3DArea(areaFaceCanvas, previusDataPoint, nextDataPoint, nextDataPoint, ref dataSeriesFaces, ref nextDataPointFaces, nextDataPoint.Parent, plankYPos); maxZIndex = Math.Max(maxZIndex, zindex); } else { // areaCanvas.Children.Add(Get2DArea(ref faces, areaParams)); } if (nextDataPoint.MarkerEnabled == true || nextDataPoint.LabelEnabled == true) { Double xPos, yPos; Marker marker = LineChart.CreateMarkerAForLineDataPoint(nextDataPoint, width, height, ref labelCanvas, out xPos, out yPos); } nextDataPoint._parsedToolTipText = nextDataPoint.TextParser(nextDataPoint.ToolTipText); } previusDataPoint = currentDataPoint; } if (frontFacePath != null) { if (chart.View3D) frontFacePath.Fill = (Boolean)dataPointList[0].Parent.LightingEnabled ? Graphics.GetFrontFaceBrush(dataPointList[0].Parent.Color) : dataPointList[0].Parent.Color; else frontFacePath.Fill = (Boolean)dataPointList[0].Parent.LightingEnabled ? Graphics.GetLightingEnabledBrush(dataPointList[0].Parent.Color, "Linear", null) : dataPointList[0].Parent.Color; series.Faces.VisualComponents.Add(frontFacePath); frontFacePath.SetValue(Canvas.ZIndexProperty, maxZIndex); areaFaceCanvas.Children.Add(frontFacePath); } foreach (FrameworkElement face in series.Faces.VisualComponents) VisifireElement.AttachEvents2AreaVisual(currentDataPoint, currentDataPoint, face); } foreach (FrameworkElement face in series.Faces.VisualComponents) VisifireElement.AttachEvents2AreaVisual(series, series, face); series.AttachAreaToolTip(chart, dataSeriesFaces.VisualComponents); areaFaceCanvas.Tag = null; Canvas plank = ColumnChart.CreateOrUpdatePlank(chart, series.PlotGroup.AxisY, areaCanvas, depth3d, Orientation.Horizontal); // apply area animation if (animationEnabled) { // if (series.Storyboard == null) // series.Storyboard = new Storyboard(); ScaleTransform scaleTransform = new ScaleTransform() { ScaleY = 0 }; areaFaceCanvas.RenderTransformOrigin = new Point(0.5, plankYPos / height); areaFaceCanvas.RenderTransform = scaleTransform; List<KeySpline> splines = AnimationHelper.GenerateKeySplineList ( new Point(0, 0), new Point(1, 1), new Point(0, 1), new Point(0.5, 1) ); // Apply animation to the entire canvas that was used to create the area series.Storyboard = AnimationHelper.ApplyPropertyAnimation(scaleTransform, "(ScaleTransform.ScaleY)", series, series.Storyboard, 1, new Double[] { 0, 1 }, new Double[] { 0, 1 }, splines); // Animating plank opacity //series.Storyboard = AnimationHelper.ApplyOpacityAnimation(areaBase, series, series.Storyboard, 1.25, 1, 0, 1); // Apply animation for label canvas series.Storyboard = AnimationHelper.ApplyOpacityAnimation(labelCanvas, series, series.Storyboard, 1.25, 1, 0, 1); } } areaFaceCanvas.SetValue(Canvas.ZIndexProperty, (Int32)2); areaCanvas.Children.Add(areaFaceCanvas); // Remove old visual and add new visual in to the existing panel if (preExistingPanel != null) { visual.Children.RemoveAt(1); visual.Children.Add(areaCanvas); } else { labelCanvas.SetValue(Canvas.ZIndexProperty, 1); visual.Children.Add(labelCanvas); visual.Children.Add(areaCanvas); } RectangleGeometry clipRectangle = new RectangleGeometry(); clipRectangle.Rect = new Rect(0, -depth3d - 4, width + depth3d, height + depth3d + chart.ChartArea.PLANK_THICKNESS + 10); areaCanvas.Clip = clipRectangle; // Clip the label canvas clipRectangle = new RectangleGeometry(); Double clipLeft = 0; Double clipTop = -depth3d - 4; Double clipWidth = width + depth3d; Double clipHeight = height + depth3d + chart.ChartArea.PLANK_THICKNESS + 10; GetClipCoordinates(chart, ref clipLeft, ref clipTop, ref clipWidth, ref clipHeight, minimumXValue, maximumXValue); clipRectangle.Rect = new Rect(clipLeft, clipTop, clipWidth, clipHeight); labelCanvas.Clip = clipRectangle; return visual; }
/// <summary> /// Create 3D bar for a DataPoint /// </summary> /// <param name="barParams">Bar parameters</param> /// <returns>Faces for bar</returns> internal static Faces Get3DBar(RectangularChartShapeParams barParams) { Faces faces = new Faces(); Canvas barVisual = new Canvas(); barVisual.Width = barParams.Size.Width; barVisual.Height = barParams.Size.Height; Brush frontBrush = barParams.Lighting ? Graphics.GetFrontFaceBrush(barParams.BackgroundBrush) : barParams.BackgroundBrush; Brush topBrush = barParams.Lighting ? Graphics.GetTopFaceBrush(barParams.BackgroundBrush) : barParams.BackgroundBrush; Brush rightBrush = barParams.Lighting ? Graphics.GetRightFaceBrush(barParams.BackgroundBrush) : barParams.BackgroundBrush; Rectangle front = ExtendedGraphics.Get2DRectangle(barParams.TagReference, barParams.Size.Width, barParams.Size.Height, barParams.BorderThickness, barParams.BorderStyle, barParams.BorderBrush, frontBrush, new CornerRadius(0), new CornerRadius(0)); faces.Parts.Add(front); faces.BorderElements.Add(front); Rectangle top = ExtendedGraphics.Get2DRectangle(barParams.TagReference, barParams.Size.Width, barParams.Depth, barParams.BorderThickness, barParams.BorderStyle, barParams.BorderBrush, topBrush, new CornerRadius(0), new CornerRadius(0)); faces.Parts.Add(top); faces.BorderElements.Add(top); top.RenderTransformOrigin = new Point(0, 1); SkewTransform skewTransTop = new SkewTransform(); skewTransTop.AngleX = -45; top.RenderTransform = skewTransTop; Rectangle right = ExtendedGraphics.Get2DRectangle(barParams.TagReference, barParams.Depth, barParams.Size.Height, barParams.BorderThickness, barParams.BorderStyle, barParams.BorderBrush, rightBrush, new CornerRadius(0), new CornerRadius(0)); faces.Parts.Add(right); faces.BorderElements.Add(right); right.RenderTransformOrigin = new Point(0, 0); SkewTransform skewTransRight = new SkewTransform(); skewTransRight.AngleY = -45; right.RenderTransform = skewTransRight; barVisual.Children.Add(front); barVisual.Children.Add(top); barVisual.Children.Add(right); top.SetValue(Canvas.TopProperty, -barParams.Depth); right.SetValue(Canvas.LeftProperty, barParams.Size.Width); faces.Visual = barVisual; faces.VisualComponents.Add(front); faces.VisualComponents.Add(top); faces.VisualComponents.Add(right); return faces; }
/// <summary> /// Get visual for StackedArea 2D /// </summary> /// <param name="faces">Faces</param> /// <param name="areaParams">Area parameters</param> /// <returns>Canvas</returns> internal static Canvas GetStacked2DArea(ref Faces faces, PolygonalChartShapeParams areaParams) { if (faces.Parts == null) faces.Parts = new List<DependencyObject>(); Canvas visual = new Canvas(); visual.Width = areaParams.Size.Width; visual.Height = areaParams.Size.Height; Polygon polygon = new Polygon() { Tag = new ElementData() { Element = areaParams.TagReference, VisualElementName = "AreaBase" } }; faces.Parts.Add(polygon); polygon.Fill = areaParams.Lighting ? Graphics.GetLightingEnabledBrush(areaParams.Background, "Linear", null) : areaParams.Background; polygon.Stroke = areaParams.BorderColor; polygon.StrokeDashArray = areaParams.BorderStyle != null ? ExtendedGraphics.CloneCollection(areaParams.BorderStyle) : areaParams.BorderStyle; polygon.StrokeThickness = areaParams.BorderThickness; polygon.StrokeMiterLimit = 1; polygon.Points = areaParams.Points; Rect polygonBounds = GetBounds(areaParams.Points); polygon.Stretch = Stretch.Fill; polygon.Width = polygonBounds.Width; polygon.Height = polygonBounds.Height; polygon.SetValue(Canvas.TopProperty, polygonBounds.Y); polygon.SetValue(Canvas.LeftProperty, polygonBounds.X); visual.Children.Add(polygon); if (areaParams.Bevel) { for (int i = 0; i < areaParams.Points.Count - 1; i++) { if (areaParams.Points[i].X == areaParams.Points[i + 1].X) continue; Double m = GetSlope(areaParams.Points[i].X, areaParams.Points[i].Y, areaParams.Points[i + 1].X, areaParams.Points[i + 1].Y); Double c = GetIntercept(areaParams.Points[i].X, areaParams.Points[i].Y, areaParams.Points[i + 1].X, areaParams.Points[i + 1].Y); c = c + (areaParams.IsPositive ? 1 : -1) * 4; Point newPt1 = new Point(areaParams.Points[i].X, m * areaParams.Points[i].X + c); Point newPt2 = new Point(areaParams.Points[i + 1].X, m * areaParams.Points[i + 1].X + c); PointCollection points = new PointCollection(); points.Add(areaParams.Points[i]); points.Add(areaParams.Points[i + 1]); points.Add(newPt2); points.Add(newPt1); Polygon bevel = new Polygon() { Tag = new ElementData() { Element = areaParams.TagReference, VisualElementName = "Bevel" } }; bevel.Points = points; bevel.Fill = Graphics.GetBevelTopBrush(areaParams.Background); faces.Parts.Add(bevel); visual.Children.Add(bevel); } } return visual; }
/// <summary> /// Get Stacked3DArea front face /// </summary> /// <param name="faces">Faces</param> /// <param name="areaParams">Area parameters</param> /// <returns>Canvas</returns> internal static Canvas GetStacked3DAreaFrontFace(ref Faces faces, PolygonalChartShapeParams areaParams) { Polygon polygon = new Polygon() { Tag = new ElementData() { Element = areaParams.TagReference, VisualElementName = "AreaBase" } }; faces.Parts.Add(polygon); Point centroid = GetCentroid(areaParams.Points); Rect size = GetBounds(areaParams.Points); polygon.SetValue(Canvas.ZIndexProperty, (Int32)centroid.Y + 1000); polygon.Fill = areaParams.Lighting ? Graphics.GetFrontFaceBrush(areaParams.Background) : areaParams.Background; polygon.Stroke = areaParams.BorderColor; polygon.StrokeDashArray = areaParams.BorderStyle != null ? ExtendedGraphics.CloneCollection(areaParams.BorderStyle) : areaParams.BorderStyle; polygon.StrokeThickness = areaParams.BorderThickness; polygon.StrokeMiterLimit = 1; polygon.Points = areaParams.Points; polygon.Stretch = Stretch.Fill; polygon.Width = size.Width; polygon.Height = size.Height; polygon.SetValue(Canvas.TopProperty, areaParams.Depth3D); polygon.SetValue(Canvas.LeftProperty, 0.0); Canvas polygonSet = new Canvas() { Tag = new ElementData() { Element = areaParams.TagReference } }; polygonSet.Width = size.Width + areaParams.Depth3D; polygonSet.Height = size.Height + areaParams.Depth3D; polygonSet.SetValue(Canvas.TopProperty, size.Top - areaParams.Depth3D); polygonSet.SetValue(Canvas.LeftProperty, size.Left); polygonSet.Children.Add(polygon); return polygonSet; }
/// <summary> /// Get visual of Area 3D /// </summary> /// <param name="faces">Faces</param> /// <param name="areaParams">AreaParams</param> /// <returns>ZIndex</returns> internal static Int32 Draw3DArea(Canvas parentVisual, DataPoint previusDataPoint, DataPoint dataPoint, DataPoint nextDataPoint, ref Faces dataSeriesFaces, ref Faces dataPointFaces, DataSeries dataSeries, Double plankYPos) { Brush sideBrush = (Boolean) dataSeries.LightingEnabled ? Graphics.GetRightFaceBrush(dataSeries.Color) : dataSeries.Color; Brush topBrush = (Boolean)dataSeries.LightingEnabled ? Graphics.GetTopFaceBrush(dataSeries.Color) : dataSeries.Color; // Int32 pointIndexLimit = dataSeries.IsPositive ? areaParams.Points.Count - 1 : areaParams.Points.Count; Random rand = new Random(DateTime.Now.Millisecond); // parentVisual.Background = new SolidColorBrush(Colors.Green); Boolean isPositive2Negative = false; // DataPoint at -ve, previous DataPoint is positive //Boolean isNegative2Positive = false; // DataPoint at -ve, next DataPoint is positive //if (dataPoint.InternalYValue < 0 && previusDataPoint.InternalYValue > 0) // isPositive2Negative = true; //if (dataPoint.InternalYValue > 0 && nextDataPoint.InternalYValue < 0) // isNegative2Positive = true; Int32 zIndex = GetAreaZIndex(dataPoint._visualPosition.X, dataPoint._visualPosition.Y, dataPoint.InternalYValue > 0 || isPositive2Negative); //dataPointFaces.da if (dataPointFaces.Area3DLeftFace != null) { Area3DDataPointFace leftFace = dataPointFaces.Area3DLeftFace; leftFace.CalculateBackFacePoints(); Path sides = new Path() { Tag = new ElementData() { Element = dataSeries } }; sides.SetValue(Canvas.ZIndexProperty, zIndex); PathGeometry pg = new PathGeometry(); PathFigure pf = new PathFigure() { IsClosed = true }; pg.Figures.Add(pf); PointCollection facePoints = leftFace.GetFacePoints(); pf.StartPoint = leftFace.FrontFacePoints[0]; // Graphics.DrawPointAt(dataPointFaces.Area3DLeftFace.FrontPointLeft, parentVisual, Colors.Yellow); foreach (Point point in facePoints) { LineSegment ls = new LineSegment() { Point = point }; pf.Segments.Add(ls); } sides.Data = pg; sides.Fill = sideBrush; sides.Opacity = dataPoint.Parent.Opacity; ApplyBorderProperties(sides, dataPoint.Parent); // sides.Fill = new SolidColorBrush(Color.FromArgb(255, (byte)rand.Next(155), (byte)rand.Next(200), (byte)rand.Next(126))); parentVisual.Children.Add(sides); leftFace.LeftFace = sides; //dataPointFaces.VisualComponents.Add(sides); //dataPointFaces.Parts.Add(sides); dataSeriesFaces.VisualComponents.Add(sides); //dataPointFaces.BorderElements.Add(sides); } if (dataPointFaces.Area3DLeftTopFace != null) { Area3DDataPointFace topFace = dataPointFaces.Area3DLeftTopFace; if (isPositive2Negative) { //Graphics.DrawPointAt(new Point(previusDataPoint._visualPosition.X, plankYPos), parentVisual, Colors.Red); //Graphics.DrawPointAt(new Point(dataPoint._visualPosition.X, plankYPos), parentVisual, Colors.Red); //Graphics.DrawPointAt(previusDataPoint._visualPosition, parentVisual, Colors.Red); //Graphics.DrawPointAt(dataPoint._visualPosition, parentVisual, Colors.Red); Point midPoint = new Point(); if (dataPointFaces.Area3DRightFace == null) { if (Graphics.IntersectionOfTwoStraightLines(new Point(previusDataPoint._visualPosition.X, plankYPos), new Point(dataPoint._visualPosition.X, plankYPos), previusDataPoint._visualPosition, dataPoint._visualPosition, ref midPoint)) { topFace.FrontFacePoints[1] = midPoint; //Graphics.DrawPointAt(midPoint, parentVisual, Colors.Green); } } //Graphics.DrawPointAt(midPoint, parentVisual, Colors.Green); } //if (isNegative2Positive) //{ // Graphics.DrawPointAt(new Point(previusDataPoint._visualPosition.X, plankYPos), parentVisual, Colors.Red); // Graphics.DrawPointAt(new Point(dataPoint._visualPosition.X, plankYPos), parentVisual, Colors.Red); // Graphics.DrawPointAt(previusDataPoint._visualPosition, parentVisual, Colors.Red); // Graphics.DrawPointAt(dataPoint._visualPosition, parentVisual, Colors.Red); // Point midPoint = new Point(); // if (Graphics.IntersectionOfTwoStraightLines(new Point(nextDataPoint._visualPosition.X, plankYPos), // new Point(dataPoint._visualPosition.X, plankYPos), // nextDataPoint._visualPosition, dataPoint._visualPosition, ref midPoint)) // { // topFace.FrontFacePoints[1] = midPoint; // } // Graphics.DrawPointAt(midPoint, parentVisual, Colors.Green); //} topFace.CalculateBackFacePoints(); Path sides = new Path() { Tag = new ElementData() { Element = dataSeries } }; sides.SetValue(Canvas.ZIndexProperty, zIndex); PathGeometry pg = new PathGeometry(); PathFigure pf = new PathFigure() { IsClosed = true }; pg.Figures.Add(pf); // Graphics.DrawPointAt(dataPointFaces.Area3DTopFace.FrontPointLeft, parentVisual, Colors.Yellow); pf.StartPoint = topFace.FrontFacePoints[0]; PointCollection facePoints = topFace.GetFacePoints(); foreach (Point point in facePoints) { LineSegment ls = new LineSegment() { Point = point }; pf.Segments.Add(ls); } sides.Data = pg; sides.Fill = topBrush; sides.Opacity = dataPoint.Parent.Opacity; ApplyBorderProperties(sides, dataPoint.Parent); // sides.Fill = new SolidColorBrush(Color.FromArgb(255, (byte)rand.Next(155), (byte)rand.Next(200), (byte)rand.Next(126))); //sideBrush; parentVisual.Children.Add(sides); topFace.TopFace = sides; // sides.Fill = new SolidColorBrush(Colors.Red); //dataPointFaces.VisualComponents.Add(sides); //dataPointFaces.Parts.Add(sides); dataSeriesFaces.VisualComponents.Add(sides); //dataPointFaces.BorderElements.Add(sides); } if (dataPointFaces.Area3DRightFace != null) { Area3DDataPointFace rightFace = dataPointFaces.Area3DRightFace; rightFace.CalculateBackFacePoints(); Path sides = new Path() { Tag = new ElementData() { Element = dataSeries } }; sides.SetValue(Canvas.ZIndexProperty, zIndex); PathGeometry pg = new PathGeometry(); PathFigure pf = new PathFigure() { IsClosed = true }; pg.Figures.Add(pf); PointCollection facePoints = rightFace.GetFacePoints(); pf.StartPoint = rightFace.FrontFacePoints[0]; // Graphics.DrawPointAt(dataPointFaces.Area3DLeftFace.FrontPointLeft, parentVisual, Colors.Yellow); // Graphics.DrawPointAt(dataPointFaces.Area3DLeftFace.FrontPointRight, parentVisual, Colors.Yellow); // Graphics.DrawPointAt(dataPointFaces.Area3DLeftFace.BackPointRight, parentVisual, Colors.Yellow); // Graphics.DrawPointAt(dataPointFaces.Area3DLeftFace.BackPointLeft, parentVisual, Colors.Yellow); foreach (Point point in facePoints) { LineSegment ls = new LineSegment() { Point = point }; pf.Segments.Add(ls); } sides.Data = pg; sides.Fill = sideBrush; sides.Opacity = dataPoint.Parent.Opacity; ApplyBorderProperties(sides, dataPoint.Parent); // sides.Fill = new SolidColorBrush(Color.FromArgb(255, (byte)rand.Next(155), (byte)rand.Next(200), (byte)rand.Next(126))); parentVisual.Children.Add(sides); rightFace.RightFace = sides; ApplyBorderProperties(sides, dataSeries); //dataPointFaces.VisualComponents.Add(sides); //dataPointFaces.Parts.Add(sides); dataSeriesFaces.VisualComponents.Add(sides); //dataPointFaces.BorderElements.Add(sides); } return zIndex; }
/// <summary> /// Get Stacked3D side faces /// </summary> /// <param name="faces">Faces</param> /// <param name="areaParams">Area parameters</param> /// <returns>Canvas</returns> private static Canvas GetStacked3DSideFaces(ref Faces faces, PolygonalChartShapeParams areaParams) { Point centroid; Brush sideBrush = areaParams.Lighting ? Graphics.GetRightFaceBrush(areaParams.Background) : areaParams.Background; Brush topBrush = areaParams.Lighting ? Graphics.GetTopFaceBrush(areaParams.Background) : areaParams.Background; Int32 pointIndexLimit = areaParams.IsPositive ? areaParams.Points.Count - 1 : areaParams.Points.Count; Canvas polygonSet = new Canvas(); Rect size = GetBounds(areaParams.Points); polygonSet.Width = size.Width + areaParams.Depth3D; polygonSet.Height = size.Height + areaParams.Depth3D; polygonSet.SetValue(Canvas.TopProperty, size.Top - areaParams.Depth3D); polygonSet.SetValue(Canvas.LeftProperty, size.Left); for (Int32 i = 0; i < pointIndexLimit; i++) { Polygon sides = new Polygon() { Tag = new ElementData() { Element = areaParams.TagReference } }; PointCollection points = new PointCollection(); Int32 index1 = i % areaParams.Points.Count; Int32 index2 = (i + 1) % areaParams.Points.Count; points.Add(areaParams.Points[index1]); points.Add(areaParams.Points[index2]); points.Add(new Point(areaParams.Points[index2].X + areaParams.Depth3D, areaParams.Points[index2].Y - areaParams.Depth3D)); points.Add(new Point(areaParams.Points[index1].X + areaParams.Depth3D, areaParams.Points[index1].Y - areaParams.Depth3D)); sides.Points = points; centroid = GetCentroid(points); Int32 zindex = GetAreaZIndex(centroid.X, centroid.Y, areaParams.IsPositive); sides.SetValue(Canvas.ZIndexProperty, zindex); if (i == (areaParams.Points.Count - 2)) { sides.Fill = sideBrush; (sides.Tag as ElementData).VisualElementName = "Side"; } else { sides.Fill = topBrush; (sides.Tag as ElementData).VisualElementName = "Top"; } sides.Stroke = areaParams.BorderColor; sides.StrokeDashArray = areaParams.BorderStyle != null ? ExtendedGraphics.CloneCollection(areaParams.BorderStyle) : areaParams.BorderStyle; sides.StrokeThickness = areaParams.BorderThickness; sides.StrokeMiterLimit = 1; Rect sidesBounds = GetBounds(points); sides.Stretch = Stretch.Fill; sides.Width = sidesBounds.Width; sides.Height = sidesBounds.Height; sides.SetValue(Canvas.TopProperty, sidesBounds.Y - (size.Top - areaParams.Depth3D)); sides.SetValue(Canvas.LeftProperty, sidesBounds.X - size.X); faces.Parts.Add(sides); polygonSet.Children.Add(sides); } return polygonSet; }
/// <summary> /// Get visual of Area 3D /// </summary> /// <param name="faces">Faces</param> /// <param name="areaParams">AreaParams</param> /// <returns>Canvas</returns> internal static Canvas Get3DArea(DataSeries currentDataSeries, ref Faces faces, PolygonalChartShapeParams areaParams) { Canvas visual = new Canvas(); visual.Width = areaParams.Size.Width; visual.Height = areaParams.Size.Height; Point centroid; Brush sideBrush = areaParams.Lighting ? Graphics.GetRightFaceBrush(areaParams.Background) : areaParams.Background; Brush topBrush = areaParams.Lighting ? Graphics.GetTopFaceBrush(areaParams.Background) : areaParams.Background; Int32 pointIndexLimit = areaParams.IsPositive ? areaParams.Points.Count - 1 : areaParams.Points.Count; Canvas polygonSet = new Canvas(); Rect size = GetBounds(areaParams.Points); polygonSet.Width = size.Width + areaParams.Depth3D; polygonSet.Height = size.Height + areaParams.Depth3D; polygonSet.SetValue(Canvas.TopProperty, size.Top - areaParams.Depth3D); polygonSet.SetValue(Canvas.LeftProperty, size.Left); visual.Children.Add(polygonSet); for (Int32 i = 0; i < pointIndexLimit; i++) { Polygon sides = new Polygon() { Tag = new ElementData() { Element = areaParams.TagReference } }; PointCollection points = new PointCollection(); Int32 index1 = i % areaParams.Points.Count; Int32 index2 = (i + 1) % areaParams.Points.Count; points.Add(areaParams.Points[index1]); points.Add(areaParams.Points[index2]); points.Add(new Point(areaParams.Points[index2].X + areaParams.Depth3D, areaParams.Points[index2].Y - areaParams.Depth3D)); points.Add(new Point(areaParams.Points[index1].X + areaParams.Depth3D, areaParams.Points[index1].Y - areaParams.Depth3D)); sides.Points = points; centroid = GetCentroid(points); Int32 zindex = GetAreaZIndex(centroid.X, centroid.Y, areaParams.IsPositive); sides.SetValue(Canvas.ZIndexProperty, zindex); if (i == (areaParams.Points.Count - 2)) { sides.Fill = sideBrush; (sides.Tag as ElementData).VisualElementName = "Side"; } else { sides.Fill = topBrush; (sides.Tag as ElementData).VisualElementName = "Top"; } sides.Stroke = areaParams.BorderColor; sides.StrokeDashArray = areaParams.BorderStyle != null ? ExtendedGraphics.CloneCollection(areaParams.BorderStyle) : areaParams.BorderStyle; sides.StrokeThickness = areaParams.BorderThickness; sides.StrokeMiterLimit = 1; Rect sidesBounds = GetBounds(points); sides.Stretch = Stretch.Fill; sides.Width = sidesBounds.Width; sides.Height = sidesBounds.Height; sides.SetValue(Canvas.TopProperty, sidesBounds.Y - (size.Top - areaParams.Depth3D)); sides.SetValue(Canvas.LeftProperty, sidesBounds.X - size.X); faces.Parts.Add(sides); polygonSet.Children.Add(sides); } Polygon polygon = new Polygon() { Tag = new ElementData() { Element = areaParams.TagReference, VisualElementName = "AreaBase" } }; faces.Parts.Add(polygon); centroid = GetCentroid(areaParams.Points); polygon.SetValue(Canvas.ZIndexProperty, (Int32)centroid.Y + 1000); polygon.Fill = areaParams.Lighting ? Graphics.GetFrontFaceBrush(areaParams.Background) : areaParams.Background; polygon.Stroke = areaParams.BorderColor; polygon.StrokeDashArray = areaParams.BorderStyle != null ? ExtendedGraphics.CloneCollection(areaParams.BorderStyle) : areaParams.BorderStyle; polygon.StrokeThickness = areaParams.BorderThickness; polygon.StrokeMiterLimit = 1; polygon.Points = areaParams.Points; polygon.Stretch = Stretch.Fill; polygon.Width = size.Width; polygon.Height = size.Height; polygon.SetValue(Canvas.TopProperty, areaParams.Depth3D); polygon.SetValue(Canvas.LeftProperty, 0.0); // apply area animation if (areaParams.AnimationEnabled) { // apply animation to the entire canvas that was used to create the area areaParams.Storyboard = ApplyAreaAnimation(currentDataSeries, polygonSet, areaParams.Storyboard, areaParams.IsPositive, 0); } polygonSet.Children.Add(polygon); return visual; }
private static void GeneratePointCollections4Line(List<DataPoint> pointCollection, Double width, Double height, Boolean isShadow, PathFigure pathFigure, ref Canvas line2dLabelCanvas) { /* * PolyLineSegment segment = new PolyLineSegment(); segment.Points = GeneratePointCollection(segment, pointCollection, createFaces); pathFigure.Segments.Add(segment); */ for (int i = 1; i < pointCollection.Count; i++) { LineSegment segment = new LineSegment(); segment.Point = pointCollection[i]._visualPosition; Faces faces = new Faces(); faces.PreviousDataPoint = pointCollection[i - 1]; if(!isShadow) { if (i != pointCollection.Count - 1) faces.NextDataPoint = pointCollection[i + 1]; else faces.NextDataPoint = null; } //Add LineSegment faces.Parts.Add(segment); // Add PathFigure faces.Parts.Add(pathFigure); if (isShadow) pointCollection[i].ShadowFaces = faces; else pointCollection[i].Faces = faces; pathFigure.Segments.Add(segment); if(!isShadow) CreateMarkerAndLabel(pointCollection, i, width, height, line2dLabelCanvas); } }
//--------------del /// <summary> /// Create 2D bar for a DataPoint /// </summary> /// <param name="barParams">Bar parameters</param> /// <returns>Faces for bar</returns> internal static Faces Get2DBar(RectangularChartShapeParams barParams) { Faces faces = new Faces(); Grid barVisual = new Grid(); barVisual.Width = barParams.Size.Width; barVisual.Height = barParams.Size.Height; Brush background = (barParams.Lighting ? Graphics.GetLightingEnabledBrush(barParams.BackgroundBrush, "Linear", null) : barParams.BackgroundBrush); Rectangle barBase = ExtendedGraphics.Get2DRectangle(barParams.TagReference, barParams.Size.Width, barParams.Size.Height, barParams.BorderThickness, barParams.BorderStyle, barParams.BorderBrush, background, barParams.XRadius, barParams.YRadius); (barBase.Tag as ElementData).VisualElementName = "ColumnBase"; //faces.Parts.Add(barBase.Children[0] as FrameworkElement); //faces.BorderElements.Add(barBase.Children[0] as Path); faces.Parts.Add(barBase); faces.BorderElements.Add(barBase); barVisual.Children.Add(barBase); if (barParams.Size.Height > 7 && barParams.Size.Width > 14 && barParams.Bevel) { Canvas bevelCanvas = ExtendedGraphics.Get2DRectangleBevel(barParams.TagReference, barParams.Size.Width - barParams.BorderThickness - barParams.BorderThickness, barParams.Size.Height - barParams.BorderThickness - barParams.BorderThickness, 6, 6, Graphics.GetBevelTopBrush(barParams.BackgroundBrush), Graphics.GetBevelSideBrush((barParams.Lighting ? -70 : 0), barParams.BackgroundBrush), Graphics.GetBevelSideBrush((barParams.Lighting ? -110 : 180), barParams.BackgroundBrush), null); foreach (FrameworkElement fe in bevelCanvas.Children) faces.Parts.Add(fe); bevelCanvas.SetValue(Canvas.LeftProperty, barParams.BorderThickness); bevelCanvas.SetValue(Canvas.TopProperty, barParams.BorderThickness); barVisual.Children.Add(bevelCanvas); } else { faces.Parts.Add(null); faces.Parts.Add(null); faces.Parts.Add(null); faces.Parts.Add(null); } if (barParams.Lighting && barParams.Bevel) { Canvas gradienceCanvas = ExtendedGraphics.Get2DRectangleGradiance(barParams.Size.Width, barParams.Size.Height, Graphics.GetLeftGradianceBrush(63), Graphics.GetLeftGradianceBrush(63), Orientation.Horizontal); foreach (FrameworkElement fe in gradienceCanvas.Children) faces.Parts.Add(fe); barVisual.Children.Add(gradienceCanvas); } else { faces.Parts.Add(null); faces.Parts.Add(null); } if (barParams.Shadow) { Double shadowVerticalOffsetGap = 1; Double shadowVerticalOffset = barParams.ShadowOffset - shadowVerticalOffsetGap; Double shadowHeight = barParams.Size.Height; CornerRadius xRadius = barParams.XRadius; CornerRadius yRadius = barParams.YRadius; if (barParams.IsStacked) { if (barParams.IsPositive) { if (barParams.IsTopOfStack) { shadowHeight = barParams.Size.Height - barParams.ShadowOffset; shadowVerticalOffset = barParams.ShadowOffset - shadowVerticalOffsetGap - shadowVerticalOffsetGap; xRadius = new CornerRadius(xRadius.TopLeft, xRadius.TopRight, xRadius.BottomRight, xRadius.BottomLeft); yRadius = new CornerRadius(yRadius.TopLeft, yRadius.TopRight, 0, 0); } else { shadowHeight = barParams.Size.Height + 6; shadowVerticalOffset = -2; xRadius = new CornerRadius(xRadius.TopLeft, xRadius.TopRight, xRadius.BottomRight, xRadius.BottomLeft); yRadius = new CornerRadius(0, 0, 0, 0); } } else { if (barParams.IsTopOfStack) { shadowHeight = barParams.Size.Height - barParams.ShadowOffset; xRadius = new CornerRadius(xRadius.TopLeft, xRadius.TopRight, xRadius.BottomRight, xRadius.BottomLeft); yRadius = new CornerRadius(yRadius.TopLeft, yRadius.TopRight, 0, 0); } else { shadowHeight = barParams.Size.Height + barParams.ShadowOffset + 2; shadowVerticalOffset = -2; xRadius = new CornerRadius(xRadius.TopLeft, xRadius.TopRight, xRadius.BottomRight, xRadius.BottomLeft); yRadius = new CornerRadius(0, 0, 0, 0); } } } Grid shadowGrid = ExtendedGraphics.Get2DRectangleShadow(barParams.TagReference, barParams.Size.Width, shadowHeight, xRadius, yRadius, barParams.IsStacked ? 3 : 5); TranslateTransform tt = new TranslateTransform() { X = barParams.ShadowOffset, Y = shadowVerticalOffset }; shadowGrid.Opacity = 0.7; shadowGrid.SetValue(Canvas.ZIndexProperty, -1); shadowGrid.RenderTransform = tt; barVisual.Children.Add(shadowGrid); } faces.VisualComponents.Add(barVisual); faces.Visual = barVisual; return faces; }
/// <summary> /// Get path geometry for Polar points /// </summary> /// <param name="pointCollection"></param> /// <returns></returns> private static Geometry GetPathGeometry(List<DataPoint> pointCollection) { PathGeometry geometry = new PathGeometry(); PathFigure pathFigure = new PathFigure(); if (pointCollection.Count > 0) { pathFigure.StartPoint = pointCollection[0]._visualPosition; for (int i = 1; i < pointCollection.Count; i++) { LineSegment segment = new LineSegment(); segment.Point = pointCollection[i]._visualPosition; Faces faces = new Faces(); pathFigure.Segments.Add(segment); } } geometry.Figures.Add(pathFigure); return geometry; }
/// <summary> /// Create3DPie /// </summary> /// <param name="width">Visual width</param> /// <param name="height">Visual height</param> /// <param name="series">DataSeries</param> /// <param name="enabledDataPoints"> Enabled InternalDataPoints in the DataSeries</param> /// <param name="dataPoint">DataPoint reference</param> /// <param name="visual">visual canvas reference</param> /// <param name="faces">Visual faces</param> /// <param name="pieParams">Pie parameters</param> /// <param name="offsetX">X offset</param> /// <param name="zindex">Z index of the pie</param> /// <param name="isAnimationEnabled">Whether animation is enabled</param> private static void Create3DPie(DataSeries currentDataSeries, Double widthOfPlotArea, Double height, DataSeries series, List<DataPoint> enabledDataPoints, DataPoint dataPoint, ref Canvas visual, ref Faces faces, ref SectorChartShapeParams pieParams, ref Double offsetX, ref Int32 zindex, Boolean isAnimationEnabled) { #region 3D Pie PieDoughnut3DPoints unExplodedPoints = new PieDoughnut3DPoints(); PieDoughnut3DPoints explodedPoints = new PieDoughnut3DPoints(); pieParams.TagReference = dataPoint; List<Shape> pieFaces = GetPie3D(currentDataSeries, ref faces, pieParams, ref zindex, ref unExplodedPoints, ref explodedPoints, ref dataPoint.LabelLine, enabledDataPoints); foreach (Shape path in pieFaces) { if (path != null) { visual.Children.Add(path); faces.VisualComponents.Add(path); faces.BorderElements.Add(path); path.RenderTransform = new TranslateTransform(); // apply animation to the 3D sections if (isAnimationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, dataPoint, series.Storyboard, path, 1.0 / (series.InternalDataPoints.Count) * (series.InternalDataPoints.IndexOf(dataPoint)), dataPoint.InternalOpacity, 0.5); path.Opacity = 0; } } } if (dataPoint.LabelLine != null && pieParams.LabelLineEnabled) { dataPoint.LabelLine.RenderTransform = new TranslateTransform(); if (dataPoint.InternalYValue == 0) { Line zeroLine = new Line(); zeroLine.X1 = pieParams.Center.X; zeroLine.Y1 = pieParams.Center.Y; zeroLine.X2 = unExplodedPoints.LabelLineStartPoint.X; zeroLine.Y2 = unExplodedPoints.LabelLineStartPoint.Y; zeroLine.Stroke = pieParams.LabelLineColor; zeroLine.StrokeThickness = 0.25; zeroLine.IsHitTestVisible = false; visual.Children.Add(zeroLine); if (isAnimationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, dataPoint, series.Storyboard, zeroLine, 2, zeroLine.Opacity, 0.5); zeroLine.Opacity = 0; } } visual.Children.Add(dataPoint.LabelLine); faces.VisualComponents.Add(dataPoint.LabelLine); } faces.Visual = visual; UpdateExplodedPosition(pieParams, dataPoint, offsetX, unExplodedPoints, explodedPoints, widthOfPlotArea); pieParams.ExplodedPoints = explodedPoints; pieParams.UnExplodedPoints = unExplodedPoints; if ((Boolean)(dataPoint.Chart as Chart).AnimatedUpdate) { dataPoint.ExplodeAnimation = new Storyboard(); dataPoint.ExplodeAnimation = CreateExplodingOut3DAnimation(currentDataSeries, dataPoint, widthOfPlotArea, dataPoint.ExplodeAnimation, pieFaces, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, unExplodedPoints, explodedPoints, pieParams.OffsetX, pieParams.OffsetY); dataPoint.UnExplodeAnimation = new Storyboard(); dataPoint.UnExplodeAnimation = CreateExplodingIn3DAnimation(currentDataSeries, dataPoint, widthOfPlotArea, dataPoint.UnExplodeAnimation, pieFaces, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, unExplodedPoints, explodedPoints, pieParams.OffsetX, pieParams.OffsetY); } else { if (!(dataPoint.Chart as Chart).InternalAnimationEnabled) { if ((Boolean)dataPoint.Exploded) { foreach (Shape path in pieFaces) { if (path == null) continue; (path.RenderTransform as TranslateTransform).X = pieParams.OffsetX; (path.RenderTransform as TranslateTransform).Y = pieParams.OffsetY; } if (dataPoint.LabelVisual != null) { if (dataPoint.LabelStyle == LabelStyles.Inside) { TranslateTransform translateTransform = new TranslateTransform(); (dataPoint.LabelVisual as Canvas).RenderTransform = translateTransform; translateTransform.X = pieParams.OffsetX; translateTransform.Y = pieParams.OffsetY; } else { (dataPoint.LabelVisual as Canvas).SetValue(Canvas.LeftProperty, explodedPoints.LabelPosition.X); } } if (dataPoint.LabelLine != null) { (dataPoint.LabelLine.RenderTransform as TranslateTransform).X = pieParams.OffsetX; (dataPoint.LabelLine.RenderTransform as TranslateTransform).Y = pieParams.OffsetY; PathFigure figure = (dataPoint.LabelLine.Data as PathGeometry).Figures[0]; PathSegmentCollection segments = figure.Segments; (segments[0] as LineSegment).Point = explodedPoints.LabelLineMidPoint; (segments[1] as LineSegment).Point = explodedPoints.LabelLineEndPoint; } dataPoint._interactiveExplodeState = true; } } } #endregion }
/// <summary> /// Draws the Vertical 3D Plank /// </summary> /// <param name="plankDepth">PlankDepth</param> /// <param name="plankThickness">PlankThickness</param> private void DrawVerticalPlank(Double plankDepth, Double plankThickness, AxisRepresentations axisChanged, Boolean isPartialUpdate) { if (isPartialUpdate && axisChanged == AxisRepresentations.AxisX) { ColumnChart.Update3DPlank(plankThickness, ScrollableLength - plankDepth, plankDepth, _verticalPlank); return; } if (_verticalPlank != null && _verticalPlank.Visual != null && _verticalPlank.Visual.Parent != null) { Panel parent = _verticalPlank.Visual.Parent as Canvas; parent.Children.Remove(_verticalPlank.Visual); } RectangularChartShapeParams columnParams = new RectangularChartShapeParams(); Brush frontBrush, topBrush, rightBrush; List<Color> colors = new List<Color>(); colors.Add(Color.FromArgb(255, 134, 134, 134)); // #FF868686 colors.Add(Color.FromArgb(255, 210, 210, 210)); // #FFD2D2D2 colors.Add(Color.FromArgb(255, 255, 255, 255)); // #FFFFFFFF colors.Add(Color.FromArgb(255, 223, 223, 223)); // #FFDFDFDF frontBrush = Graphics.CreateLinearGradientBrush(0, new Point(1.1, 0.49), new Point(-0.15, 0.49), colors, new List<double>() { 0, 0.844, 1, 0.442 }); colors = new List<Color>(); colors.Add(Color.FromArgb(255, 232, 232, 232)); // #FFE8E8E8 colors.Add(Color.FromArgb(255, 142, 135, 135)); // #FF8E8787 rightBrush = Graphics.CreateLinearGradientBrush(0, new Point(0, 0.5), new Point(1, 0.5), colors, new List<double>() { 1, 0 }); colors = new List<Color>(); colors.Add(Color.FromArgb(255, 232, 232, 232)); // #FFE8E8E8 colors.Add(Color.FromArgb(255, 142, 135, 135)); // #FF8E8787 topBrush = Graphics.CreateLinearGradientBrush(0, new Point(0.084, 0.441), new Point(1.916, 0.443), colors, new List<double>() { 0, 1 }); _verticalPlank = ColumnChart.Get3DPlank(plankThickness, ScrollableLength - plankDepth, plankDepth, frontBrush, topBrush, rightBrush); Panel plank = _verticalPlank.Visual as Panel; plank.SetValue(Canvas.TopProperty, plankDepth); plank.SetValue(Canvas.ZIndexProperty, -1); PlottingCanvas.Children.Add(plank); }
/// <summary> /// Create3DPie /// </summary> /// <param name="width">Visual width</param> /// <param name="height">Visual height</param> /// <param name="series">DataSeries</param> /// <param name="enabledDataPoints"> Enabled InternalDataPoints in the DataSeries</param> /// <param name="dataPoint">DataPoint reference</param> /// <param name="visual">visual canvas reference</param> /// <param name="faces">Visual faces</param> /// <param name="pieParams">Pie parameters</param> /// <param name="offsetX">X offset</param> /// <param name="offsetX">Y offset</param> /// <param name="zindex">Z index of the pie</param> /// <param name="isAnimationEnabled">Whether animation is enabled</param> /// <param name="labelStyleCounter">labelStyle count</param> private static void Create2DPie(DataSeries currentDataSeries, Double widthOfPlotArea, Double height, DataSeries series, List<DataPoint> enabledDataPoints, DataPoint dataPoint, ref Canvas visual, ref Faces faces, ref SectorChartShapeParams pieParams, ref Double offsetX, ref Double offsetY, ref Int32 zindex, Boolean isAnimationEnabled, Int32 labelStateCount) { #region 2D Pie PieDoughnut2DPoints unExplodedPoints = new PieDoughnut2DPoints(); PieDoughnut2DPoints explodedPoints = new PieDoughnut2DPoints(); pieParams.TagReference = dataPoint; if (labelStateCount == enabledDataPoints.Count) pieParams.OuterRadius -= pieParams.OuterRadius * pieParams.ExplodeRatio; Canvas pieVisual = GetPie2D(currentDataSeries, ref faces, pieParams, ref unExplodedPoints, ref explodedPoints, ref dataPoint.LabelLine, enabledDataPoints); UpdateExplodedPosition(pieParams, dataPoint, offsetX, unExplodedPoints, explodedPoints, widthOfPlotArea); pieParams.ExplodedPoints = explodedPoints; pieParams.UnExplodedPoints = unExplodedPoints; TranslateTransform translateTransform = new TranslateTransform(); pieVisual.RenderTransform = translateTransform; if ((Boolean)(currentDataSeries.Chart as Chart).AnimatedUpdate) { dataPoint.ExplodeAnimation = new Storyboard(); dataPoint.ExplodeAnimation = CreateExplodingOut2DAnimation(currentDataSeries, dataPoint, widthOfPlotArea, dataPoint.ExplodeAnimation, pieVisual, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, translateTransform, unExplodedPoints, explodedPoints, offsetX, offsetY); dataPoint.UnExplodeAnimation = new Storyboard(); dataPoint.UnExplodeAnimation = CreateExplodingIn2DAnimation(currentDataSeries, dataPoint, widthOfPlotArea, dataPoint.UnExplodeAnimation, pieVisual, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, translateTransform, unExplodedPoints, explodedPoints, offsetX, offsetY); } else { if (!(currentDataSeries.Chart as Chart).InternalAnimationEnabled) { if ((Boolean)dataPoint.Exploded) { translateTransform.X = offsetX; translateTransform.Y = offsetY; if (dataPoint.LabelVisual != null) { if (dataPoint.LabelStyle == LabelStyles.Inside) { translateTransform = new TranslateTransform(); (dataPoint.LabelVisual as Canvas).RenderTransform = translateTransform; translateTransform.X = offsetX; translateTransform.Y = offsetY; } else { (dataPoint.LabelVisual as Canvas).SetValue(Canvas.LeftProperty, explodedPoints.LabelPosition.X); } } if (dataPoint.LabelLine != null) { PathFigure figure = (dataPoint.LabelLine.Data as PathGeometry).Figures[0]; PathSegmentCollection segments = figure.Segments; (segments[0] as LineSegment).Point = explodedPoints.LabelLineMidPoint; (segments[1] as LineSegment).Point = explodedPoints.LabelLineEndPoint; } dataPoint._interactiveExplodeState = true; } } } pieVisual.SetValue(Canvas.TopProperty, height / 2 - pieVisual.Height / 2); pieVisual.SetValue(Canvas.LeftProperty, widthOfPlotArea / 2 - pieVisual.Width / 2); visual.Children.Add(pieVisual); faces.VisualComponents.Add(pieVisual); faces.Visual = pieVisual; #endregion }
// Canvas bubleChartCanvas, DataPoint dataPoint, Double minimumZVal, Double maximumZVal, Double plotWidth, Double plotHeight private static void CreateOrUpdateAPointDataPoint(Canvas pointChartCanvas, DataPoint dataPoint, Double plotAreaWidth, Double plotAreaHeight) { Faces dpFaces = dataPoint.Faces; // Remove preexisting dataPoint visual and label visual if (dpFaces != null && dpFaces.Visual != null && pointChartCanvas == dpFaces.Visual.Parent) { pointChartCanvas.Children.Remove(dataPoint.Faces.Visual); //dpFaces = null; } dataPoint.Faces = null; dpFaces = new Faces(); if (Double.IsNaN(dataPoint.InternalYValue) || (dataPoint.Enabled == false)) return; Chart chart = dataPoint.Chart as Chart; PlotGroup plotGroup = dataPoint.Parent.PlotGroup; Double xPosition = Graphics.ValueToPixelPosition(0, plotAreaWidth, (Double)plotGroup.AxisX.InternalAxisMinimum, (Double)plotGroup.AxisX.InternalAxisMaximum, dataPoint.InternalXValue); Double yPosition = Graphics.ValueToPixelPosition(plotAreaHeight, 0, (Double)plotGroup.AxisY.InternalAxisMinimum, (Double)plotGroup.AxisY.InternalAxisMaximum, dataPoint.InternalYValue); Brush markerColor = dataPoint.Color; //markerColor = (chart.View3D ? Graphics.GetLightingEnabledBrush3D(markerColor) : // ((Boolean)dataPoint.LightingEnabled ? Graphics.GetLightingEnabledBrush(markerColor, "Linear", null) : markerColor)); markerColor = (chart.View3D ? Graphics.Get3DBrushLighting(dataPoint.Color, (Boolean)dataPoint.LightingEnabled) : ((Boolean)dataPoint.LightingEnabled ? Graphics.GetLightingEnabledBrush(markerColor, "Linear", null) : markerColor)); Size markerSize = new Size((Double)dataPoint.MarkerSize, (Double)dataPoint.MarkerSize); Boolean markerBevel = false; String labelText = (Boolean)dataPoint.LabelEnabled ? dataPoint.TextParser(dataPoint.LabelText) : ""; Marker marker = new Marker((MarkerTypes)dataPoint.MarkerType, (Double)dataPoint.MarkerScale, markerSize, markerBevel, markerColor, labelText); marker.Tag = new ElementData() { Element = dataPoint }; marker.ShadowEnabled = (Boolean)dataPoint.ShadowEnabled; if (!VisifireControl.IsMediaEffectsEnabled) marker.PixelLavelShadow = false; else marker.PixelLavelShadow = true; marker.MarkerSize = new Size((Double)dataPoint.MarkerSize, (Double)dataPoint.MarkerSize); if (marker.MarkerType != MarkerTypes.Cross) { if (dataPoint.BorderColor != null) marker.BorderColor = dataPoint.BorderColor; } else marker.BorderColor = markerColor; marker.BorderThickness = ((Thickness)dataPoint.MarkerBorderThickness).Left; if (!String.IsNullOrEmpty(labelText)) { marker.FontColor = Chart.CalculateDataPointLabelFontColor(chart, dataPoint, dataPoint.LabelFontColor, LabelStyles.OutSide); marker.FontSize = (Double)dataPoint.LabelFontSize; marker.FontWeight = (FontWeight)dataPoint.LabelFontWeight; marker.FontFamily = dataPoint.LabelFontFamily; marker.FontStyle = (FontStyle)dataPoint.LabelFontStyle; marker.TextBackground = dataPoint.LabelBackground; marker.TextAlignmentX = AlignmentX.Center; marker.TextAlignmentY = AlignmentY.Center; if (!Double.IsNaN(dataPoint.LabelAngle) && dataPoint.LabelAngle != 0) { marker.LabelAngle = dataPoint.LabelAngle; marker.TextOrientation = Orientation.Vertical; marker.TextAlignmentX = AlignmentX.Center; marker.TextAlignmentY = AlignmentY.Center; marker.LabelStyle = (LabelStyles)dataPoint.LabelStyle; } marker.CreateVisual(); if (Double.IsNaN(dataPoint.LabelAngle) || dataPoint.LabelAngle == 0) { if ((yPosition - marker.TextBlockSize.Height / 2) < 0) marker.TextAlignmentY = AlignmentY.Bottom; else if ((yPosition + marker.TextBlockSize.Height / 2) > plotAreaHeight) marker.TextAlignmentY = AlignmentY.Top; if ((xPosition - marker.TextBlockSize.Width / 2) < 0) marker.TextAlignmentX = AlignmentX.Right; else if ((xPosition + marker.TextBlockSize.Width / 2) > plotAreaWidth) marker.TextAlignmentX = AlignmentX.Left; } } //marker.LabelEnabled =(Boolean) dataPoint.LabelEnabled; //marker.TextBackground = dataPoint.LabelBackground; //marker.FontColor = Chart.CalculateDataPointLabelFontColor(chart, dataPoint, dataPoint.LabelFontColor, LabelStyles.OutSide); //marker.FontSize = (Double)dataPoint.LabelFontSize; //marker.FontWeight = (FontWeight)dataPoint.LabelFontWeight; //marker.FontFamily = dataPoint.LabelFontFamily; //marker.FontStyle = (FontStyle)dataPoint.LabelFontStyle; //marker.TextAlignmentX = AlignmentX.Center; //marker.TextAlignmentY = AlignmentY.Center; marker.CreateVisual(); marker.Visual.Opacity = (Double)dataPoint.Opacity * (Double)dataPoint.Parent.Opacity; marker.AddToParent(pointChartCanvas, xPosition, yPosition, new Point(0.5, 0.5)); dataPoint._visualPosition = new Point(xPosition, yPosition); dpFaces.VisualComponents.Add(marker.Visual); dpFaces.Visual = marker.Visual; dpFaces.BorderElements.Add(marker.MarkerShape); dataPoint.Marker = marker; dataPoint.Faces = dpFaces; dataPoint.Faces.Visual.Opacity = (Double)dataPoint.Opacity * (Double)dataPoint.Parent.Opacity; dataPoint.AttachEvent2DataPointVisualFaces(dataPoint); dataPoint.AttachEvent2DataPointVisualFaces(dataPoint.Parent); dataPoint._parsedToolTipText = dataPoint.TextParser(dataPoint.ToolTipText); if(!chart.IndicatorEnabled) dataPoint.AttachToolTip(chart, dataPoint, dataPoint.Faces.VisualComponents); dataPoint.AttachHref(chart, dataPoint.Faces.VisualComponents, dataPoint.Href, (HrefTargets)dataPoint.HrefTarget); dataPoint.SetCursor2DataPointVisualFaces(); if (dataPoint.Parent.SelectionEnabled && dataPoint.Selected) dataPoint.Select(true); }
/// <summary> /// Get visual object for bubble chart /// </summary> /// <param name="width">Width of the chart</param> /// <param name="height">Height of the chart</param> /// <param name="plotDetails">plotDetails</param> /// <param name="seriesList">List of DataSeries</param> /// <param name="chart">Chart</param> /// <param name="plankDepth">Plank depth</param> /// <param name="animationEnabled">Whether animation is enabled</param> /// <returns>Bubble chart canvas</returns> internal static Canvas GetVisualObjectForBubbleChart(Panel preExistingPanel, Double width, Double height, PlotDetails plotDetails, List<DataSeries> seriesList, Chart chart, Double plankDepth, bool animationEnabled) { if (Double.IsNaN(width) || Double.IsNaN(height) || width <= 0 || height <= 0) return null; // Visual for all bubble charts, Nothing but presisting visual for buble chart Canvas visual; // Holds all bubbles of all series Canvas bubbleChartCanvas; RenderHelper.RepareCanvas4Drawing(preExistingPanel as Canvas, out visual, out bubbleChartCanvas, width, height); Double depth3d = plankDepth / (plotDetails.Layer3DCount == 0 ? 1 : plotDetails.Layer3DCount) * (chart.View3D ? 1 : 0); Double visualOffset = depth3d * (plotDetails.SeriesDrawingIndex[seriesList[0]] + 1 - (plotDetails.Layer3DCount == 0 ? 0 : 1)); visual.SetValue(Canvas.TopProperty, visualOffset); visual.SetValue(Canvas.LeftProperty, -visualOffset); Double minimumZVal, maximumZVal; CalculateMaxAndMinZValueFromAllSeries(ref seriesList, out minimumZVal, out maximumZVal); foreach (DataSeries series in seriesList) { Faces dsFaces = new Faces() { Visual = bubbleChartCanvas }; series.Faces = dsFaces; if (series.Enabled == false) continue; //out Double minimumZVal, out Double maximumZVal PlotGroup plotGroup = series.PlotGroup; List<DataPoint> dataPointsInViewPort = RenderHelper.GetDataPointsUnderViewPort(series, false); foreach (DataPoint dataPoint in dataPointsInViewPort) { CreateOrUpdateAPointDataPoint(bubbleChartCanvas, dataPoint, minimumZVal, maximumZVal, width, height); // Apply animation if (animationEnabled && dataPoint.Marker != null) { if (dataPoint.Parent.Storyboard == null) dataPoint.Parent.Storyboard = new Storyboard(); // Apply animation to the bubbles dataPoint.Parent.Storyboard = ApplyBubbleChartAnimation(dataPoint.Parent, dataPoint.Marker.Visual, dataPoint.Parent.Storyboard, width, height); } } } RectangleGeometry clipRectangle = new RectangleGeometry(); clipRectangle.Rect = new Rect(0, -chart.ChartArea.PLANK_DEPTH, width + chart.ChartArea.PLANK_OFFSET, height + chart.ChartArea.PLANK_DEPTH); visual.Clip = clipRectangle; return visual; }
/// <summary> /// Returns 3D Doughnut shapes /// </summary> /// <param name="faces">Doughnut faces</param> /// <param name="doughnutParams">Doughnut parameters</param> /// <param name="unExplodedPoints">UnExploded dataPoints</param> /// <param name="explodedPoints">Exploded dataPoints</param> /// <param name="labelLinePath">Label line path</param> /// <param name="enabledDataPoints">List of enabled dataPoints</param> /// <returns>List of Shape</returns> private static List<Shape> GetDoughnut3D(DataSeries currentDataSeries, ref Faces faces, SectorChartShapeParams doughnutParams, ref PieDoughnut3DPoints unExplodedPoints, ref PieDoughnut3DPoints explodedPoints, ref Path labelLinePath, List<DataPoint> enabledDataPoints) { List<Shape> pieFaces = new List<Shape>(); Shape topFace = null, bottomFace = null, rightFace = null, leftFace = null; // calculate 3d offsets Double yOffset = -doughnutParams.Depth / 2 * doughnutParams.ZAxisScaling; Point center = new Point(); center.X += doughnutParams.Width / 2; center.Y += doughnutParams.Height / 2; // calculate all points Point3D topFaceCenter = new Point3D(); topFaceCenter.X = center.X; topFaceCenter.Y = center.Y + yOffset; topFaceCenter.Z = doughnutParams.OffsetY * Math.Sin(doughnutParams.StartAngle) * Math.Cos(doughnutParams.TiltAngle) + doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D topOuterArcStart = new Point3D(); topOuterArcStart.X = topFaceCenter.X + doughnutParams.OuterRadius * Math.Cos(doughnutParams.StartAngle); topOuterArcStart.Y = topFaceCenter.Y + doughnutParams.OuterRadius * Math.Sin(doughnutParams.StartAngle) * doughnutParams.YAxisScaling; topOuterArcStart.Z = (topFaceCenter.Y + doughnutParams.OuterRadius) * Math.Sin(doughnutParams.StartAngle) * Math.Cos(doughnutParams.TiltAngle) + doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D topOuterArcStop = new Point3D(); topOuterArcStop.X = topFaceCenter.X + doughnutParams.OuterRadius * Math.Cos(doughnutParams.StopAngle); topOuterArcStop.Y = topFaceCenter.Y + doughnutParams.OuterRadius * Math.Sin(doughnutParams.StopAngle) * doughnutParams.YAxisScaling; topOuterArcStop.Z = (topFaceCenter.Y + doughnutParams.OuterRadius) * Math.Sin(doughnutParams.StopAngle) * Math.Cos(doughnutParams.TiltAngle) + doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D topInnerArcStart = new Point3D(); topInnerArcStart.X = topFaceCenter.X + doughnutParams.InnerRadius * Math.Cos(doughnutParams.StartAngle); topInnerArcStart.Y = topFaceCenter.Y + doughnutParams.InnerRadius * Math.Sin(doughnutParams.StartAngle) * doughnutParams.YAxisScaling; topInnerArcStart.Z = (topFaceCenter.Y + doughnutParams.InnerRadius) * Math.Sin(doughnutParams.StartAngle) * Math.Cos(doughnutParams.TiltAngle) + doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D topInnerArcStop = new Point3D(); topInnerArcStop.X = topFaceCenter.X + doughnutParams.InnerRadius * Math.Cos(doughnutParams.StopAngle); topInnerArcStop.Y = topFaceCenter.Y + doughnutParams.InnerRadius * Math.Sin(doughnutParams.StopAngle) * doughnutParams.YAxisScaling; topInnerArcStop.Z = (topFaceCenter.Y + doughnutParams.InnerRadius) * Math.Sin(doughnutParams.StopAngle) * Math.Cos(doughnutParams.TiltAngle) + doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D bottomFaceCenter = new Point3D(); bottomFaceCenter.X = center.X; bottomFaceCenter.Y = center.Y - yOffset; bottomFaceCenter.Z = doughnutParams.OffsetY * Math.Sin(doughnutParams.StartAngle) * Math.Cos(doughnutParams.TiltAngle) - doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D bottomOuterArcStart = new Point3D(); bottomOuterArcStart.X = bottomFaceCenter.X + doughnutParams.OuterRadius * Math.Cos(doughnutParams.StartAngle); bottomOuterArcStart.Y = bottomFaceCenter.Y + doughnutParams.OuterRadius * Math.Sin(doughnutParams.StartAngle) * doughnutParams.YAxisScaling; bottomOuterArcStart.Z = (bottomFaceCenter.Y + doughnutParams.OuterRadius) * Math.Sin(doughnutParams.StartAngle) * Math.Cos(doughnutParams.TiltAngle) - doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D bottomOuterArcStop = new Point3D(); bottomOuterArcStop.X = bottomFaceCenter.X + doughnutParams.OuterRadius * Math.Cos(doughnutParams.StopAngle); bottomOuterArcStop.Y = bottomFaceCenter.Y + doughnutParams.OuterRadius * Math.Sin(doughnutParams.StopAngle) * doughnutParams.YAxisScaling; bottomOuterArcStop.Z = (bottomFaceCenter.Y + doughnutParams.OuterRadius) * Math.Sin(doughnutParams.StopAngle) * Math.Cos(doughnutParams.TiltAngle) - doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D bottomInnerArcStart = new Point3D(); bottomInnerArcStart.X = bottomFaceCenter.X + doughnutParams.InnerRadius * Math.Cos(doughnutParams.StartAngle); bottomInnerArcStart.Y = bottomFaceCenter.Y + doughnutParams.InnerRadius * Math.Sin(doughnutParams.StartAngle) * doughnutParams.YAxisScaling; bottomInnerArcStart.Z = (bottomFaceCenter.Y + doughnutParams.InnerRadius) * Math.Sin(doughnutParams.StartAngle) * Math.Cos(doughnutParams.TiltAngle) - doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D bottomInnerArcStop = new Point3D(); bottomInnerArcStop.X = bottomFaceCenter.X + doughnutParams.InnerRadius * Math.Cos(doughnutParams.StopAngle); bottomInnerArcStop.Y = bottomFaceCenter.Y + doughnutParams.InnerRadius * Math.Sin(doughnutParams.StopAngle) * doughnutParams.YAxisScaling; bottomInnerArcStop.Z = (bottomFaceCenter.Y + doughnutParams.InnerRadius) * Math.Sin(doughnutParams.StopAngle) * Math.Cos(doughnutParams.TiltAngle) - doughnutParams.Depth * Math.Cos(Math.PI / 2 - doughnutParams.TiltAngle); Point3D centroid = GetCentroid(topInnerArcStart, topInnerArcStop, topOuterArcStart, topOuterArcStop, bottomInnerArcStart, bottomInnerArcStop, bottomOuterArcStart, bottomOuterArcStop); UpdatePositionLabelInsidePie(doughnutParams, yOffset); if (doughnutParams.StartAngle == doughnutParams.StopAngle && doughnutParams.IsLargerArc || enabledDataPoints.Count == 1) { // draw singleton pie here topFace = new Ellipse() { Tag = new ElementData() { Element = doughnutParams.TagReference } }; // topFace.Fill = doughnutParams.Lighting ? Graphics.GetLightingEnabledBrush(doughnutParams.Background, "Radial", new Double[] { 0.99, 0.745 }) : doughnutParams.Background; topFace.Fill = doughnutParams.Lighting ? Graphics.GetLightingEnabledBrush(doughnutParams.Background, "Linear", new Double[] { 0.99, 0.854 }) : doughnutParams.Background; topFace.Width = 2 * doughnutParams.OuterRadius; topFace.Height = 2 * doughnutParams.OuterRadius * doughnutParams.YAxisScaling; topFace.SetValue(Canvas.LeftProperty, (Double)(doughnutParams.Center.X - topFace.Width / 2)); topFace.SetValue(Canvas.TopProperty, (Double)(doughnutParams.Center.Y - topFace.Height / 2 + yOffset)); GeometryGroup gg = new GeometryGroup(); gg.Children.Add(new EllipseGeometry() { Center = new Point(topFace.Width / 2, topFace.Height / 2), RadiusX = topFace.Width, RadiusY = topFace.Height }); gg.Children.Add(new EllipseGeometry() { Center = new Point(topFace.Width / 2, topFace.Height / 2), RadiusX = doughnutParams.InnerRadius, RadiusY = topFace.Height - 2 * (doughnutParams.OuterRadius - doughnutParams.InnerRadius) }); topFace.Clip = gg; pieFaces.Add(topFace); faces.Parts.Add(topFace); bottomFace = new Ellipse() { Tag = new ElementData() { Element = doughnutParams.TagReference } }; bottomFace.Fill = doughnutParams.Lighting ? Graphics.GetLightingEnabledBrush(doughnutParams.Background, "Radial", new Double[] { 0.99, 0.745 }) : doughnutParams.Background; // topFace.Stroke = pieParams.Lighting ? Graphics.GetLightingEnabledBrush(pieParams.Background, "Radial", new Double[] { 0.99, 0.745 }) : pieParams.Background; bottomFace.Width = 2 * doughnutParams.OuterRadius; bottomFace.Height = 2 * doughnutParams.OuterRadius * doughnutParams.YAxisScaling; bottomFace.SetValue(Canvas.LeftProperty, (Double)(doughnutParams.Center.X - topFace.Width / 2)); bottomFace.SetValue(Canvas.TopProperty, (Double)(doughnutParams.Center.Y - topFace.Height / 2)); gg = new GeometryGroup(); gg.Children.Add(new EllipseGeometry() { Center = new Point(topFace.Width / 2, topFace.Height / 2), RadiusX = topFace.Width, RadiusY = topFace.Height }); gg.Children.Add(new EllipseGeometry() { Center = new Point(topFace.Width / 2, topFace.Height / 2), RadiusX = doughnutParams.InnerRadius, RadiusY = topFace.Height - 2 * (doughnutParams.OuterRadius - doughnutParams.InnerRadius) }); bottomFace.Clip = gg; pieFaces.Add(bottomFace); faces.Parts.Add(bottomFace); } else { topFace = GetDoughnutFace(doughnutParams, centroid, topInnerArcStart, topInnerArcStop, topOuterArcStart, topOuterArcStop, true); pieFaces.Add(topFace); faces.Parts.Add(topFace); bottomFace = GetDoughnutFace(doughnutParams, centroid, bottomInnerArcStart, bottomInnerArcStop, bottomOuterArcStart, bottomOuterArcStop, false); pieFaces.Add(bottomFace); faces.Parts.Add(bottomFace); rightFace = GetPieSide(doughnutParams, centroid, topInnerArcStart, bottomInnerArcStart, topOuterArcStart, bottomOuterArcStart); pieFaces.Add(rightFace); faces.Parts.Add(rightFace); leftFace = GetPieSide(doughnutParams, centroid, topInnerArcStop, bottomInnerArcStop, topOuterArcStop, bottomOuterArcStop); pieFaces.Add(leftFace); faces.Parts.Add(leftFace); } List<Shape> curvedSurface = GetDoughnutCurvedFace(doughnutParams, centroid, topFaceCenter, bottomFaceCenter); pieFaces.InsertRange(pieFaces.Count, curvedSurface); foreach (FrameworkElement fe in curvedSurface) faces.Parts.Add(fe); labelLinePath = CreateLabelLine(currentDataSeries, doughnutParams, center, ref unExplodedPoints, ref explodedPoints); if ((doughnutParams.TagReference as DataPoint).InternalYValue == 0) return new List<Shape>(); //Top face ZIndex topFace.SetValue(Canvas.ZIndexProperty, (Int32)(50000)); //BottomFace ZIndex bottomFace.SetValue(Canvas.ZIndexProperty, (Int32)(-50000)); if (!(doughnutParams.StartAngle == doughnutParams.StopAngle && doughnutParams.IsLargerArc)) { // ZIndex of curved face if (doughnutParams.StartAngle >= Math.PI && doughnutParams.StartAngle <= Math.PI * 2 && doughnutParams.StopAngle >= Math.PI && doughnutParams.StopAngle <= Math.PI * 2 && doughnutParams.IsLargerArc) { _elementPositionData.Add(new ElementPositionData(rightFace, doughnutParams.StartAngle, doughnutParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], 0, Math.PI)); _elementPositionData.Add(new ElementPositionData(curvedSurface[1], doughnutParams.StartAngle, 0)); _elementPositionData.Add(new ElementPositionData(curvedSurface[2], Math.PI, doughnutParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(leftFace, doughnutParams.StopAngle, doughnutParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, 0, Math.PI)); } else if (doughnutParams.StartAngle >= 0 && doughnutParams.StartAngle <= Math.PI && doughnutParams.StopAngle >= 0 && doughnutParams.StopAngle <= Math.PI && doughnutParams.IsLargerArc) { _elementPositionData.Add(new ElementPositionData(rightFace, doughnutParams.StartAngle, doughnutParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, Math.PI)); _elementPositionData.Add(new ElementPositionData(curvedSurface[1], Math.PI * 2, doughnutParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[2], Math.PI, Math.PI * 2)); _elementPositionData.Add(new ElementPositionData(leftFace, doughnutParams.StopAngle, doughnutParams.StopAngle)); if (labelLinePath != null) labelLinePath.SetValue(Canvas.ZIndexProperty, -50000); } else if (doughnutParams.StartAngle >= 0 && doughnutParams.StartAngle <= Math.PI && doughnutParams.StopAngle >= Math.PI && doughnutParams.StopAngle <= Math.PI * 2) { _elementPositionData.Add(new ElementPositionData(rightFace, doughnutParams.StartAngle, doughnutParams.StartAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, doughnutParams.StartAngle, Math.PI)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, Math.PI)); _elementPositionData.Add(new ElementPositionData(curvedSurface[1], Math.PI, doughnutParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(leftFace, doughnutParams.StopAngle, doughnutParams.StopAngle)); } else if (doughnutParams.StartAngle >= Math.PI && doughnutParams.StartAngle <= Math.PI * 2 && doughnutParams.StopAngle >= 0 && doughnutParams.StopAngle <= Math.PI) { _elementPositionData.Add(new ElementPositionData(rightFace, doughnutParams.StartAngle, doughnutParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], 0, doughnutParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[1], doughnutParams.StartAngle, 0)); _elementPositionData.Add(new ElementPositionData(leftFace, doughnutParams.StopAngle, doughnutParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, doughnutParams.StopAngle, doughnutParams.StopAngle)); } else { _elementPositionData.Add(new ElementPositionData(rightFace, doughnutParams.StartAngle, doughnutParams.StartAngle)); if (doughnutParams.StartAngle >= 0 && doughnutParams.StartAngle < Math.PI / 2 && doughnutParams.StopAngle >= 0 && doughnutParams.StopAngle < Math.PI / 2) { if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, doughnutParams.StopAngle, doughnutParams.StopAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, doughnutParams.StopAngle)); } else if (doughnutParams.StartAngle >= 0 && doughnutParams.StartAngle < Math.PI / 2 && doughnutParams.StopAngle >= Math.PI / 2 && doughnutParams.StopAngle < Math.PI) { if (labelLinePath != null) labelLinePath.SetValue(Canvas.ZIndexProperty, 40000); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, doughnutParams.StopAngle)); } else if (doughnutParams.StartAngle >= Math.PI / 2 && doughnutParams.StartAngle < Math.PI && doughnutParams.StopAngle >= Math.PI / 2 && doughnutParams.StopAngle < Math.PI) { if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, doughnutParams.StartAngle, doughnutParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, doughnutParams.StopAngle)); } else if (doughnutParams.StartAngle >= Math.PI && doughnutParams.StartAngle < Math.PI * 1.5 && doughnutParams.StopAngle >= Math.PI && doughnutParams.StopAngle < Math.PI * 1.5) { _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, doughnutParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, doughnutParams.StartAngle, doughnutParams.StartAngle)); } else if (doughnutParams.StartAngle >= Math.PI * 1.5 && doughnutParams.StartAngle < Math.PI * 2 && doughnutParams.StopAngle >= Math.PI * 1.5 && doughnutParams.StopAngle < Math.PI * 2) { _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, doughnutParams.StopAngle)); if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, doughnutParams.StartAngle, doughnutParams.StopAngle)); } else { if (labelLinePath != null) _elementPositionData.Add(new ElementPositionData(labelLinePath, doughnutParams.StartAngle, doughnutParams.StartAngle)); _elementPositionData.Add(new ElementPositionData(curvedSurface[0], doughnutParams.StartAngle, doughnutParams.StopAngle)); } _elementPositionData.Add(new ElementPositionData(leftFace, doughnutParams.StopAngle, doughnutParams.StopAngle)); } } return pieFaces; }
/// <summary> /// Get visual object for CandleStick chart /// </summary> /// <param name="width">Width of the chart</param> /// <param name="height">Height of the chart</param> /// <param name="plotDetails">plotDetails</param> /// <param name="seriesList">List of DataSeries</param> /// <param name="chart">Chart</param> /// <param name="plankDepth">Plank depth</param> /// <param name="animationEnabled">Whether animation is enabled</param> /// <returns>CandleStick chart canvas</returns> internal static Canvas GetVisualObjectForCandleStick(Panel preExistingPanel, Double width, Double height, PlotDetails plotDetails, List<DataSeries> seriesList, Chart chart, Double plankDepth, bool animationEnabled) { // return new Canvas() { Background = Graphics.GetRandonColor() , Width = width, Height = height}; if (Double.IsNaN(width) || Double.IsNaN(height) || width <= 0 || height <= 0) return null; Canvas visual, labelCanvas, candleStickCanvas; RenderHelper.RepareCanvas4Drawing(preExistingPanel as Canvas, out visual, out labelCanvas, out candleStickCanvas, width, height); Double depth3d = plankDepth / (plotDetails.Layer3DCount == 0 ? 1 : plotDetails.Layer3DCount) * (chart.View3D ? 1 : 0); Double visualOffset = depth3d * (plotDetails.SeriesDrawingIndex[seriesList[0]] + 1 - (plotDetails.Layer3DCount == 0 ? 0 : 1)); visual.SetValue(Canvas.TopProperty, visualOffset); visual.SetValue(Canvas.LeftProperty, -visualOffset); Double animationBeginTime = 0; DataSeries _tempDataSeries = null; // Calculate width of a DataPoint Double dataPointWidth = CalculateDataPointWidth(width, height, chart); foreach (DataSeries series in seriesList) { if (series.Enabled == false) continue; Faces dsFaces = new Faces() { Visual = candleStickCanvas, LabelCanvas = labelCanvas }; series.Faces = dsFaces; PlotGroup plotGroup = series.PlotGroup; _tempDataSeries = series; foreach (DataPoint dataPoint in series.InternalDataPoints) CreateOrUpdateACandleStick(dataPoint, candleStickCanvas, labelCanvas, width, height, dataPointWidth); // Apply animation to series if (animationEnabled) { if (_tempDataSeries.Storyboard == null) _tempDataSeries.Storyboard = new Storyboard(); _tempDataSeries.Storyboard = AnimationHelper.ApplyOpacityAnimation(candleStickCanvas, _tempDataSeries, _tempDataSeries.Storyboard, animationBeginTime, 1, 0, 1); animationBeginTime += 0.5; } } // Label animation if (animationEnabled && _tempDataSeries != null) _tempDataSeries.Storyboard = AnimationHelper.ApplyOpacityAnimation(labelCanvas, _tempDataSeries, _tempDataSeries.Storyboard, animationBeginTime, 1, 0, 1); candleStickCanvas.Tag = null; // ColumnChart.CreateOrUpdatePlank(chart, seriesList[0].PlotGroup.AxisY, candleStickCanvas, depth3d, Orientation.Horizontal); // Remove old visual and add new visual in to the existing panel if (preExistingPanel != null) { visual.Children.RemoveAt(1); visual.Children.Add(candleStickCanvas); } else { labelCanvas.SetValue(Canvas.ZIndexProperty, 1); visual.Children.Add(labelCanvas); visual.Children.Add(candleStickCanvas); } RectangleGeometry clipRectangle = new RectangleGeometry(); clipRectangle.Rect = new Rect(0, -chart.ChartArea.PLANK_DEPTH, width + chart.ChartArea.PLANK_OFFSET, height + chart.ChartArea.PLANK_DEPTH); visual.Clip = clipRectangle; return visual; // visual.Children.Add(candleStickCanvas); // visual.Children.Add(labelCanvas); // return visual; }
/// <summary> /// Create3DPie /// </summary> /// <param name="width">Visual width</param> /// <param name="height">Visual height</param> /// <param name="series">DataSeries</param> /// <param name="enabledDataPoints"> Enabled InternalDataPoints in the DataSeries</param> /// <param name="dataPoint">DataPoint reference</param> /// <param name="visual">visual canvas reference</param> /// <param name="faces">Visual faces</param> /// <param name="pieParams">Pie parameters</param> /// <param name="offsetX">X offset</param> /// <param name="offsetX">Y offset</param> /// <param name="zindex">Z index of the pie</param> /// <param name="isAnimationEnabled">Whether animation is enabled</param> /// <param name="labelStyleCounter">labelStyle count</param> private static void Create2DPie(DataSeries currentDataSeries, Double widthOfPlotArea, Double height, DataSeries series, List<DataPoint> enabledDataPoints, DataPoint dataPoint, ref Canvas visual, ref Faces faces, ref SectorChartShapeParams pieParams, ref Double offsetX, ref Double offsetY, ref Int32 zindex, Boolean isAnimationEnabled, Int32 labelStateCount) { #region 2D Pie PieDoughnut2DPoints unExplodedPoints = new PieDoughnut2DPoints(); PieDoughnut2DPoints explodedPoints = new PieDoughnut2DPoints(); pieParams.TagReference = dataPoint; if (labelStateCount == enabledDataPoints.Count) pieParams.OuterRadius -= pieParams.OuterRadius * pieParams.ExplodeRatio; Canvas pieVisual = GetPie2D(currentDataSeries, ref faces, pieParams, ref unExplodedPoints, ref explodedPoints, ref dataPoint.LabelLine, enabledDataPoints); UpdateExplodedPosition(pieParams, dataPoint, offsetX, unExplodedPoints, explodedPoints, widthOfPlotArea); TranslateTransform translateTransform = new TranslateTransform(); pieVisual.RenderTransform = translateTransform; dataPoint.ExplodeAnimation = new Storyboard(); dataPoint.ExplodeAnimation = CreateExplodingOut2DAnimation(currentDataSeries, dataPoint, dataPoint.ExplodeAnimation, pieVisual, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, translateTransform, unExplodedPoints, explodedPoints, offsetX, offsetY); dataPoint.UnExplodeAnimation = new Storyboard(); dataPoint.UnExplodeAnimation = CreateExplodingIn2DAnimation(currentDataSeries, dataPoint, dataPoint.UnExplodeAnimation, pieVisual, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, translateTransform, unExplodedPoints, explodedPoints, offsetX, offsetY); pieVisual.SetValue(Canvas.TopProperty, height / 2 - pieVisual.Height / 2); pieVisual.SetValue(Canvas.LeftProperty, widthOfPlotArea / 2 - pieVisual.Width / 2); visual.Children.Add(pieVisual); faces.VisualComponents.Add(pieVisual); faces.Visual = pieVisual; #endregion }
/// <summary> /// Get PathGeometry for Line and Shadow /// </summary> /// <param name="pointCollectionList">List of points collection</param> /// <returns>Geometry</returns> /// <summary> /// Get PathGeometry for Line and Shadow /// </summary> /// <param name="dataPointCollectionList">List of Segments. And EachSegments contains a list of DataPoints</param> /// <returns></returns> internal static Geometry GetPathGeometry(RenderAs renderAs, GeometryGroup oldData, List<List<DataPoint>> dataPointCollectionList, Boolean isShadow, Double width, Double height, Canvas line2dLabelCanvas) { GeometryGroup gg; if (oldData != null) { gg = oldData; gg.Children.Clear(); } else { gg = new GeometryGroup(); } foreach (List<DataPoint> pointCollection in dataPointCollectionList) { PathGeometry geometry = new PathGeometry(); PathFigure pathFigure = new PathFigure(); if (pointCollection.Count > 0) { pathFigure.StartPoint = pointCollection[0]._visualPosition; Faces faces = new Faces(); //Add LineSegment faces.Parts.Add(null); // Add PathFigure faces.Parts.Add(pathFigure); if (isShadow) pointCollection[0].ShadowFaces = faces; else { pointCollection[0].Faces = faces; faces.PreviousDataPoint = null; if(pointCollection.Count > 1) faces.NextDataPoint = pointCollection[1]; CreateMarkerAndLabel(pointCollection, 0, width, height, line2dLabelCanvas); } if (renderAs == RenderAs.Spline) GeneratePointCollections4SpLine(pointCollection, width, height, isShadow, pathFigure, ref line2dLabelCanvas); else GeneratePointCollections4Line(pointCollection, width, height, isShadow, pathFigure, ref line2dLabelCanvas); } geometry.Figures.Add(pathFigure); gg.Children.Add(geometry); } return gg; }
/// <summary> /// Return visual object for doughnut chart /// </summary> /// <param name="width">Width of the PlotArea</param> /// <param name="height">Height of the PlotArea</param> /// <param name="plotDetails">PlotDetails reference</param> /// <param name="seriesList">List of series list</param> /// <param name="chart">Chart reference</param> /// <param name="animationEnabled">Whether animation is enabled</param> /// <returns>Canvas</returns> internal static Canvas GetVisualObjectForDoughnutChart(Double widthOfPlotArea, Double height, PlotDetails plotDetails, List<DataSeries> seriesList, Chart chart, bool animationEnabled) { if (Double.IsNaN(widthOfPlotArea) || Double.IsNaN(height) || widthOfPlotArea <= 0 || height <= 0) return null; DataSeries currentDataSeries = null; Canvas visual = new Canvas(); visual.Width = widthOfPlotArea; visual.Height = height; DataSeries series = seriesList[0]; if (series.Enabled == false) return visual; // List<DataPoint> enabledDataPoints = (from datapoint in series.InternalDataPoints where datapoint.Enabled == true && datapoint.InternalYValue != 0 && !Double.IsNaN(datapoint.InternalYValue) select datapoint).ToList(); List<DataPoint> enabledDataPoints = (from datapoint in series.InternalDataPoints where datapoint.Enabled == true && !Double.IsNaN(datapoint.InternalYValue) select datapoint).ToList(); if ((from dp in enabledDataPoints select dp.InternalYValue).Sum() == 0) enabledDataPoints.Clear(); Double absoluteSum = plotDetails.GetAbsoluteSumOfDataPoints(enabledDataPoints); absoluteSum = (absoluteSum == 0) ? 1 : absoluteSum; Double centerX = widthOfPlotArea / 2; Double centerY = height / 2; Double offsetX = 0; Double offsetY = 0; Size pieCanvas = new Size(); Canvas labelCanvas = CreateAndPositionLabels(absoluteSum, enabledDataPoints, widthOfPlotArea, height, ((chart.View3D) ? 0.4 : 1), chart.View3D, ref pieCanvas); Double radius = Math.Min(pieCanvas.Width, pieCanvas.Height) / (chart.View3D ? 1 : 2); Double startAngle = series.InternalStartAngle; Double endAngle = 0; Double angle; Double meanAngle; Double absoluteYValue; Double radiusDiff = 0; var explodedDataPoints = (from datapoint in series.InternalDataPoints where datapoint.Exploded == true && datapoint.InternalYValue != 0 select datapoint); radiusDiff = (explodedDataPoints.Count() > 0) ? radius * 0.3 : 0; if (chart.View3D) { _elementPositionData = new List<ElementPositionData>(); } if (labelCanvas != null) { labelCanvas.SetValue(Canvas.ZIndexProperty, 50001); labelCanvas.IsHitTestVisible = false; } if (series.Storyboard == null) series.Storyboard = new Storyboard(); currentDataSeries = series; SectorChartShapeParams doughnutParams = null; Int32 labelStateCounter = 0; if (!chart.View3D) { foreach (DataPoint dataPoint in enabledDataPoints) { if (dataPoint.LabelStyle == LabelStyles.Inside || !(Boolean)dataPoint.LabelEnabled) labelStateCounter++; } } foreach (DataPoint dataPoint in enabledDataPoints) { if (Double.IsNaN(dataPoint.InternalYValue))// || dataPoint.InternalYValue == 0) continue; absoluteYValue = Math.Abs(dataPoint.InternalYValue); angle = (absoluteYValue / absoluteSum) * Math.PI * 2; endAngle = startAngle + angle; meanAngle = (startAngle + endAngle) / 2; doughnutParams = new SectorChartShapeParams(); dataPoint.VisualParams = doughnutParams; doughnutParams.AnimationEnabled = animationEnabled; doughnutParams.Storyboard = series.Storyboard; doughnutParams.ExplodeRatio = chart.View3D ? 0.2 : 0.1; doughnutParams.Center = new Point(centerX, centerY); doughnutParams.DataPoint = dataPoint; doughnutParams.InnerRadius = radius / 2; doughnutParams.OuterRadius = radius; if (chart.View3D) { doughnutParams.StartAngle = doughnutParams.FixAngle((startAngle) % (Math.PI * 2)); doughnutParams.StopAngle = doughnutParams.FixAngle((endAngle) % (Math.PI * 2)); } else { doughnutParams.StartAngle = startAngle; doughnutParams.StopAngle = endAngle; } doughnutParams.Lighting = (Boolean)dataPoint.LightingEnabled; doughnutParams.Bevel = series.Bevel; doughnutParams.IsLargerArc = (angle / (Math.PI)) > 1; doughnutParams.Background = dataPoint.Color; doughnutParams.Width = widthOfPlotArea; doughnutParams.Height = height; doughnutParams.TiltAngle = Math.Asin(0.4); doughnutParams.Depth = 20 / doughnutParams.YAxisScaling; doughnutParams.MeanAngle = meanAngle; doughnutParams.LabelLineEnabled = (Boolean)dataPoint.LabelLineEnabled; doughnutParams.LabelLineColor = dataPoint.LabelLineColor; doughnutParams.LabelLineThickness = (Double)dataPoint.LabelLineThickness; doughnutParams.LabelLineStyle = ExtendedGraphics.GetDashArray((LineStyles)dataPoint.LabelLineStyle); offsetX = radius * doughnutParams.ExplodeRatio * Math.Cos(meanAngle); offsetY = radius * doughnutParams.ExplodeRatio * Math.Sin(meanAngle); doughnutParams.OffsetX = offsetX; doughnutParams.OffsetY = offsetY * (chart.View3D ? doughnutParams.YAxisScaling : 1); if (dataPoint.LabelVisual != null) { if (dataPoint.LabelVisual.Visibility == Visibility.Collapsed) doughnutParams.LabelLineEnabled = false; Double left = (Double)dataPoint.LabelVisual.GetValue(Canvas.LeftProperty); if (left < widthOfPlotArea / 2) { doughnutParams.LabelLineTargetToRight = true; // pieParams.LabelPoint = new Point((Double)dataPoint.LabelVisual.GetValue(Canvas.LeftProperty) + dataPoint.LabelVisual.DesiredSize.Width, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.DesiredSize.Height / 2); doughnutParams.LabelPoint = new Point(left + dataPoint.LabelVisual.Width + LabelPlacementHelper.LABEL_LINE_GAP, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.Height / 2); } else { doughnutParams.LabelLineTargetToRight = false; doughnutParams.LabelPoint = new Point(left - LabelPlacementHelper.LABEL_LINE_GAP, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.Height / 2); } //if ((Double)dataPoint.LabelVisual.GetValue(Canvas.LeftProperty) < width / 2) //{ // doughnutParams.LabelPoint = new Point((Double)dataPoint.LabelVisual.GetValue(Canvas.LeftProperty) + dataPoint.LabelVisual.Width + LABEL_LINE_GAP, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.Height / 2); //} //else //{ // doughnutParams.LabelPoint = new Point((Double)dataPoint.LabelVisual.GetValue(Canvas.LeftProperty) - LABEL_LINE_GAP, (Double)dataPoint.LabelVisual.GetValue(Canvas.TopProperty) + dataPoint.LabelVisual.Height / 2); //} // apply animation to the labels if (animationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, doughnutParams.DataPoint, series.Storyboard, dataPoint.LabelVisual, 2, 1, 0.5); dataPoint.LabelVisual.Opacity = 0; } } if (dataPoint.LabelStyle == LabelStyles.Inside && dataPoint.InternalYValue == 0) doughnutParams.LabelLineEnabled = false; Faces faces = new Faces(); faces.Parts = new List<DependencyObject>(); doughnutParams.TagReference = dataPoint; if (chart.View3D) { PieDoughnut3DPoints unExplodedPoints = new PieDoughnut3DPoints(); PieDoughnut3DPoints explodedPoints = new PieDoughnut3DPoints(); List<Shape> doughnutFaces = GetDoughnut3D(currentDataSeries, ref faces, doughnutParams, ref unExplodedPoints, ref explodedPoints, ref dataPoint.LabelLine, enabledDataPoints); foreach (Shape path in doughnutFaces) { if (path != null) { visual.Children.Add(path); faces.VisualComponents.Add(path); faces.BorderElements.Add(path); path.RenderTransform = new TranslateTransform(); // apply animation to the 3D sections if (animationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, doughnutParams.DataPoint, series.Storyboard, path, 1.0 / (series.InternalDataPoints.Count) * (series.InternalDataPoints.IndexOf(dataPoint)), dataPoint.InternalOpacity, 0.5); path.Opacity = 0; } } } if (dataPoint.LabelLine != null && doughnutParams.LabelLineEnabled) { dataPoint.LabelLine.RenderTransform = new TranslateTransform(); visual.Children.Add(dataPoint.LabelLine); if (dataPoint.InternalYValue == 0) { Double yOffset = doughnutParams.YAxisScaling; Line zeroLine = new Line(); zeroLine.X1 = doughnutParams.Center.X + doughnutParams.InnerRadius * Math.Cos(doughnutParams.MeanAngle); zeroLine.Y1 = doughnutParams.Center.Y + doughnutParams.InnerRadius * Math.Sin(doughnutParams.MeanAngle); zeroLine.Y1 -= offsetY; zeroLine.Y1 += doughnutParams.Depth / 2 * doughnutParams.ZAxisScaling; zeroLine.X2 = unExplodedPoints.LabelLineStartPoint.X; zeroLine.Y2 = unExplodedPoints.LabelLineStartPoint.Y; zeroLine.Stroke = doughnutParams.LabelLineColor; zeroLine.StrokeThickness = 0.25; zeroLine.IsHitTestVisible = false; visual.Children.Add(zeroLine); if (animationEnabled) { series.Storyboard = CreateOpacityAnimation(currentDataSeries, doughnutParams.DataPoint, series.Storyboard, zeroLine, 2, zeroLine.Opacity, 0.5); zeroLine.Opacity = 0; } } faces.VisualComponents.Add(dataPoint.LabelLine); } faces.Visual = visual; UpdateExplodedPosition(doughnutParams, dataPoint, offsetX, unExplodedPoints, explodedPoints, widthOfPlotArea); ///------------------------ dataPoint.ExplodeAnimation = new Storyboard(); dataPoint.ExplodeAnimation = CreateExplodingOut3DAnimation(currentDataSeries, dataPoint, dataPoint.ExplodeAnimation, doughnutFaces, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, unExplodedPoints, explodedPoints, doughnutParams.OffsetX, doughnutParams.OffsetY); dataPoint.UnExplodeAnimation = new Storyboard(); dataPoint.UnExplodeAnimation = CreateExplodingIn3DAnimation(currentDataSeries, dataPoint, dataPoint.UnExplodeAnimation, doughnutFaces, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, unExplodedPoints, explodedPoints, doughnutParams.OffsetX, doughnutParams.OffsetY); } else { PieDoughnut2DPoints unExplodedPoints = new PieDoughnut2DPoints(); PieDoughnut2DPoints explodedPoints = new PieDoughnut2DPoints(); if (labelStateCounter == enabledDataPoints.Count) { doughnutParams.OuterRadius -= doughnutParams.OuterRadius * doughnutParams.ExplodeRatio; doughnutParams.InnerRadius = doughnutParams.OuterRadius / 2; } Canvas pieVisual = GetDoughnut2D(currentDataSeries, ref faces, doughnutParams, ref unExplodedPoints, ref explodedPoints, ref dataPoint.LabelLine, enabledDataPoints); UpdateExplodedPosition(doughnutParams, dataPoint, offsetX, unExplodedPoints, explodedPoints, widthOfPlotArea); TranslateTransform translateTransform = new TranslateTransform(); pieVisual.RenderTransform = translateTransform; dataPoint.ExplodeAnimation = new Storyboard(); dataPoint.ExplodeAnimation = CreateExplodingOut2DAnimation(currentDataSeries, dataPoint, dataPoint.ExplodeAnimation, pieVisual, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, translateTransform, unExplodedPoints, explodedPoints, offsetX, offsetY); dataPoint.UnExplodeAnimation = new Storyboard(); dataPoint.UnExplodeAnimation = CreateExplodingIn2DAnimation(currentDataSeries, dataPoint, dataPoint.UnExplodeAnimation, pieVisual, dataPoint.LabelVisual as Canvas, dataPoint.LabelLine, translateTransform, unExplodedPoints, explodedPoints, offsetX, offsetY); pieVisual.SetValue(Canvas.TopProperty, height / 2 - pieVisual.Height / 2); pieVisual.SetValue(Canvas.LeftProperty, widthOfPlotArea / 2 - pieVisual.Width / 2); visual.Children.Add(pieVisual); faces.VisualComponents.Add(pieVisual); faces.Visual = pieVisual; } dataPoint.Faces = faces; startAngle = endAngle; if (!chart.AnimationEnabled || chart.IsInDesignMode || !chart.ChartArea._isFirstTimeRender) { if (dataPoint.Faces != null) { foreach (Shape shape in dataPoint.Faces.BorderElements) { InteractivityHelper.ApplyBorderEffect(shape, (BorderStyles)dataPoint.BorderStyle, dataPoint.InternalBorderThickness.Left, dataPoint.BorderColor); } } } } if (chart.View3D) { Int32 zindex1, zindex2; _elementPositionData.Sort(ElementPositionData.CompareAngle); zindex1 = 1000; zindex2 = -1000; for (Int32 i = 0; i < _elementPositionData.Count; i++) { SetZIndex(_elementPositionData[i].Element, ref zindex1, ref zindex2, _elementPositionData[i].StartAngle); } } if (labelCanvas != null) visual.Children.Add(labelCanvas); RectangleGeometry clipRectangle = new RectangleGeometry(); clipRectangle.Rect = new Rect(0, 0, widthOfPlotArea, height); visual.Clip = clipRectangle; return visual; }
private static void GeneratePointCollections4SpLine(List<DataPoint> pointCollection, Double width, Double height, Boolean isShadow, PathFigure pathFigure, ref Canvas line2dLabelCanvas) { Point[] knotPoints = (from dp in pointCollection select dp._visualPosition).ToArray(); // Get Bezier Spline Control Points. Point[] cp1, cp2; Bezier.GetCurveControlPoints(2, knotPoints, out cp1, out cp2); if (pointCollection.Count > 0 && pointCollection[0].Faces != null) pointCollection[0].Faces.DataContext = pointCollection; /* PolyLineSegment segment = new PolyLineSegment(); segment.Points = GeneratePointCollection(segment, pointCollection, createFaces); pathFigure.Segments.Add(segment); */ for (int i = 1; i < pointCollection.Count; i++) { Faces faces = new Faces(); faces.DataContext = pointCollection; BezierSegment segment = new BezierSegment() { Point1 = cp1[i - 1], Point2 = cp2[i - 1], Point3 = knotPoints[i] }; //Graphics.DrawPointAt(segment.Point1, line2dLabelCanvas, Colors.Red); //Graphics.DrawPointAt(segment.Point2, line2dLabelCanvas, Colors.Green); //Graphics.DrawPointAt(segment.Point3, line2dLabelCanvas, Colors.Blue); faces.PreviousDataPoint = pointCollection[i - 1]; if (!isShadow) { if (i != pointCollection.Count - 1) faces.NextDataPoint = pointCollection[i + 1]; else faces.NextDataPoint = null; } // Add LineSegment faces.Parts.Add(segment); // Add PathFigure faces.Parts.Add(pathFigure); if (isShadow) pointCollection[i].ShadowFaces = faces; else pointCollection[i].Faces = faces; pathFigure.Segments.Add(segment); if (!isShadow) { CreateMarkerAndLabel(pointCollection, i, width, height, line2dLabelCanvas); } } }
/// <summary> /// Get PathGeometry for Line and Shadow /// </summary> /// <param name="pointCollectionList">List of points collection</param> /// <returns>Geometry</returns> /// <summary> /// Get PathGeometry for Line and Shadow /// </summary> /// <param name="dataPointCollectionList">List of Segments. And EachSegments contains a list of DataPoints</param> /// <returns></returns> private static Geometry GetPathGeometry(GeometryGroup oldData, List<List<DataPoint>> dataPointCollectionList, Boolean isShadow, Double width, Double height, Canvas line2dLabelCanvas) { GeometryGroup gg; if (oldData != null) { gg = oldData; gg.Children.Clear(); } else { gg = new GeometryGroup(); } foreach (List<DataPoint> pointCollection in dataPointCollectionList) { PathGeometry geometry = new PathGeometry(); PathFigure pathFigure = new PathFigure(); Double xPosition = 0; Double yPosition = 0; if (pointCollection.Count > 0) { pathFigure.StartPoint = pointCollection[0]._visualPosition; Faces faces = new Faces(); //Add LineSegment faces.Parts.Add(null); // Add PathFigure faces.Parts.Add(pathFigure); if (isShadow) pointCollection[0].ShadowFaces = faces; else { pointCollection[0].Faces = faces; faces.PreviousDataPoint = null; if (pointCollection.Count > 1) faces.NextDataPoint = pointCollection[1]; if (pointCollection[0].Marker != null && pointCollection[0].Marker.Visual != null) { Point newMarkerPosition = pointCollection[0].Marker.CalculateActualPosition(pointCollection[0]._visualPosition.X, pointCollection[0]._visualPosition.Y, new Point(0.5, 0.5)); pointCollection[0]._parsedToolTipText = pointCollection[0].TextParser(pointCollection[0].ToolTipText); pointCollection[0].Marker.Visual.Visibility = Visibility.Visible; pointCollection[0].Marker.Visual.SetValue(Canvas.TopProperty, newMarkerPosition.Y); pointCollection[0].Marker.Visual.SetValue(Canvas.LeftProperty, newMarkerPosition.X); } else { LineChart.CreateMarkerAForLineDataPoint(pointCollection[0], width, height, ref line2dLabelCanvas, out xPosition, out yPosition); } if ((Boolean)pointCollection[0].LabelEnabled) { if (pointCollection[0].LabelVisual != null) { Double labelLeft = 0; Double labelTop = 0; SetLabelPosition4LineDataPoint(pointCollection[0], width, height, pointCollection[0].InternalYValue >= 0, pointCollection[0]._visualPosition.X, pointCollection[0]._visualPosition.Y, ref labelLeft, ref labelTop, 6, new Size(pointCollection[0].LabelVisual.Width, pointCollection[0].LabelVisual.Height)); (((pointCollection[0].LabelVisual as Border).Child as Canvas).Children[0] as TextBlock).Text = pointCollection[0].TextParser(pointCollection[0].LabelText); pointCollection[0].LabelVisual.Visibility = Visibility.Visible; pointCollection[0].LabelVisual.SetValue(Canvas.LeftProperty, labelLeft); pointCollection[0].LabelVisual.SetValue(Canvas.TopProperty, labelTop); } else { CreateLabel4LineDataPoint(pointCollection[0], width, height, pointCollection[0].InternalYValue >= 0, xPosition, yPosition, ref line2dLabelCanvas, true); } } //CreateMarkerAForLineDataPoint(pointCollection[0], width, height, ref line2dLabelCanvas, out xPosition, out yPosition); //if((Boolean)pointCollection[0].LabelEnabled) // CreateLabel4LineDataPoint(pointCollection[0], width, height, pointCollection[0].InternalYValue >= 0, xPosition, yPosition, ref line2dLabelCanvas, true); } /* * PolyLineSegment segment = new PolyLineSegment(); segment.Points = GeneratePointCollection(segment, pointCollection, createFaces); pathFigure.Segments.Add(segment); */ //if (pointCollection.Count < 2) //{ // LineSegment seg = new LineSegment(); // Point p = new Point(); // p.X = pointCollection[1]._visualPosition.X; // p.Y = pointCollection[0]._visualPosition.Y; // seg.Point = p; // faces.Parts.Add(seg); // pathFigure.Segments.Add(seg); //} for (int i = 1; i < pointCollection.Count; i++) { //Creates a new line segment from previous DataPoint to Step point. LineSegment segment1 = new LineSegment(); Point p = new Point(); p.X = pointCollection[i]._visualPosition.X; p.Y = pointCollection[i - 1]._visualPosition.Y; segment1.Point = p; //Creates a new line segment from Step point to next DataPoint LineSegment segment = new LineSegment(); segment.Point = pointCollection[i]._visualPosition; faces = new Faces(); faces.PreviousDataPoint = pointCollection[i - 1]; if (!isShadow) { if (i != pointCollection.Count - 1) faces.NextDataPoint = pointCollection[i + 1]; else faces.NextDataPoint = null; } //Add LineSegments faces.Parts.Add(segment1); faces.Parts.Add(segment); // Add PathFigure faces.Parts.Add(pathFigure); if (isShadow) pointCollection[i].ShadowFaces = faces; else pointCollection[i].Faces = faces; pathFigure.Segments.Add(segment1); pathFigure.Segments.Add(segment); if (!isShadow) { if (pointCollection[i].Marker != null && pointCollection[i].Marker.Visual != null) { Point newMarkerPosition = pointCollection[i].Marker.CalculateActualPosition(pointCollection[i]._visualPosition.X, pointCollection[i]._visualPosition.Y, new Point(0.5, 0.5)); pointCollection[i]._parsedToolTipText = pointCollection[i].TextParser(pointCollection[i].ToolTipText); pointCollection[i].Marker.Visual.Visibility = Visibility.Visible; pointCollection[i].Marker.Visual.SetValue(Canvas.TopProperty, newMarkerPosition.Y); pointCollection[i].Marker.Visual.SetValue(Canvas.LeftProperty, newMarkerPosition.X); } else { LineChart.CreateMarkerAForLineDataPoint(pointCollection[i], width, height, ref line2dLabelCanvas, out xPosition, out yPosition); } if ((Boolean)pointCollection[i].LabelEnabled) { if (pointCollection[i].LabelVisual != null) { Double labelLeft = 0; Double labelTop = 0; SetLabelPosition4LineDataPoint(pointCollection[i], width, height, pointCollection[i].InternalYValue >= 0, pointCollection[i]._visualPosition.X, pointCollection[i]._visualPosition.Y, ref labelLeft, ref labelTop, 6, new Size(pointCollection[i].LabelVisual.Width, pointCollection[i].LabelVisual.Height)); (((pointCollection[i].LabelVisual as Border).Child as Canvas).Children[0] as TextBlock).Text = pointCollection[i].TextParser(pointCollection[i].LabelText); pointCollection[i].LabelVisual.Visibility = Visibility.Visible; pointCollection[i].LabelVisual.SetValue(Canvas.LeftProperty, labelLeft); pointCollection[i].LabelVisual.SetValue(Canvas.TopProperty, labelTop); } else { CreateLabel4LineDataPoint(pointCollection[i], width, height, pointCollection[i].InternalYValue >= 0, xPosition, yPosition, ref line2dLabelCanvas, true); } } //CreateMarkerAForLineDataPoint(pointCollection[i], width, height, ref line2dLabelCanvas, out xPosition, out yPosition); //if ((Boolean)pointCollection[i].LabelEnabled) // CreateLabel4LineDataPoint(pointCollection[i], width, height, pointCollection[i].InternalYValue >= 0, xPosition, yPosition, ref line2dLabelCanvas, true); } } } geometry.Figures.Add(pathFigure); gg.Children.Add(geometry); } return gg; }
/// <summary> /// Create a slice of a pyramid /// </summary> /// <param name="isLightingGradientLayer">Whether CreatePyramidSlice() function should create a layer for lighting</param> /// <param name="topRadius">Top Radius of the pyramid</param> /// <param name="is3D">Whether the chart is a 3D Chart</param> /// <param name="pyramidSlice">PyramidSlice canvas reference</param> /// <param name="yScaleTop">Top YScale for 3D view</param> /// <param name="yScaleBottom">Bottom YScale for 3D view</param> /// <param name="sideFillColor">Side surface fill color</param> /// <param name="topFillColor">Top surface fill color</param> /// <param name="topSurfaceStroke">Top surface stroke color</param> /// <param name="animationEnabled">Whether animation is enabled</param> /// <returns>Return pyramid slice canvas</returns> private static Canvas CreatePyramidSlice(Boolean isLightingGradientLayer, Double topRadius, Boolean is3D, TriangularChartSliceParms pyramidSlice, Double yScaleTop, Double yScaleBottom, Brush sideFillColor, Brush topFillColor, Brush topSurfaceStroke, Boolean animationEnabled) { Canvas sliceCanvas = new Canvas() { Tag = new ElementData() { Element = pyramidSlice.DataPoint } }; Canvas visual = new Canvas() { Width = topRadius * 2, Height = pyramidSlice.Height, Tag = new ElementData() { Element = pyramidSlice.DataPoint } }; // Canvas holds a slice of a pyramid chart Faces faces = null; //visual.Background = Graphics.GetRandomColor(); Pyramid2DSlice pyramid2DSlice = new Pyramid2DSlice() { LT = new Point(topRadius - Math.Abs(pyramidSlice.TopRadius), 0), RT = new Point(topRadius + Math.Abs(pyramidSlice.TopRadius), 0), LB = new Point(topRadius - Math.Abs(pyramidSlice.BottomRadius), pyramidSlice.Height), RB = new Point(topRadius + Math.Abs(pyramidSlice.BottomRadius), pyramidSlice.Height) }; Pyramid3DSlice pyramid3DSlice = null; if (is3D) { Double opacity = pyramidSlice.DataPoint.Opacity * pyramidSlice.DataPoint.Parent.Opacity; pyramid3DSlice = new Pyramid3DSlice(pyramid2DSlice, Math.Abs(yScaleTop / 2), Math.Abs(yScaleBottom / 2) , isLightingGradientLayer ? new SolidColorBrush(Colors.Transparent) : pyramidSlice.DataPoint.Color , (pyramidSlice.Index == 0) , (Boolean)pyramidSlice.DataPoint.LightingEnabled, opacity); List<Path> paths = new List<Path>(); Path lightingLayerLeft = null, lightingLayerFront = null, lightingLayerRight = null; Path backLayerLeft = pyramid3DSlice.GetFace(Pyramid3dLayer.BackLayerLeft, pyramidSlice.DataPoint, !isLightingGradientLayer); Path backLayerRight = pyramid3DSlice.GetFace(Pyramid3dLayer.BackLayerRight, pyramidSlice.DataPoint, !isLightingGradientLayer); Path bottomLayer = pyramid3DSlice.GetFace(Pyramid3dLayer.BottomLayer, pyramidSlice.DataPoint, !isLightingGradientLayer); Path frontLayerLeft = pyramid3DSlice.GetFace(Pyramid3dLayer.FrontLayerLeft, pyramidSlice.DataPoint, !isLightingGradientLayer); Path frontLayerRight = pyramid3DSlice.GetFace(Pyramid3dLayer.FrontLayerRight, pyramidSlice.DataPoint, !isLightingGradientLayer); Path topLayer = pyramid3DSlice.GetFace(Pyramid3dLayer.TopLayer, pyramidSlice.DataPoint, !isLightingGradientLayer); paths.Add(backLayerLeft); paths.Add(backLayerRight); paths.Add(bottomLayer); paths.Add(frontLayerLeft); paths.Add(frontLayerRight); paths.Add(topLayer); if ((Boolean)pyramidSlice.DataPoint.LightingEnabled && !isLightingGradientLayer) { if (pyramidSlice.Index != 0) paths.Add(lightingLayerLeft = pyramid3DSlice.GetFace(Pyramid3dLayer.LightingLayerLeft, pyramidSlice.DataPoint, !isLightingGradientLayer)); paths.Add(lightingLayerFront = pyramid3DSlice.GetFace(Pyramid3dLayer.LightingLayerFront, pyramidSlice.DataPoint, !isLightingGradientLayer)); if (pyramidSlice.Index != 0) paths.Add(lightingLayerRight = pyramid3DSlice.GetFace(Pyramid3dLayer.LightingLayerRight, pyramidSlice.DataPoint, !isLightingGradientLayer)); } foreach (Path path in paths) visual.Children.Add(path); if (!isLightingGradientLayer) { // Update faces for the DataPoint faces = new Faces(); foreach (Path path in paths) faces.VisualComponents.Add(path); foreach (Path path in paths) faces.Parts.Add(path); // If lighting is disabled then the visual components are the border elements if (!(Boolean)pyramidSlice.DataPoint.LightingEnabled) { foreach (Path path in paths) { if (path != bottomLayer && path != backLayerLeft && path != backLayerRight) faces.BorderElements.Add(path); } if(opacity < 1) faces.BorderElements.Add(bottomLayer); } pyramidSlice.DataPoint.Faces = faces; } else { faces = pyramidSlice.DataPoint.Faces; if (faces != null) { foreach (Path path in paths) { if (path != bottomLayer && path != backLayerLeft && path != backLayerRight) faces.BorderElements.Add(path); } if (opacity < 1) faces.BorderElements.Add(bottomLayer); } } if (faces.BorderElements != null) { foreach (Path path in faces.BorderElements) { path.StrokeThickness = pyramidSlice.DataPoint.BorderThickness.Left; path.Stroke = pyramidSlice.DataPoint.BorderColor; path.StrokeDashArray = ExtendedGraphics.GetDashArray((BorderStyles)pyramidSlice.DataPoint.BorderStyle); } } // Apply animation for the 3D pyramid slice if (animationEnabled) { foreach (Path path in paths) { //Double animationBeginTime = (pyramidSlice.DataPoint.Parent.InternalDataPoints.Count - pyramidSlice.Index) / pyramidSlice.DataPoint.Parent.InternalDataPoints.Count; pyramidSlice.DataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(path, pyramidSlice.DataPoint.Parent, pyramidSlice.DataPoint.Parent.Storyboard, 0, pyramidSlice.DataPoint.InternalOpacity, 0, 1); } } } else { // PathGeometry for for a pyramid slice path PathGeometry pathGeometry = new PathGeometry(); // pathFigure for for a pyramid slice path PathFigure pathFigure = new PathFigure() { StartPoint = pyramid2DSlice.LT, IsClosed= true }; // PathFigure of a pyramid slice // Path for for a pyramid slice Path path4Slice = new Path() { Fill = sideFillColor }; path4Slice.Tag = new ElementData() { Element = pyramidSlice.DataPoint }; // Set path data path4Slice.Data = pathGeometry; // Set properties for path path4Slice.StrokeThickness = 0; path4Slice.Stroke = new SolidColorBrush(Colors.Black); // Add path elements to its parent canvas pathGeometry.Figures.Add(pathFigure); visual.Children.Add(path4Slice); PolyLineSegment polySeg = new PolyLineSegment(); polySeg.Points = pyramid2DSlice.GetAllPoints(); pathFigure.Segments.Add(polySeg); // Points of a 2D pyramid slice Point[] pyramidCornerPoints = new Point[8]; pyramidCornerPoints[0] = new Point(topRadius - pyramidSlice.TopRadius, 0); pyramidCornerPoints[1] = new Point(topRadius + pyramidSlice.TopRadius, 0); pyramidCornerPoints[2] = new Point(topRadius + pyramidSlice.BottomRadius, pyramidSlice.Height); pyramidCornerPoints[3] = new Point(topRadius - pyramidSlice.BottomRadius, pyramidSlice.Height); // Apply animation for the 2D pyramid slice if (animationEnabled) pyramidSlice.DataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(path4Slice, pyramidSlice.DataPoint.Parent, pyramidSlice.DataPoint.Parent.Storyboard, 0, pyramidSlice.DataPoint.InternalOpacity, 0, 1); if (!isLightingGradientLayer) { // Update faces for the DataPoint faces = new Faces(); faces.VisualComponents.Add(path4Slice); (path4Slice.Tag as ElementData).VisualElementName = "PyramidBase"; faces.Parts.Add(path4Slice); faces.BorderElements.Add(path4Slice); path4Slice.StrokeThickness = pyramidSlice.DataPoint.BorderThickness.Left; path4Slice.Stroke = pyramidSlice.DataPoint.BorderColor; path4Slice.StrokeDashArray = ExtendedGraphics.GetDashArray((BorderStyles)pyramidSlice.DataPoint.BorderStyle); pyramidSlice.DataPoint.Faces = faces; // Apply bevel effect for the 2D pyramid Slice if (pyramidSlice.DataPoint.Parent.Bevel) { ApplyPyramidBevel(visual, pyramidSlice, sideFillColor, pyramidCornerPoints); } } else { path4Slice.IsHitTestVisible = false; pyramidSlice.DataPoint.Faces.VisualComponents.Add(path4Slice); (path4Slice.Tag as ElementData).VisualElementName = "Lighting"; } } if (isLightingGradientLayer) { visual.IsHitTestVisible = false; } else { // Drawing LabelLine Canvas labelLineCanvas = CreateLabelLine(pyramidSlice, pyramid3DSlice, topRadius, animationEnabled); if (labelLineCanvas != null) { sliceCanvas.Children.Add(labelLineCanvas); faces.VisualComponents.Add(labelLineCanvas); } // Add label visual to the visual if ((Boolean)pyramidSlice.DataPoint.LabelEnabled) { Canvas labelCanvas = new Canvas(); labelCanvas.SetValue(Canvas.ZIndexProperty, (Int32)10); faces.VisualComponents.Add(pyramidSlice.DataPoint.LabelVisual); // Label placement if (pyramidSlice.DataPoint.LabelStyle == LabelStyles.OutSide) { pyramidSlice.DataPoint.LabelVisual.SetValue(Canvas.TopProperty, pyramidSlice.LabelLineEndPoint.Y - pyramidSlice.DataPoint.LabelVisual.Height / 2); pyramidSlice.DataPoint.LabelVisual.SetValue(Canvas.LeftProperty, pyramidSlice.LabelLineEndPoint.X + 2); } else { if(is3D) { Point centerPoint = Graphics.MidPointOfALine(pyramid3DSlice.Top3DLayer.CB, pyramid3DSlice.Bottom3DLayer.CB); pyramidSlice.DataPoint.LabelVisual.SetValue(Canvas.TopProperty, (centerPoint.Y - pyramidSlice.DataPoint.LabelVisual.Height / 2)); } else pyramidSlice.DataPoint.LabelVisual.SetValue(Canvas.TopProperty, pyramidSlice.LabelLineEndPoint.Y - pyramidSlice.DataPoint.LabelVisual.Height / 2); pyramidSlice.DataPoint.LabelVisual.SetValue(Canvas.LeftProperty, topRadius - pyramidSlice.DataPoint.LabelVisual.Width / 2); } if (animationEnabled) pyramidSlice.DataPoint.Parent.Storyboard = AnimationHelper.ApplyOpacityAnimation(pyramidSlice.DataPoint.LabelVisual, pyramidSlice.DataPoint.Parent, pyramidSlice.DataPoint.Parent.Storyboard, 1.2, 0.5, 0, 1); labelCanvas.Children.Add(pyramidSlice.DataPoint.LabelVisual); sliceCanvas.Children.Add(labelCanvas); } } // if (!isLightingGradientLayer) // faces.Visual = visual; sliceCanvas.Children.Add(visual); // sliceCanvas.Background = new SolidColorBrush(Color.FromArgb((byte)rand.Next(0,200),(byte)rand.Next(0,200),(byte)rand.Next(0,200),(byte)rand.Next(0,200))); return sliceCanvas; }