Vector3 AlignTextPosition(AlignedItemLabels labels, PyramidObject obj, IPyramidGenerator generator, float height)
        {
            Vector3 position = new Vector3(labels.Location.Breadth, labels.Seperation, labels.Location.Depth);

            position.y += height;
            position    = generator.GetTextPosition(justification, labels.Alignment == ChartLabelAlignment.Base);
            return(position);
        }
        private void GeneratePyramid(bool update)
        {
            if (update == false)
            {
                ClearChart();
            }
            else
            {
                EnsureTextController();
            }
            if (((IInternalPyramidData)Data).InternalDataSource == null)
            {
                return;
            }

            double[,] data = ((IInternalPyramidData)Data).InternalDataSource.getRawData();
            int rowCount    = data.GetLength(0);
            int columnCount = data.GetLength(1);

            if (rowCount != 1) // row count for pie must be 1
            {
                return;
            }

            double total = 0.0;

            for (int i = 0; i < columnCount; ++i)
            {
                double val = Math.Max(data[0, i], 0);
                total += val;
            }

            var rectTrans = GetComponent <RectTransform>();

            totalHeight = rectTrans.rect.height;
            totalWidth  = rectTrans.rect.width;

            float baseX1            = 0;
            float baseX2            = totalWidth;
            float accumilatedHeight = 0;
            float?firstCenterHeight = null;
            float acummilatedWeight = 0;

            for (int i = 0; i < columnCount; ++i)
            {
                object userData     = ((IInternalPyramidData)Data).InternalDataSource.Columns[i].UserData;
                var    categoryData = ((PyramidData.CategoryData)userData);

                string name   = ((IInternalPyramidData)Data).InternalDataSource.Columns[i].Name;
                double amount = Math.Max(data[0, i], 0);
                if (amount == 0f)
                {
                    continue;
                }

                float weight       = (float)(amount / total);
                float actualHeight = totalHeight * weight;

                float slopeRight = categoryData.RightSlope;
                float slopeLeft  = categoryData.LeftSlope;
                float atan;
                switch (slope)
                {
                case SlopeType.Center:
                    atan       = -Mathf.Atan2(totalHeight, totalWidth * 0.5f) * Mathf.Rad2Deg + 90;
                    slopeRight = atan;
                    slopeLeft  = atan;
                    break;

                case SlopeType.Left:
                    atan       = -Mathf.Atan2(totalHeight, totalWidth) * Mathf.Rad2Deg + 90;
                    slopeLeft  = 0;
                    slopeRight = atan;
                    break;

                case SlopeType.Right:
                    atan       = -Mathf.Atan2(totalHeight, totalWidth) * Mathf.Rad2Deg + 90;
                    slopeLeft  = atan;
                    slopeRight = 0;
                    break;

                default:
                    break;
                }
                GameObject        pyramidObject     = null;
                GameObject        pyramidBackObject = null;
                IPyramidGenerator generator         = null;
                IPyramidGenerator backgenerator     = null;
                PyramidObject     dataObject;
                float             centerHeight    = actualHeight * 0.5f + accumilatedHeight;
                float             unblendedHeight = centerHeight;
                if (firstCenterHeight.HasValue == false)
                {
                    firstCenterHeight = centerHeight;
                }
                centerHeight = Mathf.Lerp(firstCenterHeight.Value, centerHeight, categoryData.PositionBlend);

                if (mPyramids.TryGetValue(name, out dataObject))
                {
                    pyramidBackObject = dataObject.backObject;
                    pyramidObject     = dataObject.pyramidObject;
                    backgenerator     = dataObject.BackGenerator;
                    generator         = dataObject.Generator;
                    generator.SetParams(baseX1, baseX2, totalWidth, slopeLeft, slopeRight, actualHeight, inset, 0f, 1f);
                    if (backgenerator != null)
                    {
                        backgenerator.SetParams(baseX1, baseX2, totalWidth, slopeLeft, slopeRight, actualHeight, 0f, acummilatedWeight, acummilatedWeight + weight);
                    }
                    if (dataObject.ItemLabel)
                    {
                        Vector3 labelPos = AlignTextPosition(mItemLabels, dataObject, generator, centerHeight);
                        dataObject.ItemLabel.transform.localPosition = labelPos;
                        ChartCommon.UpdateTextParams(dataObject.ItemLabel.UIText, categoryData.Title);
                    }
                }
                else
                {
                    dataObject = new PyramidObject();

                    if (backMaterial != null)
                    {
                        var backGenerator = PreparePyramidObject(out pyramidBackObject);
                        backGenerator.SetParams(baseX1, baseX2, totalWidth, slopeLeft, slopeRight, actualHeight, 0f, acummilatedWeight, acummilatedWeight + weight);
                        dataObject.backObject    = pyramidBackObject;
                        dataObject.BackGenerator = backGenerator;
                        ChartCommon.HideObject(pyramidBackObject, hideHierarchy);
                        pyramidBackObject.transform.SetParent(transform, false);
                        ChartCommon.EnsureComponent <ChartItem>(pyramidBackObject);
                        ChartMaterialController backcontrol = ChartCommon.EnsureComponent <ChartMaterialController>(pyramidBackObject);
                        backcontrol.Materials = new ChartDynamicMaterial(backMaterial);
                        foreach (var itemEffect  in pyramidBackObject.GetComponents <ChartItemEffect>())
                        {
                            ChartCommon.SafeDestroy(itemEffect);
                        }
                        ChartCommon.SafeDestroy(backGenerator.ContainerObject);
                    }

                    generator = PreparePyramidObject(out pyramidObject);
                    generator.SetParams(baseX1, baseX2, totalWidth, slopeLeft, slopeRight, actualHeight, inset, 0f, 1f);
                    ChartCommon.HideObject(pyramidObject, hideHierarchy);
                    pyramidObject.transform.SetParent(transform, false);
                    ChartCommon.EnsureComponent <ChartItem>(pyramidObject);



                    ChartMaterialController control = ChartCommon.EnsureComponent <ChartMaterialController>(pyramidObject);
                    control.Materials = Data.GetMaterial(name);
                    control.Refresh();


                    dataObject.Generator     = generator;
                    dataObject.category      = name;
                    dataObject.pyramidObject = pyramidObject;
                    mPyramids.Add(name, dataObject);

                    CharItemEffectController effect = ChartCommon.EnsureComponent <CharItemEffectController>(pyramidObject);
                    effect.WorkOnParent = false;
                    effect.InitialScale = false;

                    ChartItemEvents[] events = pyramidObject.GetComponentsInChildren <ChartItemEvents>();
                    for (int j = 0; j < events.Length; ++j)
                    {
                        if (events[j] == null)
                        {
                            continue;
                        }
                        InternalItemEvents comp = (InternalItemEvents)events[j];
                        comp.Parent   = this;
                        comp.UserData = dataObject;
                    }


                    if (mItemLabels != null)
                    {
                        Vector3       labelPos  = AlignTextPosition(mItemLabels, dataObject, generator, 0f);
                        float         angle     = justification == JustificationType.LeftAligned ? -180f : 180f;
                        BillboardText billboard = ChartCommon.CreateBillboardText(null, mItemLabels.TextPrefab, dataObject.pyramidObject.transform, categoryData.Title, labelPos.x, labelPos.y, labelPos.z, angle, null, hideHierarchy, mItemLabels.FontSize, mItemLabels.FontSharpness);
                        dataObject.ItemLabel = billboard;
                        dataObject.ItemLabel.transform.localPosition = labelPos;
                        TextController.AddText(billboard);
                    }
                }

                dataObject.Text  = categoryData.Text;
                dataObject.Title = categoryData.Title;

                if (IsCanvas)
                {
                    if (pyramidObject != null)
                    {
                        Vector2 actualPosition = new Vector2(0.5f, centerHeight) + categoryData.Shift;
                        actualPosition = new Vector2(actualPosition.x, actualPosition.y / TotalHeight);
                        var objectRect = pyramidObject.GetComponent <RectTransform>();
                        objectRect.pivot            = new Vector2(0.5f, 0.5f);
                        objectRect.anchorMin        = actualPosition;
                        objectRect.anchorMax        = actualPosition;
                        objectRect.anchoredPosition = new Vector2();
                        objectRect.sizeDelta        = new Vector2(totalWidth, actualHeight);
                    }
                    if (pyramidBackObject != null)
                    {
                        Vector2 actualPosition = new Vector2(0.5f, unblendedHeight);
                        actualPosition = new Vector2(actualPosition.x, actualPosition.y / TotalHeight);
                        var objectRect = pyramidBackObject.GetComponent <RectTransform>();
                        objectRect.pivot            = new Vector2(0f, 0f);
                        objectRect.anchorMin        = actualPosition;
                        objectRect.anchorMax        = actualPosition;
                        objectRect.anchoredPosition = new Vector2();
                    }
                }
                accumilatedHeight += actualHeight;
                acummilatedWeight += weight;
                if (backgenerator != null)
                {
                    backgenerator.Generate();
                }
                generator.Generate();
                generator.GetUpperBase(out baseX1, out baseX2);
                generator.ApplyInfo(categoryData.Title, categoryData.Text, categoryData.Image, categoryData.Scale);
                generator.SetAlpha(categoryData.Alpha);
            }
        }