public static Color32 GetLineGradientColor(VisualMap visualMap, Vector3 pos, GridCoord grid, Axis axis,
                                                   Axis relativedAxis, Color32 defaultColor)
        {
            double value = 0;
            double min   = 0;
            double max   = 0;

            if (visualMap.dimension == 0)
            {
                min = axis.context.minValue;
                max = axis.context.maxValue;
                if (axis.IsCategory() && axis.boundaryGap)
                {
                    float startX = grid.context.x + axis.context.scaleWidth / 2;
                    value = (min + (pos.x - startX) / (grid.context.width - axis.context.scaleWidth) * (max - min));
                    if (visualMap.IsPiecewise())
                    {
                        value = (int)value;
                    }
                }
                else
                {
                    value = min + (pos.x - grid.context.x) / grid.context.width * (max - min);
                }
            }
            else
            {
                min = relativedAxis.context.minValue;
                max = relativedAxis.context.maxValue;
                if (relativedAxis.IsCategory() && relativedAxis.boundaryGap)
                {
                    float startY = grid.context.y + relativedAxis.context.scaleWidth / 2;
                    value = (min + (pos.y - startY) / (grid.context.height - relativedAxis.context.scaleWidth) * (max - min));
                    if (visualMap.IsPiecewise())
                    {
                        value = (int)value;
                    }
                }
                else
                {
                    value = min + (pos.y - grid.context.y) / grid.context.height * (max - min);
                }
            }

            var color = visualMap.GetColor(value);

            if (ChartHelper.IsClearColor(color))
            {
                return(defaultColor);
            }
            else
            {
                if (color.a != 0)
                {
                    color.a = defaultColor.a;
                }

                return(color);
            }
        }
        public static void AutoSetLineMinMax(VisualMap visualMap, Serie serie, bool isY, Axis axis, Axis relativedAxis)
        {
            if (!IsNeedGradient(visualMap) || !visualMap.autoMinMax)
            {
                return;
            }

            double min   = 0;
            double max   = 0;
            var    xAxis = isY ? relativedAxis : axis;
            var    yAxis = isY ? axis : relativedAxis;

            if (visualMap.dimension == 0)
            {
                min = xAxis.IsCategory() ? 0 : xAxis.context.minValue;
                max = xAxis.IsCategory() ? serie.dataCount - 1 : xAxis.context.maxValue;
                SetMinMax(visualMap, min, max);
            }
            else
            {
                min = yAxis.IsCategory() ? 0 : yAxis.context.minValue;
                max = yAxis.IsCategory() ? serie.dataCount - 1 : yAxis.context.maxValue;
                SetMinMax(visualMap, min, max);
            }
        }
 /// <summary>
 /// 获得数值value在坐标轴上对应的长度
 /// </summary>
 /// <param name="grid"></param>
 /// <param name="axis"></param>
 /// <param name="scaleWidth"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public static float GetAxisValueLength(GridCoord grid, Axis axis, float scaleWidth, double value)
 {
     return(GetAxisPositionInternal(grid, axis, scaleWidth, value, false, true));
 }
        /// <summary>
        /// 调整最大最小值
        /// </summary>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        public static void AdjustMinMaxValue(Axis axis, ref double minValue, ref double maxValue, bool needFormat, int ceilRate = 0)
        {
            if (axis.type == Axis.AxisType.Log)
            {
                int minSplit = 0;
                int maxSplit = 0;
                maxValue         = ChartHelper.GetMaxLogValue(maxValue, axis.logBase, axis.logBaseE, out maxSplit);
                minValue         = ChartHelper.GetMinLogValue(minValue, axis.logBase, axis.logBaseE, out minSplit);
                axis.splitNumber = (minSplit > 0 && maxSplit > 0) ? (maxSplit + minSplit - 1) : (maxSplit + minSplit);
                return;
            }
            if (axis.type == Axis.AxisType.Time)
            {
            }
            else if (axis.minMaxType == Axis.AxisMinMaxType.Custom)
            {
                if (axis.min != 0 || axis.max != 0)
                {
                    if (axis.inverse)
                    {
                        minValue = -axis.max;
                        maxValue = -axis.min;
                    }
                    else
                    {
                        minValue = axis.min;
                        maxValue = axis.max;
                    }
                }
            }
            else
            {
                if (ceilRate == 0)
                {
                    ceilRate = axis.ceilRate;
                }
                switch (axis.minMaxType)
                {
                case Axis.AxisMinMaxType.Default:

                    if (minValue == 0 && maxValue == 0)
                    {
                    }
                    else if (minValue > 0 && maxValue > 0)
                    {
                        minValue = 0;
                        maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
                    }
                    else if (minValue < 0 && maxValue < 0)
                    {
                        minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
                        maxValue = 0;
                    }
                    else
                    {
                        minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
                        maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
                    }
                    break;

                case Axis.AxisMinMaxType.MinMax:

                    minValue = ceilRate != 0 ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
                    maxValue = ceilRate != 0 ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
                    break;
                }
            }
        }
        /// <summary>
        /// 获得分割段宽度
        /// </summary>
        /// <param name="coordinateWidth"></param>
        /// <param name="dataZoom"></param>
        /// <returns></returns>
        public static float GetScaleWidth(Axis axis, float coordinateWidth, int index, DataZoom dataZoom = null)
        {
            if (index < 0)
            {
                return(0);
            }

            int num      = GetScaleNumber(axis, coordinateWidth, dataZoom);
            int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom);

            if (num <= 0)
            {
                num = 1;
            }

            if (axis.IsTime() || axis.IsValue())
            {
                var value     = axis.GetLabelValue(index);
                var lastValue = axis.GetLabelValue(index - 1);
                return(axis.context.minMaxRange == 0 ?
                       0 :
                       (float)(coordinateWidth * (value - lastValue) / axis.context.minMaxRange));
            }
            else
            {
                var data = axis.GetDataList(dataZoom);
                if (axis.IsCategory() && data.Count > 0)
                {
                    var count = axis.boundaryGap ? data.Count : data.Count - 1;
                    int tick  = count / splitNum;
                    if (count <= 0)
                    {
                        return(0);
                    }

                    var each = coordinateWidth / count;
                    if (axis.insertDataToHead)
                    {
                        var max = axis.boundaryGap ? splitNum : splitNum - 1;
                        if (index == 1)
                        {
                            if (axis.axisTick.alignWithLabel)
                            {
                                return(each * tick);
                            }
                            else
                            {
                                return(coordinateWidth - each * tick * max);
                            }
                        }
                        else
                        {
                            if (count < splitNum)
                            {
                                return(each);
                            }
                            else
                            {
                                return(each * (count / splitNum));
                            }
                        }
                    }
                    else
                    {
                        var max = axis.boundaryGap ? num - 1 : num;
                        if (index >= max)
                        {
                            if (axis.axisTick.alignWithLabel)
                            {
                                return(each * tick);
                            }
                            else
                            {
                                return(coordinateWidth - each * tick * (index - 1));
                            }
                        }
                        else
                        {
                            if (count < splitNum)
                            {
                                return(each);
                            }
                            else
                            {
                                return(each * (count / splitNum));
                            }
                        }
                    }
                }
                else
                {
                    if (splitNum <= 0)
                    {
                        return(0);
                    }
                    else
                    {
                        return(coordinateWidth / splitNum);
                    }
                }
            }
        }
        /// <summary>
        /// 获得分割段数
        /// </summary>
        /// <param name="dataZoom"></param>
        /// <returns></returns>
        public static int GetSplitNumber(Axis axis, float coordinateWid, DataZoom dataZoom)
        {
            if (axis.type == Axis.AxisType.Value)
            {
                return(axis.context.labelValueList.Count - 1);
            }
            else if (axis.type == Axis.AxisType.Time)
            {
                return(axis.context.labelValueList.Count);
            }
            else if (axis.type == Axis.AxisType.Log)
            {
                return(axis.splitNumber > 0 ? axis.splitNumber : 4);
            }
            else if (axis.type == Axis.AxisType.Category)
            {
                int dataCount = axis.GetDataList(dataZoom).Count;
                if (!axis.boundaryGap)
                {
                    dataCount -= 1;
                }
                if (dataCount <= 0)
                {
                    dataCount = 1;
                }

                if (axis.splitNumber <= 0)
                {
                    if (dataCount <= 10)
                    {
                        return(dataCount);
                    }
                    else
                    {
                        for (int i = 4; i < 6; i++)
                        {
                            if (dataCount % i == 0)
                            {
                                return(i);
                            }
                        }
                        return(5);
                    }
                }
                else
                {
                    if (axis.splitNumber <= 0 || axis.splitNumber > dataCount)
                    {
                        return(dataCount);
                    }
                    if (dataCount >= axis.splitNumber * 2)
                    {
                        return(axis.splitNumber);
                    }
                    else
                    {
                        return(dataCount);
                    }
                }
            }
            return(0);
        }
        /// <summary>
        /// 获得标签显示的名称
        /// </summary>
        /// <param name="index"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <param name="dataZoom"></param>
        /// <returns></returns>
        public static string GetLabelName(Axis axis, float coordinateWidth, int index, double minValue, double maxValue,
                                          DataZoom dataZoom, bool forcePercent)
        {
            int split = GetSplitNumber(axis, coordinateWidth, dataZoom);

            if (axis.type == Axis.AxisType.Value)
            {
                if (minValue == 0 && maxValue == 0)
                {
                    maxValue = axis.max != 0 ? axis.max : 1;
                }
                double value = 0;
                if (forcePercent)
                {
                    maxValue = 100;
                }

                value = axis.GetLabelValue(index);
                if (axis.inverse)
                {
                    value    = -value;
                    minValue = -minValue;
                    maxValue = -maxValue;
                }
                if (forcePercent)
                {
                    return(string.Format("{0}%", (int)value));
                }
                else
                {
                    return(axis.axisLabel.GetFormatterContent(index, value, minValue, maxValue));
                }
            }
            else if (axis.type == Axis.AxisType.Log)
            {
                double value = axis.logBaseE ?
                               System.Math.Exp(axis.GetLogMinIndex() + index) :
                               System.Math.Pow(axis.logBase, axis.GetLogMinIndex() + index);
                if (axis.inverse)
                {
                    value    = -value;
                    minValue = -minValue;
                    maxValue = -maxValue;
                }
                return(axis.axisLabel.GetFormatterContent(index, value, minValue, maxValue, true));
            }
            else if (axis.type == Axis.AxisType.Time)
            {
                if (minValue == 0 && maxValue == 0)
                {
                    return(string.Empty);
                }
                if (index > axis.context.labelValueList.Count - 1)
                {
                    return(string.Empty);
                }

                var value = axis.GetLabelValue(index);
                return(axis.axisLabel.GetFormatterDateTime(index, value, minValue, maxValue));
            }
            var showData  = axis.GetDataList(dataZoom);
            int dataCount = showData.Count;

            if (dataCount <= 0)
            {
                return("");
            }
            int rate = axis.boundaryGap ? (dataCount / split) : (dataCount - 1) / split;

            if (rate == 0)
            {
                rate = 1;
            }
            if (axis.insertDataToHead)
            {
                if (index > 0)
                {
                    var residue  = (dataCount - 1) - split * rate;
                    var newIndex = residue + (index - 1) * rate;
                    if (newIndex < 0)
                    {
                        newIndex = 0;
                    }
                    return(axis.axisLabel.GetFormatterContent(newIndex, showData[newIndex]));
                }
                else
                {
                    if (axis.boundaryGap && coordinateWidth / dataCount > 5)
                    {
                        return(string.Empty);
                    }
                    else
                    {
                        return(axis.axisLabel.GetFormatterContent(0, showData[0]));
                    }
                }
            }
            else
            {
                int newIndex = index * rate;
                if (newIndex < dataCount)
                {
                    return(axis.axisLabel.GetFormatterContent(newIndex, showData[newIndex]));
                }
                else
                {
                    if (axis.boundaryGap && coordinateWidth / dataCount > 5)
                    {
                        return(string.Empty);
                    }
                    else
                    {
                        return(axis.axisLabel.GetFormatterContent(dataCount - 1, showData[dataCount - 1]));
                    }
                }
            }
        }