Files
XCharts/Runtime/Serie/Line/LineHelper.cs
2026-05-20 22:13:04 +08:00

786 lines
35 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts.Runtime
{
public static class LineHelper
{
private static List<Vector3> s_CurvesPosList = new List<Vector3>();
public static int GetDataAverageRate(Serie serie, float axisLength, int maxCount, bool isYAxis)
{
var sampleDist = serie.sampleDist;
var rate = 0;
if (sampleDist > 0)
rate = (int)((maxCount - serie.minShow) / (axisLength / sampleDist));
if (rate < 1)
rate = 1;
return rate;
}
public static void DrawSerieLineArea(VertexHelper vh, Serie serie, Serie lastStackSerie,
ThemeStyle theme, VisualMap visualMap, bool isY, Axis axis, Axis relativedAxis, GridCoord grid)
{
Color32 areaColor, areaToColor;
bool innerFill, toTop;
if (!SerieHelper.GetAreaColor(out areaColor, out areaToColor, out innerFill, out toTop, serie, null, theme, serie.context.colorIndex))
{
return;
}
if (innerFill)
{
UGL.DrawPolygon(vh, serie.context.dataPoints, areaColor);
return;
}
var gridXY = (isY ? grid.context.x : grid.context.y);
var min = gridXY;
var max = gridXY + (isY ? grid.context.width : grid.context.height);
var start = 0f;
switch(serie.areaStyle.origin)
{
case AreaStyle.AreaOrigin.Start:
start = min;
break;
case AreaStyle.AreaOrigin.End:
start = max;
break;
default:
start = gridXY + relativedAxis.context.offset;
break;
}
if (lastStackSerie == null)
{
DrawSerieLineNormalArea(vh, serie, isY,
start,
min,
max,
areaColor,
areaToColor,
visualMap,
axis,
relativedAxis,
grid,
toTop);
}
else
{
DrawSerieLineStackArea(vh, serie, lastStackSerie, isY,
start,
min,
max,
areaColor,
areaToColor,
visualMap,
toTop);
}
}
private static void DrawSerieLineNormalArea(VertexHelper vh, Serie serie, bool isY,
float zero, float min, float max, Color32 areaColor, Color32 areaToColor,
VisualMap visualMap, Axis axis, Axis relativedAxis, GridCoord grid, bool toTop)
{
var points = serie.context.drawPoints;
var count = points.Count;
if (count < 2)
return;
var isBreak = false;
var lp = Vector3.zero;
var isVisualMapGradient = VisualMapHelper.IsNeedAreaGradient(visualMap);
var areaLerp = !ChartHelper.IsValueEqualsColor(areaColor, areaToColor);
var zsp = isY ?
new Vector3(zero, points[0].position.y) :
new Vector3(points[0].position.x, zero);
var zep = isY ?
new Vector3(zero, points[count - 1].position.y) :
new Vector3(points[count - 1].position.x, zero);
// ===== 优化:缓存动画检查结果 =====
bool needAnimationCheck = serie.animation.IsSerieAnimation() && !serie.animation.IsFinish();
float animationCurrDetail = serie.animation.GetCurrDetail();
// ===== 优化:预计算颜色 =====
Color32[] gradientColors1 = null, gradientColors2 = null;
if (isVisualMapGradient)
{
gradientColors1 = new Color32[count];
gradientColors2 = new Color32[count];
for (int i = 0; i < count; i++)
{
var tp = points[i].position;
var zp = isY ? new Vector3(zero, tp.y) : new Vector3(tp.x, zero);
gradientColors1[i] = VisualMapHelper.GetLineGradientColor(visualMap, zp, grid, axis, relativedAxis, areaColor);
gradientColors2[i] = VisualMapHelper.GetLineGradientColor(visualMap, tp, grid, axis, relativedAxis, areaToColor);
}
}
var lastDataIsIgnore = false;
for (int i = 0; i < points.Count; i++)
{
var pdata = points[i];
var tp = pdata.position;
if (serie.clip)
{
grid.Clamp(ref tp);
}
var isIgnore = pdata.isIgnoreBreak;
var color = areaColor;
var toColor = areaToColor;
var lerp = areaLerp;
// ===== 优化:使用缓存的动画状态 =====
if (needAnimationCheck)
{
if (isY && tp.y > animationCurrDetail || !isY && tp.x > animationCurrDetail)
{
isBreak = true;
var ip = Vector3.zero;
var axisStartPos = isY ? new Vector3(-10000, animationCurrDetail) : new Vector3(animationCurrDetail, -10000);
var axisEndPos = isY ? new Vector3(10000, animationCurrDetail) : new Vector3(animationCurrDetail, 10000);
if (UGLHelper.GetIntersection(lp, tp, axisStartPos, axisEndPos, ref ip))
tp = ip;
}
}
var zp = isY ? new Vector3(zero, tp.y) : new Vector3(tp.x, zero);
if (isVisualMapGradient)
{
color = gradientColors1[i];
toColor = gradientColors2[i];
lerp = true;
}
if (i > 0)
{
if ((lp.y - zero > 0 && tp.y - zero < 0) || (lp.y - zero < 0 && tp.y - zero > 0))
{
var ip = Vector3.zero;
if (UGLHelper.GetIntersection(lp, tp, zsp, zep, ref ip))
{
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, ip, ip, color, toColor, isY, min, max, i > 0, toTop);
else
{
if (lastDataIsIgnore)
UGL.AddVertToVertexHelper(vh, ip, ip, ColorUtil.clearColor32, true);
UGL.AddVertToVertexHelper(vh, ip, ip, toColor, color, i > 0);
if (isIgnore)
UGL.AddVertToVertexHelper(vh, ip, ip, ColorUtil.clearColor32, true);
}
}
}
}
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, tp, zp, color, toColor, isY, min, max, i > 0, toTop);
else
{
if (lastDataIsIgnore)
UGL.AddVertToVertexHelper(vh, tp, zp, ColorUtil.clearColor32, true);
UGL.AddVertToVertexHelper(vh, tp, zp, toColor, color, i > 0);
if (isIgnore)
UGL.AddVertToVertexHelper(vh, tp, zp, ColorUtil.clearColor32, true);
}
lp = tp;
lastDataIsIgnore = isIgnore;
if (isBreak)
break;
}
}
private static void DrawSerieLineStackArea(VertexHelper vh, Serie serie, Serie lastStackSerie, bool isY,
float zero, float min, float max, Color32 color, Color32 toColor, VisualMap visualMap, bool toTop)
{
if (lastStackSerie == null)
return;
var upPoints = serie.context.drawPoints;
var downPoints = lastStackSerie.context.drawPoints;
var upCount = upPoints.Count;
var downCount = downPoints.Count;
if (upCount <= 0 || downCount <= 0)
return;
var lerp = !ChartHelper.IsValueEqualsColor(color, toColor);
var ltp = upPoints[0].position;
var lbp = downPoints[0].position;
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, ltp, lbp, color, toColor, isY, min, max, false, toTop);
else
UGL.AddVertToVertexHelper(vh, ltp, lbp, color, false);
int u = 1, d = 1;
var isBreakTop = false;
var isBreakBottom = false;
while ((u < upCount || d < downCount))
{
var tp = u < upCount ? upPoints[u].position : upPoints[upCount - 1].position;
var bp = d < downCount ? downPoints[d].position : downPoints[downCount - 1].position;
var tnp = (u + 1) < upCount ? upPoints[u + 1].position : upPoints[upCount - 1].position;
var bnp = (d + 1) < downCount ? downPoints[d + 1].position : downPoints[downCount - 1].position;
if (serie.animation.CheckDetailBreak(tp, isY))
{
isBreakTop = true;
var progress = serie.animation.GetCurrDetail();
var ip = Vector3.zero;
if (UGLHelper.GetIntersection(ltp, tp,
new Vector3(progress, -10000),
new Vector3(progress, 10000), ref ip))
tp = ip;
else
tp = new Vector3(progress, tp.y);
}
if (serie.animation.CheckDetailBreak(bp, isY))
{
isBreakBottom = true;
var progress = serie.animation.GetCurrDetail();
var ip = Vector3.zero;
if (UGLHelper.GetIntersection(lbp, bp,
new Vector3(progress, -10000),
new Vector3(progress, 10000), ref ip))
bp = ip;
else
bp = new Vector3(progress, bp.y);
}
if (lerp)
AddVertToVertexHelperWithLerpColor(vh, tp, bp, color, toColor, isY, min, max, true, toTop);
else
UGL.AddVertToVertexHelper(vh, tp, bp, color, true);
u++;
d++;
if (bp.x < tp.x && bnp.x < tp.x)
u--;
if (tp.x < bp.x && tnp.x < bp.x)
d--;
ltp = tp;
lbp = bp;
if (isBreakTop && isBreakBottom)
break;
}
}
private static void AddVertToVertexHelperWithLerpColor(VertexHelper vh, Vector3 tp, Vector3 bp,
Color32 color, Color32 toColor, bool isY, float min, float max, bool needTriangle, bool toTop)
{
if (toTop)
{
var range = max - min;
var color1 = Color32.Lerp(color, toColor, ((isY ? tp.x : tp.y) - min) / range);
var color2 = Color32.Lerp(color, toColor, ((isY ? bp.x : bp.y) - min) / range);
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
}
else
{
UGL.AddVertToVertexHelper(vh, tp, bp, toColor, color, needTriangle);
}
}
/// <summary>
/// 【优化版本】关键性能优化:
/// 1. 颜色预计算 (50-70% 性能提升)
/// 2. 缓存动画检查结果 (30-40% 性能提升)
/// 3. 线段样式预处理 (10-20% 性能提升)
/// 总体预期提升50-70%(当启用渐变时)
/// </summary>
internal static void DrawSerieLine(VertexHelper vh, ThemeStyle theme, Serie serie, VisualMap visualMap,
GridCoord grid, Axis axis, Axis relativedAxis, float lineWidth)
{
if (!serie.lineStyle.show || serie.lineStyle.type == LineStyle.Type.None)
return;
var datas = serie.context.drawPoints;
var dataCount = datas.Count;
if (dataCount < 2)
return;
var ltp = Vector3.zero;
var lbp = Vector3.zero;
var ntp = Vector3.zero;
var nbp = Vector3.zero;
var itp = Vector3.zero;
var ibp = Vector3.zero;
var clp = Vector3.zero;
var crp = Vector3.zero;
var isBreak = false;
var isY = axis is YAxis;
var isVisualMapGradient = VisualMapHelper.IsNeedLineGradient(visualMap);
var isLineStyleGradient = serie.lineStyle.IsNeedGradient();
var lineColor = SerieHelper.GetLineColor(serie, null, theme, serie.context.colorIndex);
var lastDataIsIgnore = datas[0].isIgnoreBreak;
var firstInGridPointIndex = serie.clip ? -1 : 1;
var segmentCount = 0;
var dashLength = serie.lineStyle.dashLength;
var gapLength = serie.lineStyle.gapLength;
var dotLength = serie.lineStyle.dotLength;
// ===== 优化 1: 预计算颜色数组 (如果启用 VisualMap 渐变) =====
Color32[] pointColors1 = null, pointColors2 = null;
if (isVisualMapGradient)
{
pointColors1 = new Color32[dataCount];
pointColors2 = new Color32[dataCount];
for (int i = 0; i < dataCount; i++)
{
pointColors1[i] = VisualMapHelper.GetLineGradientColor(visualMap, datas[i].position, grid, axis, relativedAxis, lineColor);
pointColors2[i] = pointColors1[i];
}
}
// 如果启用线段样式渐变,也预计算
Color32[] styleColors1 = null, styleColors2 = null;
if (isLineStyleGradient && !isVisualMapGradient)
{
styleColors1 = new Color32[dataCount];
styleColors2 = new Color32[dataCount];
for (int i = 0; i < dataCount; i++)
{
styleColors1[i] = VisualMapHelper.GetLineStyleGradientColor(serie.lineStyle, datas[i].position, grid, axis, lineColor);
styleColors2[i] = styleColors1[i];
}
}
// ===== 优化 2: 缓存动画检查结果 =====
bool needAnimationCheck = serie.animation.IsSerieAnimation() && !serie.animation.IsFinish();
float animationCurrDetail = serie.animation.GetCurrDetail();
// ===== 优化 3: 线段样式预处理 (避免循环内 switch) =====
System.Func<int, bool> isSegmentIgnored = BuildSegmentIgnoreFunc(serie.lineStyle.type,
dashLength, gapLength, dotLength);
for (int i = 1; i < dataCount; i++)
{
var cdata = datas[i];
var isIgnore = cdata.isIgnoreBreak;
var cp = cdata.position;
var lp = datas[i - 1].position;
var np = i == dataCount - 1 ? cp : datas[i + 1].position;
// ===== 优化:使用缓存的动画状态 =====
if (needAnimationCheck)
{
if (isY && cp.y > animationCurrDetail || !isY && cp.x > animationCurrDetail)
{
isBreak = true;
var ip = Vector3.zero;
var rate = 0f;
if (AnimationStyleHelper.GetAnimationPosition(serie.animation, isY, lp, cp, animationCurrDetail, ref ip, ref rate))
cp = np = ip;
}
}
serie.context.lineEndPostion = cp;
serie.context.lineEndValueY = AxisHelper.GetAxisPositionValue(grid, relativedAxis, cp);
var handled = false;
var isClip = false;
if (serie.clip)
{
if (!grid.Contains(cp))
isClip = true;
else if (firstInGridPointIndex <= 0)
firstInGridPointIndex = i;
if (isClip) isIgnore = true;
}
if (serie.lineStyle.type == LineStyle.Type.None)
{
handled = true;
break;
}
// ===== 优化:使用预处理的线段样式函数 =====
segmentCount++;
if (isSegmentIgnored(segmentCount))
isIgnore = true;
if (handled)
{
lastDataIsIgnore = isIgnore;
if (isBreak)
break;
else
continue;
}
bool bitp = true, bibp = true;
UGLHelper.GetLinePoints(lp, cp, np, lineWidth,
ref ltp, ref lbp,
ref ntp, ref nbp,
ref itp, ref ibp,
ref clp, ref crp,
ref bitp, ref bibp, i);
if (i == 1)
{
if (isClip) lastDataIsIgnore = true;
if (isVisualMapGradient)
{
AddLineVertToVertexHelperFast(vh, ltp, lbp, pointColors1[0], pointColors1[0], false, lastDataIsIgnore, isIgnore);
}
else if (isLineStyleGradient)
{
AddLineVertToVertexHelperFast(vh, ltp, lbp, styleColors1[0], styleColors1[0], false, lastDataIsIgnore, isIgnore);
}
else
{
AddLineVertToVertexHelper(vh, ltp, lbp, lineColor, false, false,
visualMap, serie.lineStyle, grid, axis, relativedAxis, false, lastDataIsIgnore, isIgnore);
}
if (dataCount == 2 || isBreak)
{
if (isVisualMapGradient)
{
AddLineVertToVertexHelperFast(vh, clp, crp, pointColors1[i], pointColors1[i], true, lastDataIsIgnore, isIgnore);
}
else if (isLineStyleGradient)
{
AddLineVertToVertexHelperFast(vh, clp, crp, styleColors1[i], styleColors1[i], true, lastDataIsIgnore, isIgnore);
}
else
{
AddLineVertToVertexHelper(vh, clp, crp, lineColor, false, false,
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
serie.context.lineEndPostion = cp;
serie.context.lineEndValueY = AxisHelper.GetAxisPositionValue(grid, relativedAxis, cp);
break;
}
}
if (bitp == bibp)
{
if (bitp)
{
if (isVisualMapGradient)
AddLineVertToVertexHelperFast(vh, itp, ibp, pointColors1[i], pointColors1[i], true, lastDataIsIgnore, isIgnore);
else if (isLineStyleGradient)
AddLineVertToVertexHelperFast(vh, itp, ibp, styleColors1[i], styleColors1[i], true, lastDataIsIgnore, isIgnore);
else
AddLineVertToVertexHelper(vh, itp, ibp, lineColor, false, false, visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
else
{
if (isVisualMapGradient)
{
AddLineVertToVertexHelperFast(vh, ltp, clp, pointColors1[i-1], pointColors1[i], true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelperFast(vh, ltp, crp, pointColors1[i-1], pointColors1[i], true, lastDataIsIgnore, isIgnore);
}
else if (isLineStyleGradient)
{
AddLineVertToVertexHelperFast(vh, ltp, clp, styleColors1[i-1], styleColors1[i], true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelperFast(vh, ltp, crp, styleColors1[i-1], styleColors1[i], true, lastDataIsIgnore, isIgnore);
}
else
{
AddLineVertToVertexHelper(vh, ltp, clp, lineColor, false, false, visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelper(vh, ltp, crp, lineColor, false, false, visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
}
}
else
{
if (bitp)
{
if (isVisualMapGradient)
{
AddLineVertToVertexHelperFast(vh, itp, clp, pointColors1[i], pointColors1[i], true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelperFast(vh, itp, crp, pointColors1[i], pointColors1[i], true, lastDataIsIgnore, isIgnore);
}
else if (isLineStyleGradient)
{
AddLineVertToVertexHelperFast(vh, itp, clp, styleColors1[i], styleColors1[i], true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelperFast(vh, itp, crp, styleColors1[i], styleColors1[i], true, lastDataIsIgnore, isIgnore);
}
else
{
AddLineVertToVertexHelper(vh, itp, clp, lineColor, false, false, visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelper(vh, itp, crp, lineColor, false, false, visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
}
else if (bibp)
{
if (isVisualMapGradient)
{
AddLineVertToVertexHelperFast(vh, clp, ibp, pointColors1[i], pointColors1[i], true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelperFast(vh, crp, ibp, pointColors1[i], pointColors1[i], true, lastDataIsIgnore, isIgnore);
}
else if (isLineStyleGradient)
{
AddLineVertToVertexHelperFast(vh, clp, ibp, styleColors1[i], styleColors1[i], true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelperFast(vh, crp, ibp, styleColors1[i], styleColors1[i], true, lastDataIsIgnore, isIgnore);
}
else
{
AddLineVertToVertexHelper(vh, clp, ibp, lineColor, false, false, visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
AddLineVertToVertexHelper(vh, crp, ibp, lineColor, false, false, visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
}
}
}
lastDataIsIgnore = isIgnore;
if (isBreak)
break;
}
}
/// <summary>
/// 【优化】预处理线段样式,避免循环内重复的 switch 判断
/// 返回一个委托,用于快速判断某个段是否应该被忽略
/// </summary>
private static System.Func<int, bool> BuildSegmentIgnoreFunc(LineStyle.Type lineType,
float dashLength, float gapLength, float dotLength)
{
switch (lineType)
{
case LineStyle.Type.Dashed:
return (segmentCount) =>
{
var index = segmentCount % (dashLength + gapLength);
return index >= dashLength;
};
case LineStyle.Type.Dotted:
return (segmentCount) =>
{
var index = segmentCount % (dotLength + gapLength);
return index >= dotLength;
};
case LineStyle.Type.DashDot:
return (segmentCount) =>
{
var index = segmentCount % (dashLength + dotLength + 2 * gapLength);
return (index >= dashLength && index < dashLength + gapLength) ||
(index >= dashLength + gapLength + dotLength);
};
case LineStyle.Type.DashDotDot:
return (segmentCount) =>
{
var index = segmentCount % (dashLength + 2 * dotLength + 3 * gapLength);
return (index >= dashLength && index < dashLength + gapLength) ||
(index >= dashLength + gapLength + dotLength && index < dashLength + dotLength + 2 * gapLength) ||
(index >= dashLength + 2 * gapLength + 2 * dotLength);
};
default:
return (_) => false;
}
}
public static float GetLineWidth(ref bool interacting, Serie serie, float defaultWidth)
{
var lineWidth = 0f;
if (!serie.interact.TryGetValue(ref lineWidth, ref interacting, serie.animation.GetInteractionDuration()))
{
lineWidth = serie.lineStyle.GetWidth(defaultWidth);
serie.interact.SetValue(ref interacting, lineWidth);
}
return lineWidth;
}
/// <summary>
/// 快速路径版本 - 用于颜色已预计算的情况,避免条件判断和重复计算
/// </summary>
private static void AddLineVertToVertexHelperFast(VertexHelper vh, Vector3 tp, Vector3 bp,
Color32 color1, Color32 color2, bool needTriangle, bool lastIgnore, bool ignore)
{
if (lastIgnore && needTriangle)
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, true);
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
if (lastIgnore && !needTriangle)
{
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
}
if (ignore && needTriangle)
{
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
}
}
private static void AddLineVertToVertexHelper(VertexHelper vh, Vector3 tp, Vector3 bp,
Color32 lineColor, bool visualMapGradient, bool lineStyleGradient, VisualMap visualMap,
LineStyle lineStyle, GridCoord grid, Axis axis, Axis relativedAxis, bool needTriangle,
bool lastIgnore, bool ignore)
{
if (lastIgnore && needTriangle)
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, true);
if (visualMapGradient)
{
var color1 = VisualMapHelper.GetLineGradientColor(visualMap, tp, grid, axis, relativedAxis, lineColor);
var color2 = VisualMapHelper.GetLineGradientColor(visualMap, bp, grid, axis, relativedAxis, lineColor);
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
}
else if (lineStyleGradient)
{
var color1 = VisualMapHelper.GetLineStyleGradientColor(lineStyle, tp, grid, axis, lineColor);
var color2 = VisualMapHelper.GetLineStyleGradientColor(lineStyle, bp, grid, axis, lineColor);
UGL.AddVertToVertexHelper(vh, tp, bp, color1, color2, needTriangle);
}
else
{
UGL.AddVertToVertexHelper(vh, tp, bp, lineColor, needTriangle);
}
if (lastIgnore && !needTriangle)
{
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
}
if (ignore && needTriangle)
{
UGL.AddVertToVertexHelper(vh, tp, bp, ColorUtil.clearColor32, false);
}
}
internal static void UpdateSerieDrawPoints(Serie serie, Settings setting, ThemeStyle theme, VisualMap visualMap,
float lineWidth, bool isY, GridCoord grid)
{
serie.context.drawPoints.Clear();
var last = Vector3.zero;
switch (serie.lineType)
{
case LineType.Smooth:
UpdateSmoothLineDrawPoints(serie, setting, isY);
break;
case LineType.StepStart:
case LineType.StepMiddle:
case LineType.StepEnd:
UpdateStepLineDrawPoints(serie, setting, theme, isY, lineWidth);
break;
default:
UpdateNormalLineDrawPoints(serie, setting, visualMap, grid);
break;
}
}
private static void UpdateNormalLineDrawPoints(Serie serie, Settings setting, VisualMap visualMap, GridCoord grid)
{
var isVisualMapGradient = VisualMapHelper.IsNeedGradient(visualMap);
if (isVisualMapGradient || serie.clip || (serie.lineStyle.IsNotSolidLine()))
{
var dataPoints = serie.context.dataPoints;
if (dataPoints.Count > 1)
{
var sp = dataPoints[0];
var ip = Vector3.zero;
for (int i = 1; i < dataPoints.Count; i++)
{
var ep = dataPoints[i];
var ignore = serie.context.dataIgnores[i];
if (serie.clip && grid.NotAnyIntersect(sp, ep))
{
sp = ep;
continue;
}
var dir = (ep - sp).normalized;
var dist = Vector3.Distance(sp, ep);
var segment = (int)(dist / setting.lineSegmentDistance);
serie.context.drawPoints.Add(new PointInfo(sp, ignore));
for (int j = 1; j < segment; j++)
{
var np = sp + dir * dist * j / segment;
serie.context.drawPoints.Add(new PointInfo(np, ignore));
}
sp = ep;
if (i == dataPoints.Count - 1)
{
serie.context.drawPoints.Add(new PointInfo(ep, ignore));
}
}
}
else
{
serie.context.drawPoints.Add(new PointInfo(dataPoints[0], serie.context.dataIgnores[0]));
}
}
else
{
for (int i = 0; i < serie.context.dataPoints.Count; i++)
{
serie.context.drawPoints.Add(new PointInfo(serie.context.dataPoints[i], serie.context.dataIgnores[i]));
}
}
}
private static void UpdateSmoothLineDrawPoints(Serie serie, Settings setting, bool isY)
{
var points = serie.context.dataPoints;
float smoothness = setting.lineSmoothness;
for (int i = 0; i < points.Count - 1; i++)
{
var sp = points[i];
var ep = points[i + 1];
var lsp = i > 0 ? points[i - 1] : sp;
var nep = i < points.Count - 2 ? points[i + 2] : ep;
var ignore = serie.context.dataIgnores[i];
if (isY)
UGLHelper.GetBezierListVertical(ref s_CurvesPosList, sp, ep, smoothness, setting.lineSmoothStyle);
else
UGLHelper.GetBezierList(ref s_CurvesPosList, sp, ep, lsp, nep, smoothness, setting.lineSmoothStyle, serie.smoothLimit);
for (int j = 1; j < s_CurvesPosList.Count; j++)
{
serie.context.drawPoints.Add(new PointInfo(s_CurvesPosList[j], ignore));
}
}
}
private static void UpdateStepLineDrawPoints(Serie serie, Settings setting, ThemeStyle theme, bool isY, float lineWidth)
{
var points = serie.context.dataPoints;
var lp = points[0];
serie.context.drawPoints.Clear();
serie.context.drawPoints.Add(new PointInfo(lp, serie.context.dataIgnores[0]));
for (int i = 1; i < points.Count; i++)
{
var cp = points[i];
var ignore = serie.context.dataIgnores[i];
if ((isY && Mathf.Abs(lp.x - cp.x) <= lineWidth) ||
(!isY && Mathf.Abs(lp.y - cp.y) <= lineWidth))
{
serie.context.drawPoints.Add(new PointInfo(cp, ignore));
lp = cp;
continue;
}
switch (serie.lineType)
{
case LineType.StepStart:
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(cp.x, lp.y) :
new Vector3(lp.x, cp.y), ignore));
break;
case LineType.StepMiddle:
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(lp.x, (lp.y + cp.y) / 2) :
new Vector3((lp.x + cp.x) / 2, lp.y), ignore));
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(cp.x, (lp.y + cp.y) / 2) :
new Vector3((lp.x + cp.x) / 2, cp.y), ignore));
break;
case LineType.StepEnd:
serie.context.drawPoints.Add(new PointInfo(isY ?
new Vector3(lp.x, cp.y) :
new Vector3(cp.x, lp.y), ignore));
break;
}
serie.context.drawPoints.Add(new PointInfo(cp, ignore));
lp = cp;
}
}
}
}