/// <summary> /// Creates a LabelLine for Pyramid Chart /// </summary> /// <param name="pyramidSlice">TriangularChartSliceParms</param> /// <param name="topRadius">Top most radius of the pyramid</param> /// <param name="animationEnabled">Whether animation is enabled</param> /// <returns>Canvas for labelline </returns> private static Canvas CreateLabelLine(TriangularChartSliceParms pyramidSlice, Pyramid3DSlice pyramid3DSlice, Double topRadius, Boolean animationEnabled) { Canvas labelLineCanvas = null; Point topRightPoint; Point bottomRightPoint; if (pyramid3DSlice == null) // If 2d { topRightPoint = new Point(topRadius + Math.Abs(pyramidSlice.TopRadius), 0); bottomRightPoint = new Point(topRadius + Math.Abs(pyramidSlice.BottomRadius), pyramidSlice.Height); } else { topRightPoint = pyramid3DSlice.Top3DLayer.R; bottomRightPoint = pyramid3DSlice.Bottom3DLayer.R; } pyramidSlice.RightMidPoint = Graphics.MidPointOfALine(topRightPoint, bottomRightPoint); pyramidSlice.LabelLineEndPoint = new Point(2 * topRadius, pyramidSlice.RightMidPoint.Y); pyramidSlice.OrginalLabelLineEndPoint = pyramidSlice.LabelLineEndPoint; if ((Boolean)pyramidSlice.DataPoint.LabelLineEnabled && pyramidSlice.DataPoint.LabelStyle == LabelStyles.OutSide) { labelLineCanvas = new Canvas(); labelLineCanvas.Width = topRadius * 2; labelLineCanvas.Height = pyramidSlice.Height; pyramidSlice.DataPoint.LabelLine = null; Path line = new Path() { Stroke = pyramidSlice.DataPoint.LabelLineColor, Fill = pyramidSlice.DataPoint.LabelLineColor, StrokeDashArray = ExtendedGraphics.GetDashArray((LineStyles)pyramidSlice.DataPoint.LabelLineStyle), StrokeThickness = (Double)pyramidSlice.DataPoint.LabelLineThickness, }; PathGeometry linePathGeometry = new PathGeometry(); // Set first point of the line PathFigure linePathFigure = new PathFigure() { StartPoint = pyramidSlice.RightMidPoint }; // Set second point of line linePathFigure.Segments.Add(new LineSegment() { Point = pyramidSlice.LabelLineEndPoint }); linePathGeometry.Figures.Add(linePathFigure); line.Data = linePathGeometry; pyramidSlice.DataPoint.LabelLine = line; labelLineCanvas.Children.Add(line); if (animationEnabled) pyramidSlice.DataPoint.Parent.Storyboard = ApplyLabeLineAnimation(labelLineCanvas, pyramidSlice.DataPoint.Parent, pyramidSlice.DataPoint.Parent.Storyboard); } return labelLineCanvas; }
/// <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; }