3.0 - ParallelChart

This commit is contained in:
monitor1394
2021-11-28 20:31:41 +08:00
parent 1b3fa7fb43
commit f39cddaa5e
28 changed files with 424 additions and 576 deletions

View File

@@ -153,6 +153,13 @@ namespace XCharts
AddChart<CandlestickChart>("CandlestickChart");
}
[MenuItem("XCharts/ParallelChart", priority = 55)]
[MenuItem("GameObject/XCharts/ParallelChart", priority = 55)]
public static void ParallelChart()
{
AddChart<ParallelChart>("ParallelChart");
}
[MenuItem("XCharts/Themes Reload")]
public static void ReloadTheme()
{

View File

@@ -5,6 +5,7 @@
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
@@ -19,19 +20,20 @@ namespace XCharts
protected override void Reset()
{
base.Reset();
AddChartComponentWhenNoExist<ParallelCoord>();
AddChartComponentWhenNoExist<ParallelAxis>();
var tooltip = GetChartComponent<Tooltip>();
tooltip.type = Tooltip.Type.Shadow;
tooltip.trigger = Tooltip.Trigger.Axis;
RemoveData();
AddChartComponent<ParallelCoord>();
for (int i = 0; i < 3; i++)
{
var valueAxis = AddChartComponent<ParallelAxis>();
valueAxis.type = Axis.AxisType.Value;
}
var categoryAxis = AddChartComponent<ParallelAxis>();
categoryAxis.type = Axis.AxisType.Category;
categoryAxis.position = Axis.AxisPosition.Right;
categoryAxis.data = new List<string>() { "x1", "x2", "x3", "x4", "x5" };
Parallel.AddDefaultSerie(this, GenerateDefaultSerieName());
// for (int i = 0; i < 5; i++)
// {
// AddXAxisData("x" + (i + 1));
// }
}
#endif
}

View File

