private void _drawPies( Canvas pieContainer, double quadWidth, double quadHeight, int iGroup) { ChartModel model = Model; double[,] yValues = model.YValues; string [] groupLabels = model.GroupLabels; Color[] seriesColors = model.SeriesColors; var pieSize = Math.Min(quadWidth / 2, quadHeight / 2); if (iGroup == -1) { iGroup = 0; } double nPies = yValues.GetUpperBound(1) + 1; double pieTotal = 0; for (int i = 0; i < nPies; ++i) { pieTotal += yValues[iGroup, i]; } string pathXAML = CurrentLookAndFeel.GetPiePathXAML(); Path pathElem; double pieStart = 0, animAngleStart = 0; List <UIElement> dataElems = null; bool animate = (AnimationDuration > 0); if (animate) { dataElems = DataElements; } string gradientXAML = CurrentLookAndFeel.GetElementGradientXAML(); TranslateTransform defaultTransform; for (int i = 0; i < nPies; ++i) { double valueRatio = 1 - (yValues[iGroup, i]) / (pieTotal); double x1 = pieSize * Math.Cos(pieStart * Math.PI * 2), y1 = pieSize * Math.Sin(pieStart * Math.PI * 2); StringBuilder sb = new StringBuilder(); sb.Append("M0,0 L"); sb.Append(x1); sb.Append(",").Append(y1); double x2 = pieSize * Math.Cos((pieStart + valueRatio) * Math.PI * 2), y2 = pieSize * Math.Sin((pieStart + valueRatio) * Math.PI * 2); if (valueRatio >= .5) // major arc { sb.Append(" A").Append(pieSize).Append(" ").Append(pieSize).Append(" 1 0 0 "); } else { sb.Append(" A").Append(pieSize).Append(" ").Append(pieSize).Append(" 1 1 0 "); } sb.Append(x2); sb.Append(",").Append(y2); sb.Append(" z"); pathElem = CreatePathFromXAMLAndData(pathXAML, sb); if (animate) { dataElems.Add(pathElem); defaultTransform = new TranslateTransform(); defaultTransform.X = defaultTransform.Y = -10000; pathElem.SetValue(Canvas.RenderTransformProperty, defaultTransform); double curAnimRatio = (yValues[iGroup, i]) / (pieTotal); _pieAnimAngles.Add(animAngleStart + curAnimRatio / 2); animAngleStart += curAnimRatio; } if (gradientXAML != null) { SetGradientOnElement(pathElem, gradientXAML, seriesColors[i], 0xe5); } else { SetFillOnElement(pathElem, seriesColors[i]); } pathElem.SetValue(Rectangle.StrokeProperty, new SolidColorBrush(seriesColors[i])); // centroid of the triangle used for tooltips Point centroid = new Point((x1 + x2) / 3, (y1 + y2) / 3); SetExpandosOnElement(pathElem, iGroup, i, centroid); if (DisplayToolTip) { pathElem.MouseEnter += new MouseEventHandler(ShowToolTip); pathElem.MouseLeave += new MouseEventHandler(HideToolTip); } pathElem.MouseLeftButtonUp += new MouseButtonEventHandler(ChartDataClicked); pieStart += valueRatio; pieContainer.Children.Add(pathElem); } /*for (var i = 0; i< nPies; ++i) * { * // calculate the pie gradient: * pieContainer.appendChild(pieElems[i]); * }*/ }
private void _draw3DPies( Canvas pieContainer, double quadWidth, double quadHeight, int iGroup) { ChartModel model = Model; double[,] yValues = model.YValues; string[] groupLabels = model.GroupLabels; Color[] seriesColors = model.SeriesColors; var pieSize = Math.Min(quadWidth / 2, quadHeight / 2); if (iGroup == -1) { iGroup = 0; } int nPies = yValues.GetUpperBound(1) + 1; double pieTotal = 0; for (int i = 0; i < nPies; ++i) { pieTotal += yValues[iGroup, i]; } string pathXAML = CurrentLookAndFeel.GetPiePathXAML(); Path pathElem; double pieStart = 0; List <UIElement> dataElems = null; bool animate = (AnimationDuration > 0); if (animate) { dataElems = DataElements; } double perspectiveHeight = pieSize / 4; Path[] pieElems = new Path[nPies], ringElems = new Path[nPies], edgeElems = new Path[nPies]; if (perspectiveHeight > _MAX_PERSPECTIVE_HEIGHT) { perspectiveHeight = _MAX_PERSPECTIVE_HEIGHT; } string gradientXAML = CurrentLookAndFeel.GetElementGradientXAML(); TranslateTransform defaultTransform; for (int i = 0; i < nPies; ++i) { double valueRatio = 1 - (yValues[iGroup, i]) / (pieTotal); double arcBeginX, arcBeginY, arcEndX, arcEndY; arcBeginX = pieSize * Math.Cos(pieStart * Math.PI * 2); arcBeginY = pieSize * Math.Sin(pieStart * Math.PI * 2); StringBuilder sb = new StringBuilder(); sb.Append("M0,0L").Append(arcBeginX).Append(",").Append(arcBeginY); arcEndX = pieSize * Math.Cos((pieStart + valueRatio) * Math.PI * 2); arcEndY = pieSize * Math.Sin((pieStart + valueRatio) * Math.PI * 2); if (valueRatio >= .5) { sb.Append(" A").Append(pieSize).Append(",").Append(pieSize).Append(" 1 0 0 "); } else { sb.Append(" A").Append(pieSize).Append(",").Append(pieSize).Append(" 1 1 0 "); } sb.Append(arcEndX).Append(",").Append(arcEndY); sb.Append(" z"); pathElem = CreatePathFromXAMLAndData(pathXAML, sb); if (animate) { dataElems.Add(pathElem); defaultTransform = new TranslateTransform(); defaultTransform.X = defaultTransform.Y = -10000; pathElem.SetValue(Canvas.RenderTransformProperty, defaultTransform); _pieAnimAngles.Add(pieStart + valueRatio / 2); } if (gradientXAML != null) { SetGradientOnElement(pathElem, gradientXAML, seriesColors[i], 0xe5); } else { SetFillOnElement(pathElem, seriesColors[i]); } pathElem.SetValue(Rectangle.StrokeProperty, new SolidColorBrush(seriesColors[i])); // centroid of the pie triangle Point centroid = new Point((arcBeginX + arcEndX) / 3, (arcBeginY + arcEndY) / 3); SetExpandosOnElement(pathElem, iGroup, i, centroid); if (DisplayToolTip) { pathElem.MouseEnter += new MouseEventHandler(ShowToolTip); pathElem.MouseLeave += new MouseEventHandler(HideToolTip); } pathElem.MouseLeftButtonUp += new MouseButtonEventHandler(ChartDataClicked); sb = new StringBuilder(); sb.Append("M").Append(arcBeginX).Append(",").Append(arcBeginY); if (valueRatio >= .5) // major arc { sb.Append(" A").Append(pieSize).Append(",").Append(pieSize).Append(" 1 0 0 "); } else { sb.Append(" A").Append(pieSize).Append(" ").Append(pieSize).Append(" 1 1 0 "); } sb.Append(arcEndX).Append(",").Append(arcEndY); sb.Append(" v").Append(perspectiveHeight); sb.Append(" M").Append(arcEndX).Append(",").Append(arcEndY + perspectiveHeight); if (valueRatio >= .5) // major arc { sb.Append(" A").Append(pieSize).Append(",").Append(pieSize).Append(" 1 0 1 "); } else { sb.Append(" A").Append(pieSize).Append(",").Append(pieSize).Append(" 1 1 1 "); } sb.Append(arcBeginX).Append(",").Append(arcBeginY + perspectiveHeight); sb.Append(" v").Append(-perspectiveHeight); Path pathRingElem = CreatePathFromXAMLAndData(pathXAML, sb); if (gradientXAML != null) { SetGradientOnElement(pathRingElem, gradientXAML, seriesColors[i], 0xe5); } else { SetFillOnElement(pathRingElem, seriesColors[i]); } pathRingElem.SetValue(Rectangle.StrokeProperty, new SolidColorBrush(seriesColors[i])); sb = new StringBuilder(); sb.Append("M0,0L"); sb.Append(arcBeginX).Append(",").Append(arcBeginY); sb.Append("v").Append(perspectiveHeight); sb.Append("L").Append(0).Append(",").Append(perspectiveHeight); sb.Append("z"); sb.Append("M0,0L"); sb.Append(arcEndX).Append(",").Append(arcEndY); sb.Append("v").Append(perspectiveHeight); sb.Append("L").Append(0).Append(",").Append(perspectiveHeight); sb.Append("z"); Path pathEdgeElem = CreatePathFromXAMLAndData(pathXAML, sb); if (animate) { dataElems.Add(pathRingElem); defaultTransform = new TranslateTransform(); defaultTransform.X = defaultTransform.Y = -10000; pathRingElem.SetValue(Canvas.RenderTransformProperty, defaultTransform); dataElems.Add(pathEdgeElem); defaultTransform = new TranslateTransform(); defaultTransform.X = defaultTransform.Y = -10000; pathEdgeElem.SetValue(Canvas.RenderTransformProperty, defaultTransform); } (pathEdgeElem.Data as PathGeometry).FillRule = FillRule.Nonzero; if (gradientXAML != null) { SetGradientOnElement(pathEdgeElem, gradientXAML, seriesColors[i], 0xe5); } else { SetFillOnElement(pathEdgeElem, seriesColors[i]); } pathEdgeElem.SetValue(Rectangle.StrokeProperty, new SolidColorBrush(seriesColors[i])); if (DisplayToolTip) { pathRingElem.MouseEnter += new MouseEventHandler(ShowToolTip); pathRingElem.MouseLeave += new MouseEventHandler(HideToolTip); pathEdgeElem.MouseEnter += new MouseEventHandler(ShowToolTip); pathEdgeElem.MouseLeave += new MouseEventHandler(HideToolTip); } SetExpandosOnElement(pathRingElem, iGroup, i, centroid); SetExpandosOnElement(pathEdgeElem, iGroup, i, centroid); pieStart += valueRatio; pieElems[i] = pathElem; ringElems[i] = pathRingElem; edgeElems[i] = pathEdgeElem; } UIElementCollection children = pieContainer.Children; // For the top half, edges have preference over rings double totalRatio = 0; for (int i = 0; i < nPies; ++i) { if (totalRatio <= .5) { children.Add(ringElems[i]); } totalRatio += (yValues[iGroup, i]) / (pieTotal); } totalRatio = 0; for (int i = 0; i < nPies; ++i) { if (totalRatio <= .5) { children.Add(edgeElems[i]); } totalRatio += (yValues[iGroup, i]) / (pieTotal); } // For the bottom half, rings have preference over edges totalRatio = 0; for (int i = 0; i < nPies; ++i) { if (totalRatio > .5) { children.Add(edgeElems[i]); } totalRatio += (yValues[iGroup, i]) / (pieTotal); } totalRatio = 0; for (int i = 0; i < nPies; ++i) { if (totalRatio > .5) { children.Add(ringElems[i]); } totalRatio += (yValues[iGroup, i]) / (pieTotal); } for (int i = 0; i < nPies; ++i) { children.Add(pieElems[i]); } }
private void _drawPerspectiveFunnel( Canvas fnlContainer, double quadWidth, double quadHeight, int iGroup) { ChartModel model = Model; double[,] yValues = model.YValues; string [] groupLabels = model.GroupLabels; Color [] seriesColors = model.SeriesColors; if (iGroup == -1) { iGroup = 0; } // Number of segments int nSeg = yValues.GetUpperBound(1) + 1; double total = 0; for (int i = 0; i < nSeg; ++i) { total += yValues[iGroup, i]; } List <UIElement> dataElems = DataElements; bool animate = (AnimationDuration > 0); string funnelXAML = CurrentLookAndFeel.GetFunnelPathXAML(); Path pathElem; string gradientXAML = CurrentLookAndFeel.GetElementGradientXAML(); MatrixTransform defaultTransform; double x = 0, y = 0, slope = (quadWidth / 2.0) / quadHeight, dx = quadWidth, dy, nextX, oldDx, nextY; // the ring height is 1/12 of the width double rx = dx / 2.0, ry = dx / 24.0, oldRx, oldRy; for (int i = nSeg - 1; i >= 0; --i) { double valueRatio = (yValues[iGroup, i]) / (total); StringBuilder sb = new StringBuilder(); sb.Append("M").Append(x).Append(",").Append(y); sb.Append(" A").Append(rx).Append(",").Append(ry); sb.Append(" 0 1,0 ").Append(dx).Append(",").Append(y); sb.Append(" A").Append(rx).Append(",").Append(ry); sb.Append(" 0 1,0 ").Append(x).Append(",").Append(y); oldDx = dx; oldRx = rx; oldRy = ry; dy = (quadHeight) * valueRatio; nextY = y + dy; nextX = quadWidth / 2.0 - slope * (quadHeight - (nextY)); dx = quadWidth - nextX; rx = (dx - nextX) / 2.0; ry = rx / 12.0; if (i != 0) { sb.Append("L").Append(nextX).Append(",").Append(nextY); sb.Append("A").Append(rx).Append(",").Append(ry); sb.Append(" 0 1,0 ").Append(dx).Append(",").Append(nextY); sb.Append("L").Append(oldDx).Append(",").Append(y); } else { double startTipY = (dy / 3.0 <= _MAX_FUNNEL_TIP)?y + (dy - dy / 3.0): quadHeight - _MAX_FUNNEL_TIP; nextX = quadWidth / 2.0 - slope * (quadHeight - (startTipY)); dx = quadWidth - nextX; rx = (dx - nextX) / 2.0; ry = rx / 12.0; sb.Append(" L").Append(nextX).Append(",").Append(startTipY); sb.Append(" L").Append(nextX).Append(",").Append(quadHeight); sb.Append(" A").Append(rx).Append(",").Append(ry); sb.Append(" 0 1,0 ").Append(dx).Append(",").Append(quadHeight); sb.Append(" A").Append(rx).Append(",").Append(ry); sb.Append(" 0 1,0 ").Append(nextX).Append(",").Append(quadHeight); sb.Append(" A").Append(rx).Append(",").Append(ry); sb.Append(" 0 1,0 ").Append(dx).Append(",").Append(quadHeight); sb.Append(" L").Append(dx).Append(",").Append(startTipY); sb.Append(" L").Append(oldDx).Append(",").Append(y); } pathElem = CreatePathFromXAMLAndData(funnelXAML, sb); if (animate) { dataElems.Add(pathElem); defaultTransform = new MatrixTransform(); Matrix m = new Matrix(0, 0, 0, 0, 0, 0); defaultTransform.Matrix = m; pathElem.RenderTransform = defaultTransform; } if (gradientXAML != null) { SetGradientOnElement(pathElem, gradientXAML, seriesColors[i], 0xE5); } else { SetFillOnElement(pathElem, seriesColors[i]); } (pathElem.Data as PathGeometry).FillRule = FillRule.Nonzero; pathElem.SetValue(Path.StrokeProperty, new SolidColorBrush(seriesColors[i])); pathElem.SetValue(Canvas.ZIndexProperty, i + 1); SetExpandosOnElement(pathElem, iGroup, i, new Point(nextX + (dx - nextX) / 2.0, y + (nextY - y) / 2.0)); if (DisplayToolTip) { pathElem.MouseEnter += new MouseEventHandler(ShowToolTip); pathElem.MouseLeave += new MouseEventHandler(HideToolTip); } pathElem.MouseLeftButtonUp += new MouseButtonEventHandler(ChartDataClicked); fnlContainer.Children.Add(pathElem); y = nextY; x = nextX; } }