Aimbot-ParallelEnv/Assets/XCharts/Runtime/Component/Axis/AxisHelper.cs
Koha9 6bc1456e4b Fist Sub
based on aimbot multi seane
2022-10-26 04:07:39 +09:00

561 lines
21 KiB
C#

using UnityEngine;
namespace XCharts.Runtime
{
public static class AxisHelper
{
/// <summary>
/// 包含箭头偏移的轴线长度
/// </summary>
/// <param name="axis"></param>
/// <returns></returns>
public static float GetAxisLineArrowOffset(Axis axis)
{
if (axis.axisLine.show && axis.axisLine.showArrow && axis.axisLine.arrow.offset > 0)
{
return axis.axisLine.arrow.offset;
}
return 0;
}
/// <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="coordinateWidth"></param>
/// <param name="dataZoom"></param>
/// <returns></returns>
public static float GetDataWidth(Axis axis, float coordinateWidth, int dataCount, DataZoom dataZoom)
{
if (dataCount < 1)
dataCount = 1;
if (axis.IsValue())
return dataCount > 1 ? coordinateWidth / (dataCount - 1) : coordinateWidth;
var categoryCount = axis.GetDataCount(dataZoom);
int segment = (axis.boundaryGap ? categoryCount : categoryCount - 1);
segment = segment <= 0 ? dataCount : segment;
if (segment <= 0)
segment = 1;
return coordinateWidth / segment;
}
/// <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]);
}
}
}
/// <summary>
/// 获得分割线条数
/// </summary>
/// <param name="dataZoom"></param>
/// <returns></returns>
public static int GetScaleNumber(Axis axis, float coordinateWidth, DataZoom dataZoom = null)
{
int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom);
if (splitNum == 0)
return 0;
if (axis.IsCategory())
{
var dataCount = axis.GetDataList(dataZoom).Count;
var scaleNum = 0;
if (axis.boundaryGap)
{
scaleNum = dataCount > 2 && dataCount % splitNum == 0 ?
splitNum + 1 :
splitNum + 2;
}
else
{
if (dataCount < splitNum) scaleNum = splitNum;
else scaleNum = dataCount > 2 && dataCount % splitNum == 0 ?
splitNum :
splitNum + 1;
}
return scaleNum;
}
else if (axis.IsTime())
return splitNum;
else
return splitNum + 1;
}
/// <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;
}
}
}
public static float GetEachWidth(Axis axis, float coordinateWidth, DataZoom dataZoom = null)
{
var data = axis.GetDataList(dataZoom);
if (data.Count > 0)
{
var count = axis.boundaryGap ? data.Count : data.Count - 1;
return count > 0 ? coordinateWidth / count : coordinateWidth;
}
else
{
int num = GetScaleNumber(axis, coordinateWidth, dataZoom) - 1;
return num > 0 ? coordinateWidth / num : coordinateWidth;
}
}
/// <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;
}
}
}
public static bool NeedShowSplit(Axis axis)
{
if (!axis.show)
return false;
if (axis.IsCategory() && axis.GetDataList().Count <= 0)
return false;
else
return true;
}
public static void AdjustCircleLabelPos(ChartLabel txt, Vector3 pos, Vector3 cenPos, float txtHig, Vector3 offset)
{
var txtWidth = txt.text.GetPreferredWidth();
var sizeDelta = new Vector2(txtWidth, txt.text.GetPreferredHeight());
txt.text.SetSizeDelta(sizeDelta);
var diff = pos.x - cenPos.x;
if (diff < -1f) //left
{
pos = new Vector3(pos.x - txtWidth / 2, pos.y);
}
else if (diff > 1f) //right
{
pos = new Vector3(pos.x + txtWidth / 2, pos.y);
}
else
{
float y = pos.y > cenPos.y ? pos.y + txtHig / 2 : pos.y - txtHig / 2;
pos = new Vector3(pos.x, y);
}
txt.SetPosition(pos + offset);
}
public static void AdjustRadiusAxisLabelPos(ChartLabel txt, Vector3 pos, Vector3 cenPos, float txtHig, Vector3 offset)
{
var txtWidth = txt.text.GetPreferredWidth();
var sizeDelta = new Vector2(txtWidth, txt.text.GetPreferredHeight());
txt.text.SetSizeDelta(sizeDelta);
var diff = pos.y - cenPos.y;
if (diff > 20f) //left
{
pos = new Vector3(pos.x - txtWidth / 2, pos.y);
}
else if (diff < -20f) //right
{
pos = new Vector3(pos.x + txtWidth / 2, pos.y);
}
else
{
float y = pos.y > cenPos.y ? pos.y + txtHig / 2 : pos.y - txtHig / 2;
pos = new Vector3(pos.x, y);
}
txt.SetPosition(pos);
}
public static float GetAxisPosition(GridCoord grid, Axis axis, double value, int dataCount = 0, DataZoom dataZoom = null)
{
var gridHeight = axis is YAxis ? grid.context.height : grid.context.width;
var gridXY = axis is YAxis ? grid.context.y : grid.context.x;
if (axis.IsCategory())
{
if (dataCount == 0) dataCount = axis.data.Count;
var categoryIndex = (int) value;
var scaleWid = AxisHelper.GetDataWidth(axis, gridHeight, dataCount, dataZoom);
float startY = gridXY + (axis.boundaryGap ? scaleWid / 2 : 0);
return startY + scaleWid * categoryIndex;
}
else
{
var yDataHig = (axis.context.minMaxRange == 0) ? 0f :
(float) ((value - axis.context.minValue) / axis.context.minMaxRange * gridHeight);
return gridXY + yDataHig;
}
}
public static double GetAxisPositionValue(GridCoord grid, Axis axis, Vector3 pos)
{
if (axis is YAxis)
return GetAxisPositionValue(pos.y, grid.context.height, axis.context.minMaxRange, grid.context.y, axis.context.offset);
else if (axis is XAxis)
return GetAxisPositionValue(pos.x, grid.context.width, axis.context.minMaxRange, grid.context.x, axis.context.offset);
else
return 0;
}
public static double GetAxisPositionValue(float xy, float axisLength, double axisRange, float axisStart, float axisOffset)
{
var yRate = axisRange / axisLength;
return yRate * (xy - axisStart - axisOffset);
}
/// <summary>
/// 获得数值value在坐标轴上的坐标位置
/// </summary>
/// <param name="grid"></param>
/// <param name="axis"></param>
/// <param name="scaleWidth"></param>
/// <param name="value"></param>
/// <returns></returns>
public static float GetAxisValuePosition(GridCoord grid, Axis axis, float scaleWidth, double value)
{
return GetAxisPositionInternal(grid, axis, scaleWidth, value, true, false);
}
/// <summary>
/// 获得数值value在坐标轴上相对起点的距离
/// </summary>
/// <param name="grid"></param>
/// <param name="axis"></param>
/// <param name="scaleWidth"></param>
/// <param name="value"></param>
/// <returns></returns>
public static float GetAxisValueDistance(GridCoord grid, Axis axis, float scaleWidth, double value)
{
return GetAxisPositionInternal(grid, axis, scaleWidth, value, false, false);
}
/// <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);
}
private static float GetAxisPositionInternal(GridCoord grid, Axis axis, float scaleWidth, double value, bool includeGridXY, bool realLength)
{
var isY = axis is YAxis;
var gridHeight = isY ? grid.context.height : grid.context.width;
var gridXY = isY ? grid.context.y : grid.context.x;
if (axis.IsLog())
{
int minIndex = axis.GetLogMinIndex();
float nowIndex = axis.GetLogValue(value);
return includeGridXY ?
gridXY + (nowIndex - minIndex) / axis.splitNumber * gridHeight :
(nowIndex - minIndex) / axis.splitNumber * gridHeight;
}
else if (axis.IsCategory())
{
var categoryIndex = (int) value;
return includeGridXY ?
gridXY + (axis.boundaryGap ? scaleWidth / 2 : 0) + scaleWidth * categoryIndex :
(axis.boundaryGap ? scaleWidth / 2 : 0) + scaleWidth * categoryIndex;
}
else
{
var yDataHig = 0f;
if (axis.context.minMaxRange != 0)
{
if (realLength)
yDataHig = (float) (value * gridHeight / axis.context.minMaxRange);
else
yDataHig = (float) ((value - axis.context.minValue) / axis.context.minMaxRange * gridHeight);
}
return includeGridXY ?
gridXY + yDataHig :
yDataHig;
}
}
}
}