@@ -42,8 +42,7 @@ namespace XCharts
if (tempMinValue != axis.context.minValue || tempMaxValue != axis.context.maxValue)
{
chart.m_IsPlayingAnimation = true;
var needCheck = !chart.m_IsPlayingAnimation && axis.context.lastCheckInverse == axis.inverse;
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue, needCheck);
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue);
axis.context.xOffset = 0;
axis.context.yOffset = 0;
axis.context.lastCheckInverse = axis.inverse;
@@ -53,7 +52,7 @@ namespace XCharts
chart.RefreshChart();
}
}
if (axis.IsValueChanging(500) && !chart.m_IsPlayingAnimation)
if (!chart.m_IsPlayingAnimation)
{
UpdateAxisLabelText(axis);
chart.RefreshChart();
@@ -63,7 +62,7 @@ namespace XCharts
internal void UpdateAxisLabelText(AngleAxis axis)
{
var runtimeWidth = 360;
axis.UpdateLabelText(runtimeWidth, null, false, 500);
axis.UpdateLabelText(runtimeWidth, null, false);
}
private void InitAngleAxis(AngleAxis axis)

View File

@@ -664,8 +664,16 @@ namespace XCharts
{
if (context.minMaxRange == 0)
return 0;
if (IsCategory() && boundaryGap)
{
var each = axisLength / data.Count;
return (float)(each * (value + 0.5f));
}
else
{
return axisLength * (float)((value - context.minValue) / context.minMaxRange);
}
}
/// <summary>
@@ -718,15 +726,13 @@ namespace XCharts
/// 更新刻度标签文字
/// </summary>
/// <param name="dataZoom"></param>
internal void UpdateLabelText(float coordinateWidth, DataZoom dataZoom, bool forcePercent, float duration)
internal void UpdateLabelText(float coordinateWidth, DataZoom dataZoom, bool forcePercent)
{
var minValue = GetCurrMinValue(duration);
var maxValue = GetCurrMaxValue(duration);
for (int i = 0; i < context.labelObjectList.Count; i++)
{
if (context.labelObjectList[i] != null)
{
var text = AxisHelper.GetLabelName(this, coordinateWidth, i, minValue, maxValue, dataZoom, forcePercent);
var text = AxisHelper.GetLabelName(this, coordinateWidth, i, context.minValue, context.maxValue, dataZoom, forcePercent);
context.labelObjectList[i].SetText(text);
}
}
@@ -740,20 +746,10 @@ namespace XCharts
return Vector3.zero;
}
internal bool UpdateMinValue(double value, bool check)
internal void UpdateMinMaxValue(double minValue, double maxValue)
{
return context.UpdateMinValue(value, check);
}
internal bool UpdateMaxValue(double value, bool check)
{
return context.UpdateMaxValue(value, check);
}
internal void UpdateMinMaxValue(double minValue, double maxValue, bool check)
{
UpdateMinValue(minValue, check);
UpdateMaxValue(maxValue, check);
context.minValue = minValue;
context.maxValue = maxValue;
double tempRange = maxValue - minValue;
if (context.minMaxRange != tempRange)
{
@@ -765,32 +761,6 @@ namespace XCharts
}
}
public double GetCurrMinValue(float duration)
{
return context.GetCurrMinValue(duration);
}
public double GetCurrMaxValue(float duration)
{
return context.GetCurrMaxValue(duration);
}
public bool IsValueChanging(float duration)
{
if (!Application.isPlaying)
return false;
if (GetCurrMinValue(duration) != context.minValue
|| GetCurrMaxValue(duration) != context.maxValue)
{
return true;
}
else
{
return false;
}
}
public float GetLogValue(double value)
{
if (value <= 0 || value == 1)

View File

@@ -13,36 +13,26 @@ namespace XCharts
{
public class AxisContext : MainComponentContext
{
internal Orient orient { get; set; }
public float x { get; internal set; }
public float y { get; internal set; }
public float width { get; internal set; }
public float height { get; internal set; }
public Vector3 position { get; internal set; }
public float left { get; internal set; }
public float right { get; internal set; }
public float bottom { get; internal set; }
public float top { get; internal set; }
/// <summary>
/// the current minimun value.
/// 当前最小值。
/// </summary>
public double minValue
{
get { return m_RuntimeMinValue; }
internal set
{
m_RuntimeMinValue = value;
m_RuntimeLastMinValue = value;
m_RuntimeMinValueUpdateTime = Time.time;
m_RuntimeMinValueChanged = true;
}
}
public double minValue { get; internal set; }
/// <summary>
/// the current maximum value.
/// 当前最大值。
/// </summary>
public double maxValue
{
get { return m_RuntimeMaxValue; }
internal set
{
m_RuntimeMaxValue = value;
m_RuntimeLastMaxValue = value;
m_RuntimeMaxValueUpdateTime = Time.time;
m_RuntimeMaxValueChanged = false;
}
}
public double maxValue { get; internal set; }
/// <summary>
/// the x offset of zero position.
/// 坐标轴原点在X轴的偏移。
@@ -70,16 +60,6 @@ namespace XCharts
private int filterStart;
private int filterEnd;
private int filterMinShow;
private double m_RuntimeMinValue;
private double m_RuntimeLastMinValue;
private bool m_RuntimeMinValueChanged;
private float m_RuntimeMinValueUpdateTime;
private double m_RuntimeMaxValue;
private double m_RuntimeLastMaxValue;
private bool m_RuntimeMaxValueChanged;
private float m_RuntimeMaxValueUpdateTime;
private bool m_RuntimeMinValueFirstChanged = true;
private bool m_RuntimeMaxValueFirstChanged = true;
private List<ChartLabel> m_AxisLabelList = new List<ChartLabel>();
private List<double> m_LabelValueList = new List<double>();
@@ -91,123 +71,6 @@ namespace XCharts
m_RuntimeData.Clear();
}
internal bool UpdateMinValue(double value, bool check)
{
if (value != maxValue)
{
if (check && Application.isPlaying)
{
if (m_RuntimeMinValueFirstChanged)
{
m_RuntimeMinValueFirstChanged = false;
}
else
{
m_RuntimeLastMinValue = minValue;
m_RuntimeMinValueChanged = true;
m_RuntimeMinValueUpdateTime = Time.time;
}
minValue = value;
}
else
{
minValue = value;
m_RuntimeLastMinValue = value;
m_RuntimeMinValueUpdateTime = Time.time;
m_RuntimeMinValueChanged = true;
}
return true;
}
else
{
return false;
}
}
internal bool UpdateMaxValue(double value, bool check)
{
if (value != maxValue)
{
if (check && Application.isPlaying)
{
if (m_RuntimeMaxValueFirstChanged)
{
m_RuntimeMaxValueFirstChanged = false;
}
else
{
m_RuntimeLastMaxValue = maxValue;
m_RuntimeMaxValueChanged = true;
m_RuntimeMaxValueUpdateTime = Time.time;
}
maxValue = value;
}
else
{
maxValue = value;
m_RuntimeLastMaxValue = value;
m_RuntimeMaxValueUpdateTime = Time.time;
m_RuntimeMaxValueChanged = false;
}
return true;
}
else
{
return false;
}
}
public double GetCurrMinValue(float duration)
{
if (!Application.isPlaying || !m_RuntimeMinValueChanged)
return minValue;
if (minValue == 0 && maxValue == 0)
return 0;
var time = Time.time - m_RuntimeMinValueUpdateTime;
if (time == 0)
return minValue;
var total = duration / 1000;
if (duration > 0 && time <= total)
{
var curr = MathUtil.Lerp(m_RuntimeLastMinValue, minValue, time / total);
return curr;
}
else
{
m_RuntimeMinValueChanged = false;
return minValue;
}
}
public double GetCurrMaxValue(float duration)
{
if (!Application.isPlaying || !m_RuntimeMaxValueChanged)
return maxValue;
if (minValue == 0 && maxValue == 0)
return 0;
var time = Time.time - m_RuntimeMaxValueUpdateTime;
if (time == 0)
return maxValue;
var total = duration / 1000;
if (duration > 0 && time < total)
{
var curr = MathUtil.Lerp(m_RuntimeLastMaxValue, maxValue, time / total);
return curr;
}
else
{
m_RuntimeMaxValueChanged = false;
return maxValue;
}
}
private List<string> m_EmptyFliter = new List<string>();
/// <summary>
/// 更新dataZoom对应的类目数据列表

View File

@@ -134,8 +134,7 @@ namespace XCharts
m_LastInterval = axis.interval;
chart.m_IsPlayingAnimation = true;
var needCheck = !chart.m_IsPlayingAnimation && axis.context.lastCheckInverse == axis.inverse;
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue, needCheck);
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue);
axis.context.xOffset = 0;
axis.context.yOffset = 0;
axis.context.lastCheckInverse = axis.inverse;
@@ -181,7 +180,7 @@ namespace XCharts
}
}
if (axis.IsValueChanging(500) && !chart.m_IsPlayingAnimation)
if ( !chart.m_IsPlayingAnimation)
{
UpdateAxisLabelText(axis);
chart.RefreshChart();
@@ -198,7 +197,7 @@ namespace XCharts
var isPercentStack = SeriesHelper.IsPercentStack<Bar>(chart.series);
var dataZoom = chart.GetDataZoomOfAxis(axis);
axis.UpdateLabelText(runtimeWidth, dataZoom, isPercentStack, 500);
axis.UpdateLabelText(runtimeWidth, dataZoom, isPercentStack);
}
internal static void UpdateAxisTickValueList(Axis axis)

View File

@@ -68,7 +68,7 @@ namespace XCharts
m_Show = true,
m_AlignWithLabel = false,
m_Inside = false,
m_ShowStartTick = false,
m_ShowStartTick = true,
m_ShowEndTick = true
};
return tick;

View File

@@ -15,12 +15,10 @@ namespace XCharts
[ComponentHandler(typeof(ParallelAxisHander), true)]
public class ParallelAxis : Axis
{
public new ParallelAxisContext context = new ParallelAxisContext();
public override void SetDefaultValue()
{
m_Show = true;
m_Type = AxisType.Category;
m_Type = AxisType.Value;
m_Min = 0;
m_Max = 0;
m_SplitNumber = 0;
@@ -35,6 +33,6 @@ namespace XCharts
iconStyle.show = false;
}
}
}

View File

