Exemplo n.º 1
0
        /// <summary>
        /// Calculate funnelSliceParms information
        /// </summary>
        /// <param name="isStreamLine">Whether its a streamline funnel chart</param>
        /// <param name="dataSeries">DataSeries reference</param>
        /// <param name="dataPoints">List of sorted reference(If required)</param>
        /// <param name="plotHeight">Total height of the plot canvas</param>
        /// <param name="plotWidth">Total width of the plot canvas</param>
        /// <param name="minPointHeight">Min height of a funnel slice</param>
        /// <param name="is3D">Whether chart is a 3D chart</param>
        /// <param name="yScale">YScale of the chart</param>
        /// <param name="gapRatio">Gap between two data points while a particular datapoint is Exploded</param>
        /// <param name="isSameSlantAngle">Whether the same slant angle to be used while drawing each slice</param>
        /// <param name="bottomRadius">Bottom most raduis of a funnel</param>
        /// <returns>FunnelSliceParms[]</returns>
        private static FunnelSliceParms[] CalculateFunnelSliceParmsInfo(Boolean isStreamLine, DataSeries dataSeries, List<DataPoint> dataPoints, Double plotHeight, Double plotWidth, Double minPointHeight, Boolean is3D, Double yScale, Double gapRatio, Boolean isSameSlantAngle, Double bottomRadius)
        {
            // Initialize funnel Slices parameters
            FunnelSliceParms[] funnelSlicesParms;

            // Actual funnel height
            // For 3d funnel height will be reduced to maintain yScale
            Double funnelHeight;

            if (dataSeries.Exploded)
            {
                gapRatio = 0.02;

                // Single gap height
                _singleGap = gapRatio * plotHeight;

                _totalGap = _singleGap * ((isStreamLine) ? dataPoints.Count : (dataPoints.Count + 1));
            }
            else
            {
                // Single gap height
                _singleGap = gapRatio * plotHeight;

                _totalGap = _singleGap * 2;
            }

            // Actual funnel height
            // For 3d funnel height will be reduced to maintain yScale
            funnelHeight = plotHeight - _totalGap - (is3D ? yScale / 2 : 0);

            if (!isStreamLine)
            {
                #region Sectional Funnel

                // Initialization of funnelSliceParms
                funnelSlicesParms = new FunnelSliceParms[dataPoints.Count];

                // Calculate sum of values
                Double sum = (from dp in dataPoints select dp.YValue).Sum();

                // Min YValue
                Double min = (from dp in dataPoints select dp.YValue).Min();

                // Funnel angle
                Double theta = Math.Atan((plotWidth / 2 - bottomRadius) / funnelHeight);

                // Height of the funnel drawn considering bottom radius
                funnelHeight -= Math.Tan(theta) / ((bottomRadius == 0) ? 1 : bottomRadius);

                // Creating prams for each funnel slice
                for (Int32 index = 0; index < dataPoints.Count; index++)
                {
                    funnelSlicesParms[index] = new FunnelSliceParms() { DataPoint = dataPoints[index], TopAngle = Math.PI / 2 - theta, BottomAngle = Math.PI / 2 + theta };

                    funnelSlicesParms[index].Height = funnelHeight * (dataPoints[index].YValue / sum);
                    funnelSlicesParms[index].TopRadius = index == 0 ? plotWidth / 2 : funnelSlicesParms[index - 1].BottomRadius;
                    funnelSlicesParms[index].BottomRadius = funnelSlicesParms[index].TopRadius - funnelSlicesParms[index].Height * Math.Tan(theta);
                    /*
                    // Set topgap and bottom gap
                    if (index == 0)
                        funnelSlicesParms[index].TopGap = singleGap + ((index == 0 && is3D) ? yScale / 2 : 0);
                    else if ((Boolean)funnelSlicesParms[index].DataPoint.Exploded)
                        funnelSlicesParms[index].TopGap = singleGap + ((index == 0 && is3D) ? yScale / 2 : 0);

                    if (index == dataPoints.Count - 1)
                        funnelSlicesParms[index].BottomGap = singleGap;
                    else if ((Boolean)funnelSlicesParms[index].DataPoint.Exploded)
                        funnelSlicesParms[index].BottomGap = singleGap;*/

                    //--------------
                    funnelSlicesParms[index].TopGap = ((index == 0 && is3D) ? yScale / 2 : 0);
                    //--------------

                }

                if (!Double.IsNaN(minPointHeight))
                {
                    Boolean isFixedSize = false;    // Whether to fix height of all slice
                    Double fixedSliceHeight = 0;

                    Double totalSumOfHeight = (from funnelSlice in funnelSlicesParms select funnelSlice.Height).Sum();
                    fixedSliceHeight = totalSumOfHeight / funnelSlicesParms.Length;

                    // Calculate minPointHeight in terms of pixel value
                    minPointHeight = (minPointHeight / 100) * funnelHeight;

                    // Funnel slices where height is less than the minPointHeight
                    List<FunnelSliceParms> fixedHeightFunnelSlices = (from funnelSlice in funnelSlicesParms where funnelSlice.Height < minPointHeight select funnelSlice).ToList();

                    List<FunnelSliceParms> variableHeightFunnelSlices = (from funnelSlice in funnelSlicesParms
                                                                         where !(from slice in fixedHeightFunnelSlices select slice).Contains(funnelSlice)
                                                                         select funnelSlice).ToList();

                    if (minPointHeight > fixedSliceHeight || fixedHeightFunnelSlices.Count == funnelSlicesParms.Count())
                    {
                        isFixedSize = true;
                    }

                    Double sumOfHeightOfSlice2BeFixed = (from funnelSlice in fixedHeightFunnelSlices select funnelSlice.Height).Sum();
                    Double sumOfVariableHeightSlices = (from funnelSlice in variableHeightFunnelSlices select funnelSlice.Height).Sum();

                    Double totalHeight2Reduce = minPointHeight * fixedHeightFunnelSlices.Count() - sumOfHeightOfSlice2BeFixed;

                    // Creating prams for each funnel slice
                    for (Int32 index = 0; index < dataPoints.Count; index++)
                    {
                        if (isFixedSize)
                        {
                            funnelSlicesParms[index].Height = fixedSliceHeight;
                        }
                        else
                        {
                            if (funnelSlicesParms[index].Height < minPointHeight)
                                funnelSlicesParms[index].Height = minPointHeight;
                            else
                                funnelSlicesParms[index].Height -= totalHeight2Reduce * (funnelSlicesParms[index].Height / sumOfVariableHeightSlices);
                        }

                        funnelSlicesParms[index].TopRadius = index == 0 ? plotWidth / 2 : funnelSlicesParms[index - 1].BottomRadius;
                        funnelSlicesParms[index].BottomRadius = funnelSlicesParms[index].TopRadius - funnelSlicesParms[index].Height * Math.Tan(theta);

                        // Set topgap and bottom gap
                        /*if (index == 0 || (Boolean)funnelSlicesParms[index].DataPoint.Exploded)
                            funnelSlicesParms[index].TopGap = _singleGap + ((index == 0 && is3D) ? yScale / 2 : 0);
                        
                        if(index == dataPoints.Count -1 || (Boolean) funnelSlicesParms[index].DataPoint.Exploded)
                            funnelSlicesParms[index].BottomGap = _singleGap;
                         */
                    }
                }

                #endregion
            }
            else
            {
                #region StreamLineFunnel

                funnelHeight -= _streamLineParentTitleSize.Height;

                // Initialization of iOValuePairs
                IOValuePair[] iOValuePairs = new IOValuePair[dataPoints.Count];

                for (Int32 index = 0; index < dataPoints.Count; index++)
                {
                    iOValuePairs[index] = new IOValuePair();
                    iOValuePairs[index].InputValue = ((index == 0) ? Double.NaN : dataPoints[index - 1].YValue);
                    iOValuePairs[index].OutPutValue = dataPoints[index].YValue;
                }

                // Initialization of funnelSliceParms
                funnelSlicesParms = new FunnelSliceParms[dataPoints.Count - 1];

                // Creating prams for each funnel slice
                Int32 slicesIndex;

                for (Int32 index = 1; index < iOValuePairs.Count(); index++)
                {
                    slicesIndex = index - 1;

                    funnelSlicesParms[slicesIndex] = new FunnelSliceParms() { DataPoint = dataPoints[index] };

                    funnelSlicesParms[slicesIndex].Height = (((iOValuePairs[index].InputValue - iOValuePairs[index].OutPutValue) / iOValuePairs[0].OutPutValue) * funnelHeight);
                    funnelSlicesParms[slicesIndex].TopRadius = slicesIndex == 0 ? plotWidth / 2 : funnelSlicesParms[slicesIndex - 1].BottomRadius;

                    if (!isSameSlantAngle)
                        funnelSlicesParms[slicesIndex].BottomRadius = (funnelSlicesParms[slicesIndex].TopRadius * Math.Sqrt(iOValuePairs[index].OutPutValue / iOValuePairs[index].InputValue));
                    else
                        funnelSlicesParms[slicesIndex].BottomRadius = (funnelSlicesParms[slicesIndex].TopRadius * (iOValuePairs[index].OutPutValue / iOValuePairs[index].InputValue));

                    Double theta = Math.Atan((funnelSlicesParms[slicesIndex].TopRadius - funnelSlicesParms[slicesIndex].BottomRadius) / funnelSlicesParms[slicesIndex].Height);
                    funnelSlicesParms[slicesIndex].TopAngle = Math.PI / 2 - theta;
                    funnelSlicesParms[slicesIndex].BottomAngle = Math.PI / 2 + theta;

                    /*
                    // Set top and bottom gap
                    if(index == 1 || (Boolean)funnelSlicesParms[slicesIndex].DataPoint.Exploded)
                        funnelSlicesParms[slicesIndex].TopGap = singleGap + ((slicesIndex == 0 && is3D) ? yScale / 2 : 0);

                    if (index == iOValuePairs.Count() - 1 || (Boolean)funnelSlicesParms[slicesIndex].DataPoint.Exploded)
                        funnelSlicesParms[slicesIndex].BottomGap = singleGap;
                    */

                    FixTopAndBottomRadiusForStreamLineFunnel(ref funnelSlicesParms[slicesIndex]);
                }

                // Enlarge Funnel Height-----------

                Double totalSumOfHeight = (from funnelSlice in funnelSlicesParms select funnelSlice.Height).Sum();

                if (totalSumOfHeight < funnelHeight)
                {
                    for (Int32 index = 1; index < iOValuePairs.Count(); index++)
                    {
                        slicesIndex = index - 1;

                        //funnelSlicesParms[slicesIndex] = new FunnelSliceParms() { DataPoint = dataPoints[index] };

                        funnelSlicesParms[slicesIndex].Height += (funnelHeight - totalSumOfHeight) * (funnelSlicesParms[slicesIndex].Height / totalSumOfHeight);

                        funnelSlicesParms[slicesIndex].TopRadius = slicesIndex == 0 ? plotWidth / 2 : funnelSlicesParms[slicesIndex - 1].BottomRadius;

                        if (!isSameSlantAngle)
                            funnelSlicesParms[slicesIndex].BottomRadius = Math.Round(funnelSlicesParms[slicesIndex].TopRadius * Math.Sqrt(iOValuePairs[index].OutPutValue / iOValuePairs[index].InputValue));
                        else
                            funnelSlicesParms[slicesIndex].BottomRadius = Math.Round(funnelSlicesParms[slicesIndex].TopRadius * (iOValuePairs[index].OutPutValue / iOValuePairs[index].InputValue));

                        Double theta = Math.Atan((funnelSlicesParms[slicesIndex].TopRadius - funnelSlicesParms[slicesIndex].BottomRadius) / funnelSlicesParms[slicesIndex].Height);
                        funnelSlicesParms[slicesIndex].TopAngle = Math.PI / 2 - theta;
                        funnelSlicesParms[slicesIndex].BottomAngle = Math.PI / 2 + theta;

                        /*
                        // Set top and bottom gap
                        if(index == 1 || (Boolean)funnelSlicesParms[slicesIndex].DataPoint.Exploded)
                            funnelSlicesParms[slicesIndex].TopGap = singleGap + ((slicesIndex == 0 && is3D) ? yScale / 2 : 0);

                        if (index == iOValuePairs.Count() - 1 || (Boolean)funnelSlicesParms[slicesIndex].DataPoint.Exploded)
                            funnelSlicesParms[slicesIndex].BottomGap = singleGap;
                        */

                        FixTopAndBottomRadiusForStreamLineFunnel(ref funnelSlicesParms[slicesIndex]);
                    }
                }

                // End Enlarge funnel Height-------


                if (!Double.IsNaN(minPointHeight))
                {
                    Boolean isFixedSize = false;    // Whether to fix height of all slice
                    Double fixedSliceHeight = 0;
                    Double funnelActualHeight = funnelHeight - _streamLineParentTitleSize.Height;

                    fixedSliceHeight = funnelActualHeight / funnelSlicesParms.Length;

                    // Calculate minPointHeight in terms of pixel value
                    minPointHeight = (minPointHeight / 100) * funnelHeight;

                    // Funnel slices where height is less than the minPointHeight
                    var fixedHeightFunnelSlices = (from funnelSlice in funnelSlicesParms where funnelSlice.Height < minPointHeight select funnelSlice);

                    var variableHeightFunnelSlices = (from funnelSlice in funnelSlicesParms
                                                      where !(from slice in fixedHeightFunnelSlices select slice).Contains(funnelSlice)
                                                      select funnelSlice);

                    if (minPointHeight > fixedSliceHeight || fixedHeightFunnelSlices.Count() == funnelSlicesParms.Count())
                    {
                        isFixedSize = true;
                    }

                    //Double totalSumOfHeight = (from funnelSlice in funnelSlicesParms select funnelSlice.Height).Sum();
                    Double sumOfHeightOfSlice2BeFixed = (from funnelSlice in fixedHeightFunnelSlices select funnelSlice.Height).Sum();
                    Double sumOfVariableHeightSlices = (from funnelSlice in variableHeightFunnelSlices select funnelSlice.Height).Sum();

                    Double totalHeight2Reduce = minPointHeight * fixedHeightFunnelSlices.Count() - sumOfHeightOfSlice2BeFixed;

                    for (Int32 index = 1; index < iOValuePairs.Count(); index++)
                    {
                        slicesIndex = index - 1;

                        if (isFixedSize)
                        {
                            funnelSlicesParms[slicesIndex].Height = fixedSliceHeight;
                        }
                        else
                        {
                            if (funnelSlicesParms[slicesIndex].Height < minPointHeight)
                                funnelSlicesParms[slicesIndex].Height = minPointHeight;
                            else
                                funnelSlicesParms[slicesIndex].Height -= totalHeight2Reduce * (funnelSlicesParms[slicesIndex].Height / sumOfVariableHeightSlices);
                        }

                        funnelSlicesParms[slicesIndex].TopRadius = slicesIndex == 0 ? plotWidth / 2 : funnelSlicesParms[slicesIndex - 1].BottomRadius;

                        if (!isSameSlantAngle)
                            funnelSlicesParms[slicesIndex].BottomRadius = Math.Round(funnelSlicesParms[slicesIndex].TopRadius * Math.Sqrt(iOValuePairs[index].OutPutValue / iOValuePairs[index].InputValue));
                        else
                            funnelSlicesParms[slicesIndex].BottomRadius = Math.Round(funnelSlicesParms[slicesIndex].TopRadius * (iOValuePairs[index].OutPutValue / iOValuePairs[index].InputValue));

                        // Set top and bottom gap
                        /*if(index == 1 || (Boolean)funnelSlicesParms[slicesIndex].DataPoint.Exploded)
                            funnelSlicesParms[slicesIndex].TopGap = _singleGap + ((slicesIndex == 0 && is3D) ? yScale / 2 : 0);
                        
                        if(index == iOValuePairs.Count() -1 || (Boolean)funnelSlicesParms[slicesIndex].DataPoint.Exploded)
                            funnelSlicesParms[slicesIndex].BottomGap = _singleGap;
                        */

                        // Calculate funnel angle
                        // funnelSlicesParms[slicesIndex].TopAngle = Math.PI / 2 - Math.Atan((funnelSlicesParms[slicesIndex].TopRadius - funnelSlicesParms[slicesIndex].BottomRadius) / funnelSlicesParms[slicesIndex].Height);

                        FixTopAndBottomRadiusForStreamLineFunnel(ref funnelSlicesParms[slicesIndex]);

                        Double theta = Math.Atan((funnelSlicesParms[slicesIndex].TopRadius - funnelSlicesParms[slicesIndex].BottomRadius) / funnelSlicesParms[slicesIndex].Height);
                        funnelSlicesParms[slicesIndex].TopAngle = Math.PI / 2 - theta;
                        funnelSlicesParms[slicesIndex].BottomAngle = Math.PI / 2 + theta;
                    }
                }
            }

                #endregion

            return funnelSlicesParms;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Calculates Exploded DataPoint Positions
        /// </summary>
        /// <param name="funnelSlices"></param>
        private static void CalcutateExplodedPosition(ref FunnelSliceParms[] funnelSlices, Boolean isStreamLine, Double yScale, DataSeries dataSeries)
        {
            Int32 sliceCount = funnelSlices.Count();
            Int32 index = 0;

            if (funnelSlices[0].DataPoint.Parent.Exploded)
            {
                if (!funnelSlices[0].DataPoint.Chart.IsInDesignMode)
                {
                    Int32 midIndex = sliceCount / 2;
                    Double beginTime = 0.4;

                    if ((dataSeries.Chart as Chart).ChartArea._isFirstTimeRender)
                        beginTime = 1;

                    for (index = midIndex; index >= 0; index--)
                    {
                        if (index < 0)
                            break;

                        Double yPosition = funnelSlices[index].Top - (midIndex - index) * _singleGap;// -yScale / 2;
                        dataSeries.Storyboard = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, dataSeries.Storyboard, funnelSlices[index].DataPoint.Faces.Visual as Panel, yPosition, beginTime);
                    }

                    for (index = midIndex + 1; index < sliceCount; index++)
                    {
                        Double yPosition = funnelSlices[index].Top + (index - midIndex) * _singleGap;// -yScale / 2;
                        dataSeries.Storyboard = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, dataSeries.Storyboard, funnelSlices[index].DataPoint.Faces.Visual as Panel, yPosition, beginTime);
                    }

                    if (dataSeries.Chart != null && !(dataSeries.Chart as Chart).ChartArea._isFirstTimeRender)
#if WPF
                        dataSeries.Storyboard.Begin(dataSeries.Chart._rootElement, true);
#else
                        dataSeries.Storyboard.Begin();
#endif

                }
            }
            else
            {
                Storyboard unExplodeStoryBoard = new Storyboard();

                for (; index < sliceCount; index++)
                {
                    funnelSlices[index].ExplodedPoints = new List<Point>();
                    funnelSlices[index].DataPoint.ExplodeAnimation = new Storyboard();
                    // For top slice
                    if (index == 0)
                    {
                        funnelSlices[index].ExplodedPoints.Add(new Point(0, funnelSlices[index].Top - _singleGap / 2));

                        funnelSlices[index].DataPoint.ExplodeAnimation = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, funnelSlices[index].DataPoint.ExplodeAnimation, funnelSlices[index].DataPoint.Faces.Visual as Panel, (funnelSlices[index].Top - _singleGap / 2), 0);
                        //unExplodeStoryBoard = CreateExplodingAnimation(unExplodeStoryBoard, funnelSlices[index].DataPoint.Faces.Visual as Panel, funnelSlices[index].Top);

                        for (Int32 i = 1; i < funnelSlices.Length; i++)
                        {
                            funnelSlices[index].ExplodedPoints.Add(new Point(0, funnelSlices[i].Top + _singleGap / 2));
                            funnelSlices[index].DataPoint.ExplodeAnimation = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, funnelSlices[index].DataPoint.ExplodeAnimation, funnelSlices[i].DataPoint.Faces.Visual as Panel, (funnelSlices[i].Top + _singleGap / 2), 0);
                            //unExplodeStoryBoard = CreateExplodingAnimation(unExplodeStoryBoard, funnelSlices[i].DataPoint.Faces.Visual as Panel, funnelSlices[i].Top);
                        }

                    }
                    // For bottom slice
                    else if (index == funnelSlices.Length - 1)
                    {
                        Int32 i = 0;

                        for (; i < index; i++)
                        {
                            funnelSlices[index].ExplodedPoints.Add(new Point(0, funnelSlices[i].Top - _singleGap / 2 + _singleGap / 6));
                            funnelSlices[index].DataPoint.ExplodeAnimation = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, funnelSlices[index].DataPoint.ExplodeAnimation, funnelSlices[i].DataPoint.Faces.Visual as Panel, (funnelSlices[i].Top - _singleGap / 2 + _singleGap / 6), 0);
                        }

                        funnelSlices[index].ExplodedPoints.Add(new Point(0, funnelSlices[i].Top + _singleGap / 2 + _singleGap / 6));
                        funnelSlices[index].DataPoint.ExplodeAnimation = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, funnelSlices[i].DataPoint.ExplodeAnimation, funnelSlices[i].DataPoint.Faces.Visual as Panel, (funnelSlices[i].Top + _singleGap / 2 + _singleGap / 6), 0);
                    }
                    // For other slice
                    else
                    {
                        Int32 i;

                        for (i = 0; i < index; i++)
                        {
                            funnelSlices[index].ExplodedPoints.Add(new Point(0, funnelSlices[i].Top - _singleGap / 2));
                            funnelSlices[index].DataPoint.ExplodeAnimation = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, funnelSlices[index].DataPoint.ExplodeAnimation, funnelSlices[i].DataPoint.Faces.Visual as Panel, (funnelSlices[i].Top - _singleGap / 2), 0);
                        }

                        funnelSlices[index].ExplodedPoints.Add(new Point(0, funnelSlices[i].Top));
                        funnelSlices[index].DataPoint.ExplodeAnimation = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, funnelSlices[index].DataPoint.ExplodeAnimation, funnelSlices[index].DataPoint.Faces.Visual as Panel, funnelSlices[index].Top, 0);

                        for (++i; i < funnelSlices.Length; i++)
                        {
                            funnelSlices[index].ExplodedPoints.Add(new Point(0, funnelSlices[i].Top + _singleGap / 2));
                            funnelSlices[index].DataPoint.ExplodeAnimation = CreateExplodingAnimation(dataSeries, funnelSlices[index].DataPoint, funnelSlices[index].DataPoint.ExplodeAnimation, funnelSlices[i].DataPoint.Faces.Visual as Panel, (funnelSlices[i].Top + _singleGap / 2), 0);
                        }
                    }
                }
            }
        }