@@ -1,22 +0,0 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts
{
public class ParallelAxisContext : AxisContext, IRectContext
{
internal ParallelCoord parallel { get; set; }
internal Orient orient { get; set; }
public float x { get; internal set; }
public float y { get; internal set; }
public float width { get; internal set; }
public float height { get; internal set; }
public Vector3 position { get; internal set; }
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: b92542e13620d417d819e8573b430dc8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -14,6 +14,8 @@ namespace XCharts
internal sealed class ParallelAxisHander : AxisHandler<ParallelAxis>
{
private Orient m_Orient;
private ParallelCoord m_Parallel;
protected override Orient orient { get { return m_Orient; } }
public override void InitComponent()
@@ -24,8 +26,6 @@ namespace XCharts
public override void Update()
{
UpdateContext(component);
UpdateAxisMinMaxValue(component.index, component);
//UpdatePointerValue(component);
}
public override void DrawBase(VertexHelper vh)
@@ -43,19 +43,19 @@ namespace XCharts
return;
m_Orient = parallel.orient;
axis.context.parallel = parallel;
m_Parallel = parallel;
var axisCount = chart.GetChartComponentNum<ParallelAxis>();
if (m_Orient == Orient.Horizonal)
{
var each = parallel.context.height / (axisCount - 1);
var each = axisCount > 1 ? parallel.context.height / (axisCount - 1) : 0;
axis.context.x = parallel.context.x;
axis.context.y = parallel.context.y + (axis.index) * each;
axis.context.width = parallel.context.width;
}
else
{
var each = parallel.context.width / (axisCount - 1);
var each = axisCount > 1 ? parallel.context.width / (axisCount - 1) : 0;
axis.context.x = parallel.context.x + (axis.index) * each;
axis.context.y = parallel.context.y;
axis.context.width = parallel.context.height;
@@ -103,7 +103,7 @@ namespace XCharts
protected override Vector3 GetLabelPosition(float scaleWid, int i)
{
if (component.context.parallel == null)
if (m_Parallel == null)
return Vector3.zero;
return GetLabelPosition(i, m_Orient, component, null,
@@ -119,7 +119,7 @@ namespace XCharts
{
if (AxisHelper.NeedShowSplit(axis))
{
if (axis.context.parallel == null)
if (m_Parallel == null)
return;
var dataZoom = chart.GetDataZoomOfAxis(axis);
@@ -137,7 +137,7 @@ namespace XCharts
{
if (AxisHelper.NeedShowSplit(axis))
{
if (axis.context.parallel == null)
if (m_Parallel == null)
return;
var dataZoom = chart.GetDataZoomOfAxis(axis);
@@ -154,7 +154,7 @@ namespace XCharts
{
if (axis.show && axis.axisLine.show)
{
if (axis.context.parallel == null)
if (m_Parallel == null)
return;
DrawAxisLine(vh, axis,

View File

@@ -41,8 +41,7 @@ namespace XCharts
if (tempMinValue != axis.context.minValue || tempMaxValue != axis.context.maxValue)
{
chart.m_IsPlayingAnimation = true;
var needCheck = !chart.m_IsPlayingAnimation && axis.context.lastCheckInverse == axis.inverse;
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue, needCheck);
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue);
axis.context.xOffset = 0;
axis.context.yOffset = 0;
axis.context.lastCheckInverse = axis.inverse;
@@ -53,7 +52,7 @@ namespace XCharts
chart.RefreshChart();
}
}
if (axis.IsValueChanging(500) && !chart.m_IsPlayingAnimation)
if (!chart.m_IsPlayingAnimation)
{
UpdateAxisLabelText(axis);
chart.RefreshChart();
@@ -63,7 +62,7 @@ namespace XCharts
internal void UpdateAxisLabelText(RadiusAxis axis)
{
var polar = chart.GetChartComponent<PolarCoord>(axis.polarIndex);
axis.UpdateLabelText(polar.context.radius, null, false, 500);
axis.UpdateLabelText(polar.context.radius, null, false);
}
private void InitRadiusAxis(RadiusAxis axis)

View File

@@ -26,8 +26,6 @@ namespace XCharts
[SerializeField] private float m_Width = 0;
[SerializeField] private float m_Height = 50;
public new SingleAxisContext context = new SingleAxisContext();
/// <summary>
/// Orientation of the axis. By default, it's 'Horizontal'. You can set it to be 'Vertical' to make a vertical axis.
/// 坐标轴朝向。默认为水平朝向。

View File

@@ -1,24 +0,0 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
namespace XCharts
{
public class SingleAxisContext : AxisContext, IRectContext
{
public float x { get; internal set; }
public float y { get; internal set; }
public float width { get; internal set; }
public float height { get; internal set; }
public Vector3 position { get; internal set; }
public float left { get; internal set; }
public float right { get; internal set; }
public float bottom { get; internal set; }
public float top { get; internal set; }
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 435915ad1c7fc41bb8362244d7bae638
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -555,6 +555,10 @@ namespace XCharts
public float GetCurrDetail()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
return m_DestDetailProgress;
#endif
return m_CurrDetailProgress;
}

View File

@@ -6,7 +6,6 @@
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections.Generic;
using System.Text;
@@ -73,7 +72,7 @@ namespace XCharts
s_Sb.Length = 0;
s_Sb.AppendFormat("fps : {0:f0} / {1:f0}\n", fps, avgFps);
s_Sb.AppendFormat("data : {0}\n", m_Chart.GetAllSerieDataCount());
s_Sb.AppendFormat("refresh : {0}", refreshCount);
s_Sb.AppendFormat("draw : {0}", refreshCount);
m_Label.SetText(s_Sb.ToString());
}
}

View File

@@ -132,13 +132,26 @@ namespace XCharts
for (int i = 0; i < component.context.parallelAxes.Count; i++)
{
var axis = component.context.parallelAxes[i];
var tempMinValue = m_SerieDimMin[i];
var tempMaxValue = m_SerieDimMax[i];
AxisHelper.AdjustMinMaxValue(axis, ref tempMinValue, ref tempMaxValue, true);
m_SerieDimMin[i] = tempMinValue;
m_SerieDimMax[i] = tempMaxValue;
}
if (axis.IsCategory())
{
m_SerieDimMax[i] = axis.data.Count > 0 ? axis.data.Count - 1 : 0;
m_SerieDimMin[i] = 0;
}
else if (axis.minMaxType == Axis.AxisMinMaxType.Custom)
{
m_SerieDimMin[i] = axis.min;
m_SerieDimMax[i] = axis.max;
}
else if (m_SerieDimMax.ContainsKey(i))
{
var tempMinValue = m_SerieDimMin[i];
var tempMaxValue = m_SerieDimMax[i];
AxisHelper.AdjustMinMaxValue(axis, ref tempMinValue, ref tempMaxValue, true);
m_SerieDimMin[i] = tempMinValue;
m_SerieDimMax[i] = tempMaxValue;
}
}
for (int i = 0; i < component.context.parallelAxes.Count; i++)
{
if (m_SerieDimMax.ContainsKey(i))
@@ -156,8 +169,7 @@ namespace XCharts
m_LastInterval = axis.interval;
chart.m_IsPlayingAnimation = true;
var needCheck = !chart.m_IsPlayingAnimation && axis.context.lastCheckInverse == axis.inverse;
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue, needCheck);
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue);
axis.context.xOffset = 0;
axis.context.yOffset = 0;
axis.context.lastCheckInverse = axis.inverse;

View File

@@ -138,7 +138,11 @@ namespace XCharts
GetChartComponent<Title>().text = GetType().Name;
m_Theme.sharedTheme.CopyTheme(ThemeType.Default);
if (m_Theme.sharedTheme != null)
m_Theme.sharedTheme.CopyTheme(ThemeType.Default);
else
m_Theme.sharedTheme = XCThemeMgr.GetTheme(ThemeType.Default);
m_Settings = null;
var sizeDelta = rectTransform.sizeDelta;
if (sizeDelta.x < 580 && sizeDelta.y < 300)

View File

@@ -498,100 +498,6 @@ namespace XCharts
posList.Add(ep);
}
public static void GetBezierList(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
Vector3 lsp, Vector3 nep, float smoothness = 2f, float k = 2.0f)
{
float dist = Mathf.Abs(sp.x - ep.x);
Vector3 cp1, cp2;
var dir = (ep - sp).normalized;
var diff = dist / k;
if (lsp == sp)
{
cp1 = sp + dist / k * dir * 1;
cp1.y = sp.y;
cp1 = sp;
}
else
{
cp1 = sp + (ep - lsp).normalized * diff;
}
if (nep == ep) cp2 = ep;
else cp2 = ep - (nep - sp).normalized * diff;
dist = Vector3.Distance(sp, ep);
int segment = (int)(dist / (smoothness <= 0 ? 2f : smoothness));
if (segment < 1) segment = (int)(dist / 0.5f);
if (segment < 4) segment = 4;
GetBezierList2(ref posList, sp, ep, segment, cp1, cp2);
if (posList.Count < 2)
{
posList.Clear();
posList.Add(sp);
posList.Add(ep);
}
}
public static void GetBezierListVertical(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
float smoothness = 2f, float k = 2.0f)
{
Vector3 dir = (ep - sp).normalized;
float dist = Vector3.Distance(sp, ep);
Vector3 cp1 = sp + dist / k * dir * 1;
Vector3 cp2 = sp + dist / k * dir * (k - 1);
cp1.x = sp.x;
cp2.x = ep.x;
int segment = (int)(dist / (smoothness <= 0 ? 2f : smoothness));
GetBezierList2(ref posList, sp, ep, segment, cp1, cp2);
if (posList.Count < 2)
{
posList.Clear();
posList.Add(sp);
posList.Add(ep);
}
}
public static List<Vector3> GetBezierList(Vector3 sp, Vector3 ep, int segment, Vector3 cp)
{
List<Vector3> list = new List<Vector3>();
for (int i = 0; i < segment; i++)
{
list.Add(GetBezier(i / (float)segment, sp, cp, ep));
}
list.Add(ep);
return list;
}
public static void GetBezierList2(ref List<Vector3> posList, Vector3 sp, Vector3 ep, int segment, Vector3 cp,
Vector3 cp2)
{
posList.Clear();
if (posList.Capacity < segment + 1)
{
posList.Capacity = segment + 1;
}
for (int i = 0; i < segment; i++)
{
posList.Add((GetBezier2(i / (float)segment, sp, cp, cp2, ep)));
}
posList.Add(ep);
}
public static Vector3 GetBezier(float t, Vector3 sp, Vector3 cp, Vector3 ep)
{
Vector3 aa = sp + (cp - sp) * t;
Vector3 bb = cp + (ep - cp) * t;
return aa + (bb - aa) * t;
}
public static Vector3 GetBezier2(float t, Vector3 sp, Vector3 p1, Vector3 p2, Vector3 ep)
{
t = Mathf.Clamp01(t);
var oneMinusT = 1f - t;
return oneMinusT * oneMinusT * oneMinusT * sp +
3f * oneMinusT * oneMinusT * t * p1 +
3f * oneMinusT * t * t * p2 +
t * t * t * ep;
}
public static bool IsValueEqualsColor(Color32 color1, Color32 color2)
{
return color1.a == color2.a &&
@@ -896,70 +802,7 @@ namespace XCharts
}
//获取两直线交点
public static Vector3 GetIntersection(Vector3 lineAStart, Vector3 lineAEnd, Vector3 lineBStart,
Vector3 lineBEnd)
{
float x1 = lineAStart.x, y1 = lineAStart.y;
float x2 = lineAEnd.x, y2 = lineAEnd.y;
float x3 = lineBStart.x, y3 = lineBStart.y;
float x4 = lineBEnd.x, y4 = lineBEnd.y;
if (x1 == x2 && x3 == x4 && x1 == x3)
{
return Vector3.zero;
}
if (y1 == y2 && y3 == y4 && y1 == y3)
{
return Vector3.zero;
}
if (x1 == x2 && x3 == x4)
{
return Vector3.zero;
}
if (y1 == y2 && y3 == y4)
{
return Vector3.zero;
}
float x, y;
if (x1 == x2)
{
float m2 = (y4 - y3) / (x4 - x3);
float c2 = -m2 * x3 + y3;
x = x1;
y = c2 + m2 * x1;
}
else if (x3 == x4)
{
float m1 = (y2 - y1) / (x2 - x1);
float c1 = -m1 * x1 + y1;
x = x3;
y = c1 + m1 * x3;
}
else
{
float m1 = (y2 - y1) / (x2 - x1);
float c1 = -m1 * x1 + y1;
float m2 = (y4 - y3) / (x4 - x3);
float c2 = -m2 * x3 + y3;
x = (c1 - c2) / (m2 - m1);
y = c2 + m2 * x;
}
if (IsInsideLine(lineAStart, lineAEnd, x, y) &&
IsInsideLine(lineBStart, lineBEnd, x, y))
{
return new Vector3(x, y, 0);
}
return Vector3.zero;
}
private static bool IsInsideLine(Vector3 start, Vector3 end, float x, float y)
{
return ((x >= start.x && x <= end.x)
|| (x >= end.x && x <= start.x))
&& ((y >= start.y && y <= end.y)
|| (y >= end.y && y <= start.y));
}
public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
{

View File

@@ -124,8 +124,8 @@ namespace XCharts
var isPercentStack = SeriesHelper.IsPercentStack<Bar>(chart.series, serie.stack);
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double xMinValue = xAxis.GetCurrMinValue(dataChangeDuration);
double xMaxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
double xMinValue = xAxis.context.minValue;
double xMaxValue = xAxis.context.maxValue;
var isAllBarEnd = true;
serie.containerIndex = grid.index;
serie.containterInstanceId = grid.instanceId;
@@ -266,10 +266,10 @@ namespace XCharts
var isPercentStack = SeriesHelper.IsPercentStack<Bar>(chart.series, serie.stack);
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double xMinValue = xAxis.GetCurrMinValue(dataChangeDuration);
double xMaxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
double yMinValue = yAxis.GetCurrMinValue(dataChangeDuration);
double yMaxValue = yAxis.GetCurrMaxValue(dataChangeDuration);
double xMinValue = xAxis.context.minValue;
double xMaxValue = xAxis.context.maxValue;
double yMinValue = yAxis.context.minValue;
double yMaxValue = yAxis.context.maxValue;
var isAllBarEnd = true;
serie.containerIndex = grid.index;
serie.containterInstanceId = grid.instanceId;

View File

@@ -42,8 +42,8 @@ namespace XCharts
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double yMinValue = yAxis.GetCurrMinValue(dataChangeDuration);
double yMaxValue = yAxis.GetCurrMaxValue(dataChangeDuration);
double yMinValue = yAxis.context.minValue;
double yMaxValue = yAxis.context.maxValue;
var isAllBarEnd = true;
var isYAxis = false;
serie.containerIndex = grid.index;

View File

@@ -562,10 +562,10 @@ namespace XCharts
return 0;
}
float xDataHig, yDataHig;
double xMinValue = xAxis.GetCurrMinValue(duration);
double xMaxValue = xAxis.GetCurrMaxValue(duration);
double yMinValue = yAxis.GetCurrMinValue(duration);
double yMaxValue = yAxis.GetCurrMaxValue(duration);
double xMinValue = xAxis.context.minValue;
double xMaxValue = xAxis.context.maxValue;
double yMinValue = yAxis.context.minValue;
double yMaxValue = yAxis.context.maxValue;
if (xAxis.IsValue() || xAxis.IsLog() || xAxis.IsTime())
{
var axisLineWidth = xAxis.axisLine.GetWidth(chart.theme.axis.lineWidth);
@@ -690,8 +690,8 @@ namespace XCharts
var rate = LineHelper.GetDataAverageRate(serie, grid, maxCount, true);
var dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
double xMinValue = xAxis.GetCurrMinValue(dataChangeDuration);
double xMaxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
double xMinValue = xAxis.context.minValue;
double xMaxValue = xAxis.context.maxValue;
serie.containerIndex = grid.index;
serie.containterInstanceId = grid.instanceId;
@@ -1171,7 +1171,8 @@ namespace XCharts
var eindex = 0;
var sp = LineHelper.GetStartPos(points, ref sindex, serie.ignoreLineBreak);
var ep = LineHelper.GetEndPos(points, ref eindex, serie.ignoreLineBreak);
var cross = ChartHelper.GetIntersection(lp, np, zeroPos, aep);
var cross = Vector3.zero;
UGLHelper.GetIntersection(lp, np, zeroPos, aep, ref cross);
if (cross == Vector3.zero || smoothDownPoints.Count <= 3)
{
@@ -1194,13 +1195,15 @@ namespace XCharts
var axisUpEnd = axisUpStart + (isYAxis ? Vector3.up * grid.context.height : Vector3.right * grid.context.width);
var axisDownStart = zeroPos - (isYAxis ? Vector3.right : Vector3.up) * axisLineWidth;
var axisDownEnd = axisDownStart + (isYAxis ? Vector3.up * grid.context.height : Vector3.right * grid.context.width);
var luPos = ChartHelper.GetIntersection(sp1, ep1, axisUpStart, axisUpEnd);
var luPos = Vector3.zero;
UGLHelper.GetIntersection(sp1, ep1, axisUpStart, axisUpEnd, ref cross);
var ecount = smoothPoints.Count - 2;
if (ecount < 0) ecount = 0;
sp1 = smoothPoints[0];
ep1 = smoothPoints[ecount];
var rdPos = ChartHelper.GetIntersection(sp1, ep1, axisDownStart, axisDownEnd);
var rdPos = Vector3.zero;
UGLHelper.GetIntersection(sp1, ep1, axisDownStart, axisDownEnd, ref rdPos);
if ((isYAxis && lp.x >= zeroPos.x) || (!isYAxis && lp.y >= zeroPos.y))
{
@@ -1471,9 +1474,9 @@ namespace XCharts
}
if (isYAxis)
ChartHelper.GetBezierListVertical(ref bezierPoints, lp, np, settings.lineSmoothness, settings.lineSmoothStyle);
UGLHelper.GetBezierListVertical(ref bezierPoints, lp, np, settings.lineSmoothness, settings.lineSmoothStyle);
else
ChartHelper.GetBezierList(ref bezierPoints, lp, np, llp, nnp, settings.lineSmoothness, settings.lineSmoothStyle);
UGLHelper.GetBezierList(ref bezierPoints, lp, np, llp, nnp, settings.lineSmoothness, settings.lineSmoothStyle);
Vector3 start, to;
if (serie.lineType == LineType.SmoothDash)

View File

@@ -34,9 +34,8 @@ namespace XCharts
var startAngle = m_AngleAxis.startAngle;
var radius = m_Polar.context.radius;
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var min = m_RadiusAxis.GetCurrMinValue(dataChangeDuration);
var max = m_RadiusAxis.GetCurrMaxValue(dataChangeDuration);
var min = m_RadiusAxis.context.minValue;
var max = m_RadiusAxis.context.maxValue;
var firstSerieData = datas[0];
var startPos = GetPolarPos(m_Polar, m_AngleAxis, firstSerieData, min, max, radius);
var nextPos = Vector3.zero;

View File

@@ -5,6 +5,7 @@
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
@@ -19,13 +20,20 @@ namespace XCharts
public static void AddDefaultSerie(BaseChart chart, string serieName)
{
var serie = chart.AddSerie<Parallel>(serieName);
serie.itemStyle.show = true;
serie.itemStyle.borderWidth = 1;
serie.itemStyle.borderColor = Color.clear;
serie.emphasis.show = true;
serie.emphasis.itemStyle.show = true;
serie.emphasis.itemStyle.borderWidth = 1;
serie.emphasis.itemStyle.borderColor = Color.black;
serie.lineStyle.width = 0.8f;
serie.lineStyle.opacity = 0.6f;
for (int i = 0; i < 100; i++)
{
var data = new List<double>(){
Random.Range(0f,50f),
Random.Range(0f,100f),
Random.Range(0f,1000f),
Random.Range(0,5),
};
serie.AddData(data, "data" + i);
}
chart.RefreshChart();
}
}
}

View File

@@ -5,6 +5,7 @@
/* */
/************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XUGL;
@@ -14,6 +15,8 @@ namespace XCharts
[UnityEngine.Scripting.Preserve]
internal sealed class ParallelHandler : SerieHandler<Parallel>
{
private List<Vector3> m_Points = new List<Vector3>();
public override void Update()
{
base.Update();
@@ -28,36 +31,11 @@ namespace XCharts
private void UpdateSerieContext()
{
if (!chart.isPointerInChart)
return;
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
serie.context.pointerItemDataIndex = -1;
serie.context.pointerEnter = false;
foreach (var serieData in serie.data)
{
var dist = Vector3.Distance(chart.pointerPos, serieData.runtimePosition);
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
var symbolSize = symbol.GetSize(serieData.data, themeSymbolSize);
if (dist <= symbolSize)
{
serie.context.pointerItemDataIndex = serieData.index;
serie.context.pointerEnter = true;
serieData.highlighted = true;
chart.RefreshTopPainter();
}
else
{
serieData.highlighted = false;
}
}
}
private void DrawParallelSerie(VertexHelper vh, int colorIndex, Parallel serie)
{
if (!serie.show) return;
if (serie.animation.HasFadeOut()) return;
var parallel = chart.GetChartComponent<ParallelCoord>(serie.parallelIndex);
@@ -69,40 +47,90 @@ namespace XCharts
return;
var animationIndex = serie.animation.GetCurrIndex();
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
var dataChanging = false;
var isHorizonal = parallel.orient == Orient.Horizonal;
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, colorIndex, false);
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
float currDetailProgress = parallel.context.x;
float totalDetailProgress = parallel.context.x + parallel.context.width;
if (serie.animation.alongWithLinePath)
{
//TODO:
}
serie.animation.InitProgress(0, currDetailProgress, totalDetailProgress);
float currDetailProgress = !isHorizonal
? parallel.context.x
: parallel.context.y;
float totalDetailProgress = !isHorizonal
? parallel.context.x + parallel.context.width
: parallel.context.y + parallel.context.height;
serie.animation.InitProgress(serie.showDataDimension, currDetailProgress, totalDetailProgress);
serie.animation.SetDataFinish(0);
serie.dataPoints.Clear();
serie.containerIndex = parallel.index;
serie.containterInstanceId = parallel.instanceId;
Vector3 sp, np;
var currProgress = serie.animation.GetCurrDetail();
var isSmooth = serie.lineType == LineType.Smooth;
foreach (var serieData in serie.data)
{
sp = GetPos(parallel, 0, serieData.data[0], isHorizonal);
m_Points.Clear();
var count = Mathf.Min(axisCount, serieData.data.Count);
for (int i = 1; i < count; i++)
var lp = Vector3.zero;
for (int i = 0; i < count; i++)
{
np = GetPos(parallel, i, serieData.data[i], isHorizonal);
UGL.DrawLine(vh, sp, np, lineWidth, lineColor);
sp = np;
if (animationIndex >= 0 && i > animationIndex) continue;
var pos = GetPos(parallel, i, serieData.data[i], isHorizonal);
if (!isHorizonal)
{
if (isSmooth)
{
m_Points.Add(pos);
}
else if (pos.x <= currProgress)
{
m_Points.Add(pos);
serie.animation.SetDataFinish(i);
}
else
{
var currProgressStart = new Vector3(currProgress, parallel.context.y - 50);
var currProgressEnd = new Vector3(currProgress, parallel.context.y + parallel.context.height + 50);
var intersectionPos = Vector3.zero;
if (UGLHelper.GetIntersection(lp, pos, currProgressStart, currProgressEnd, ref intersectionPos))
m_Points.Add(intersectionPos);
else
m_Points.Add(pos);
break;
}
}
else
{
if (isSmooth)
{
m_Points.Add(pos);
}
else if (pos.y <= currProgress)
{
m_Points.Add(pos);
serie.animation.SetDataFinish(i);
}
else
{
var currProgressStart = new Vector3(parallel.context.x - 50, currProgress);
var currProgressEnd = new Vector3(parallel.context.x + parallel.context.width + 50, currProgress);
var intersectionPos = Vector3.zero;
if (UGLHelper.GetIntersection(lp, pos, currProgressStart, currProgressEnd, ref intersectionPos))
m_Points.Add(intersectionPos);
else
m_Points.Add(pos);
break;
}
}
lp = pos;
}
}
if (dataChanging)
{
chart.RefreshPainter(serie);
if (isSmooth)
UGL.DrawCurves(vh, m_Points, lineWidth, lineColor, chart.settings.lineSmoothness, currProgress, isHorizonal);
else
UGL.DrawLine(vh, m_Points, lineWidth, lineColor, isSmooth);
}
if (!serie.animation.IsFinish())
{

View File

@@ -126,6 +126,48 @@ namespace XUGL
DrawTriangle(vh, dnPos, upPos1, upPos2, color);
}
}
public static void DrawLine(VertexHelper vh, List<Vector3> points, float width, Color32 color, bool smooth)
{
if (points.Count < 2) return;
else if (points.Count <= 2)
{
DrawLine(vh, points[0], points[1], width, color);
}
else if (smooth)
{
DrawCurves(vh, points, width, color, 2);
}
else
{
var lineLT = Vector3.zero;
var lineLB = Vector3.zero;
var ltp = Vector3.zero;
var lbp = Vector3.zero;
var ntp = Vector3.zero;
var nbp = Vector3.zero;
var itp = Vector3.zero;
var ibp = Vector3.zero;
for (int i = 1; i < points.Count - 1; i++)
{
UGLHelper.GetLinePoints(points[i - 1], points[i], points[i + 1], width,
ref ltp, ref lbp, ref ntp, ref nbp, ref itp, ref ibp);
if (i == 1)
{
lineLT = ltp;
lineLB = lbp;
}
DrawQuadrilateral(vh, lineLB, ibp, itp, lineLT, color);
lineLT = itp;
lineLB = ibp;
}
DrawQuadrilateral(vh, lineLB, nbp, ntp, lineLT, color);
}
}
/// <summary>
/// Draw a dash line. 画虚线
/// </summary>
@@ -1619,17 +1661,58 @@ namespace XUGL
var dist = Vector3.Distance(sp, ep);
var segment = (int)(dist / (smoothness <= 0 ? 2f : smoothness));
UGLHelper.GetBezierList2(ref s_CurvesPosList, sp, ep, segment, cp1, cp2);
if (s_CurvesPosList.Count > 1)
DrawCurvesInternal(vh, s_CurvesPosList, lineWidth, lineColor);
}
public static void DrawCurves(VertexHelper vh, List<Vector3> points, float width, Color32 color,
float smoothness, float currProgress = float.PositiveInfinity, bool isYAxis = false)
{
for (int i = 0; i < points.Count - 1; i++)
{
var start = s_CurvesPosList[0];
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;
if (currProgress != float.PositiveInfinity)
{
var smoothness2 = 0f;
if (isYAxis)
smoothness2 = ep.y <= currProgress ? smoothness : smoothness * 0.5f;
else
smoothness2 = ep.x <= currProgress ? smoothness : smoothness * 0.5f;
UGLHelper.GetBezierList(ref s_CurvesPosList, sp, ep, lsp, nep, smoothness2);
}
else
{
UGLHelper.GetBezierList(ref s_CurvesPosList, sp, ep, lsp, nep, smoothness);
}
DrawCurvesInternal(vh, s_CurvesPosList, width, color, currProgress, isYAxis);
}
}
private static void DrawCurvesInternal(VertexHelper vh, List<Vector3> curvesPosList, float lineWidth,
Color32 lineColor, float currProgress = float.PositiveInfinity, bool isYAxis = false)
{
if (curvesPosList.Count > 1)
{
var start = curvesPosList[0];
var to = Vector3.zero;
var dir = s_CurvesPosList[1] - start;
var dir = curvesPosList[1] - start;
var diff = Vector3.Cross(dir, Vector3.forward).normalized * lineWidth;
var startUp = start - diff;
var startDn = start + diff;
for (int i = 1; i < s_CurvesPosList.Count; i++)
for (int i = 1; i < curvesPosList.Count; i++)
{
to = s_CurvesPosList[i];
to = curvesPosList[i];
if (currProgress != float.PositiveInfinity)
{
if (isYAxis && to.y > currProgress)
break;
if (!isYAxis && to.x > currProgress)
break;
}
diff = Vector3.Cross(to - start, Vector3.forward).normalized * lineWidth;
var toUp = to - diff;
var toDn = to + diff;

View File

@@ -14,53 +14,66 @@ namespace XUGL
{
public static bool IsValueEqualsColor(Color32 color1, Color32 color2)
{
return color1.a == color2.a &&
color1.b == color2.b &&
color1.g == color2.g &&
color1.r == color2.r;
return color1.a == color2.a
&& color1.b == color2.b
&& color1.g == color2.g
&& color1.r == color2.r;
}
public static bool IsValueEqualsColor(Color color1, Color color2)
{
return color1.a == color2.a &&
color1.b == color2.b &&
color1.g == color2.g &&
color1.r == color2.r;
return color1.a == color2.a
&& color1.b == color2.b
&& color1.g == color2.g
&& color1.r == color2.r;
}
public static bool IsValueEqualsString(string str1, string str2)
{
if (str1 == null && str2 == null) return true;
else if (str1 != null && str2 != null) return str1.Equals(str2);
if (str1 == null && str2 == null)
return true;
else if (str1 != null && str2 != null)
return str1.Equals(str2);
else return false;
}
public static bool IsValueEqualsVector2(Vector2 v1, Vector2 v2)
{
return v1.x == v2.x && v1.y == v2.y;
return v1.x == v2.x
&& v1.y == v2.y;
}
public static bool IsValueEqualsVector3(Vector3 v1, Vector3 v2)
{
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
return v1.x == v2.x
&& v1.y == v2.y
&& v1.z == v2.z;
}
public static bool IsValueEqualsList<T>(List<T> list1, List<T> list2)
{
if (list1 == null || list2 == null) return false;
if (list1.Count != list2.Count) return false;
if (list1 == null || list2 == null)
return false;
if (list1.Count != list2.Count)
return false;
for (int i = 0; i < list1.Count; i++)
{
if (list1[i] == null && list2[i] == null) { }
if (list1[i] == null && list2[i] == null)
{
}
else
{
if (list1[i] != null)
{
if (!list1[i].Equals(list2[i])) return false;
if (!list1[i].Equals(list2[i]))
return false;
}
else
{
if (!list2[i].Equals(list1[i])) return false;
if (!list2[i].Equals(list1[i]))
return false;
}
}
}
@@ -69,17 +82,25 @@ namespace XUGL
public static bool IsClearColor(Color32 color)
{
return color.a == 0 && color.b == 0 && color.g == 0 && color.r == 0;
return color.a == 0
&& color.b == 0
&& color.g == 0
&& color.r == 0;
}
public static bool IsClearColor(Color color)
{
return color.a == 0 && color.b == 0 && color.g == 0 && color.r == 0;
return color.a == 0
&& color.b == 0
&& color.g == 0
&& color.r == 0;
}
public static bool IsZeroVector(Vector3 pos)
{
return pos.x == 0 && pos.y == 0 && pos.z == 0;
return pos.x == 0
&& pos.y == 0
&& pos.z == 0;
}
public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
@@ -113,6 +134,12 @@ namespace XUGL
if (segment < 1) segment = (int)(dist / 0.5f);
if (segment < 4) segment = 4;
GetBezierList2(ref posList, sp, ep, segment, cp1, cp2);
if (posList.Count < 2)
{
posList.Clear();
posList.Add(sp);
posList.Add(ep);
}
}
public static void GetBezierListVertical(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
@@ -126,6 +153,12 @@ namespace XUGL
cp2.x = ep.x;
int segment = (int)(dist / (smoothness <= 0 ? 2f : smoothness));
GetBezierList2(ref posList, sp, ep, segment, cp1, cp2);
if (posList.Count < 2)
{
posList.Clear();
posList.Add(sp);
posList.Add(ep);
}
}
public static List<Vector3> GetBezierList(Vector3 sp, Vector3 ep, int segment, Vector3 cp)
@@ -139,8 +172,8 @@ namespace XUGL
return list;
}
public static void GetBezierList2(ref List<Vector3> posList, Vector3 sp, Vector3 ep, int segment, Vector3 cp,
Vector3 cp2)
public static void GetBezierList2(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
int segment, Vector3 cp, Vector3 cp2)
{
posList.Clear();
if (posList.Capacity < segment + 1)
@@ -180,17 +213,12 @@ namespace XUGL
public static Vector3 GetVertialDire(Vector3 dire)
{
if (dire.x == 0)
{
return new Vector3(-1, 0, 0);
}
if (dire.y == 0)
{
return new Vector3(0, -1, 0);
}
else
{
return new Vector3(-dire.y / dire.x, 1, 0).normalized;
}
}
/// <summary>
@@ -213,7 +241,77 @@ namespace XUGL
public static Vector3 GetPos(Vector3 center, float radius, float angle, bool isDegree = false)
{
angle = isDegree ? angle * Mathf.Deg2Rad : angle;
return new Vector3(center.x + radius * Mathf.Sin(angle), center.y + radius * Mathf.Cos(angle));
return new Vector3(center.x + radius * Mathf.Sin(angle),
center.y + radius * Mathf.Cos(angle));
}
/// <summary>
/// 获得两直线的交点
/// </summary>
/// <param name="p1">线段1起点</param>
/// <param name="p2">线段1终点</param>
/// <param name="p3">线段2起点</param>
/// <param name="p4">线段2终点</param>
/// <param name="intersection">相交点。当不想交时默认为 Vector3.zero </param>
/// <returns>相交则返回 true, 否则返回 false</returns>
public static bool GetIntersection(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, ref Vector3 intersection)
{
intersection = Vector3.zero;
var d = (p2.x - p1.x) * (p4.y - p3.y) - (p2.y - p1.y) * (p4.x - p3.x);
if (d == 0)
return false;
var u = ((p3.x - p1.x) * (p4.y - p3.y) - (p3.y - p1.y) * (p4.x - p3.x)) / d;
var v = ((p3.x - p1.x) * (p2.y - p1.y) - (p3.y - p1.y) * (p2.x - p1.x)) / d;
if (u < 0 || u > 1 || v < 0 || v > 1)
return false;
intersection.x = p1.x + u * (p2.x - p1.x);
intersection.y = p1.y + u * (p2.y - p1.y);
return true;
}
/// <summary>
/// 三个点画线段所需要的六个关键点
/// </summary>
/// <param name="lp">上一个点</param>
/// <param name="cp">当前点</param>
/// <param name="np">下一个点</param>
/// <param name="width">线段宽度</param>
/// <param name="ltp">上一个点的上角点</param>
/// <param name="lbp">上一个点的下角点</param>
/// <param name="ntp">下一个点的上角点</param>
/// <param name="nbp">下一个点的下角点</param>
/// <param name="itp">交汇点的上角点</param>
/// <param name="ibp">交汇点的下角点</param>
internal static void GetLinePoints(Vector3 lp, Vector3 cp, Vector3 np, float width,
ref Vector3 ltp, ref Vector3 lbp,
ref Vector3 ntp, ref Vector3 nbp,
ref Vector3 itp, ref Vector3 ibp)
{
var dir1 = (cp - lp).normalized;
var dir2 = (cp - np).normalized;
var dir1v = Vector3.Cross(dir1, Vector3.forward).normalized;
var dir2v = Vector3.Cross(dir2, Vector3.back).normalized;
ltp = lp + dir1v * width;
lbp = lp - dir1v * width;
ntp = np + dir2v * width;
nbp = np - dir2v * width;
var ldist = 1.3f * Vector3.Distance(cp, lp) * dir1;
var rdist = 1.3f * Vector3.Distance(cp, np) * dir2;
if (!UGLHelper.GetIntersection(ltp, ltp + ldist, ntp, ntp + rdist, ref itp))
{
itp = cp + dir1v * width;
}
if (!UGLHelper.GetIntersection(lbp, lbp + ldist, nbp, nbp + rdist, ref ibp))
{
ibp = cp - dir1v * width;
}
}
}
}