AirControl  1.3.0
Open Source, Modular, and Extensible Flight Simulator For Deep Learning Research
PolarChart.cs
1 /************************************************/
2 /* */
3 /* Copyright (c) 2018 - 2021 monitor1394 */
4 /* https://github.com/monitor1394 */
5 /* */
6 /************************************************/
7 
8 using System;
9 using System.Collections.Generic;
10 using UnityEngine;
11 using UnityEngine.UI;
12 using XUGL;
13 
14 namespace XCharts
15 {
16  [AddComponentMenu("XCharts/PolarChart", 21)]
17  [ExecuteInEditMode]
18  [RequireComponent(typeof(RectTransform))]
19  [DisallowMultipleComponent]
20  public partial class PolarChart : BaseChart
21  {
22  public Polar GetPolar(int index)
23  {
24  if (index >= 0 && index < m_Polars.Count) return m_Polars[index];
25  else return null;
26  }
27 
28  protected override void InitComponent()
29  {
30  base.InitComponent();
31  if (m_Polars.Count == 0) m_Polars = new List<Polar>() { Polar.defaultPolar };
32  if (m_RadiusAxes.Count == 0) m_RadiusAxes = new List<RadiusAxis>() { RadiusAxis.defaultRadiusAxis };
33  if (m_AngleAxes.Count == 0) m_AngleAxes = new List<AngleAxis>() { AngleAxis.defaultAngleAxis };
34  CheckMinMaxValue();
35  UpdateRuntimeValue();
36  InitPolars();
37  InitRadiusAxes();
38  InitAngleAxes();
40  tooltip.runtimeAngle = -1;
41  }
42 
43 #if UNITY_EDITOR
44  protected override void Reset()
45  {
46  base.Reset();
47  m_Polars.Clear();
48  m_RadiusAxes.Clear();
49  m_AngleAxes.Clear();
50  InitComponent();
51  title.text = "PolarChart";
52  tooltip.type = Tooltip.Type.Corss;
53  RemoveData();
54  ResetValuePolar();
55  Awake();
56  }
57 
58  private void ResetValuePolar()
59  {
60  m_AngleAxes[0].type = Axis.AxisType.Value;
61  m_AngleAxes[0].minMaxType = Axis.AxisMinMaxType.Custom;
62  m_AngleAxes[0].min = 0;
63  m_AngleAxes[0].max = 360;
64  AddSerie(SerieType.Line, "line1");
65  for (int i = 0; i <= 360; i++)
66  {
67  var t = i / 180f * Mathf.PI;
68  var r = Mathf.Sin(2 * t) * Mathf.Cos(2 * t) * 2;
69  AddData(0, Mathf.Abs(r), i);
70  }
71  }
72 
73  private void ResetCategoryPolar()
74  {
75  m_AngleAxes[0].type = Axis.AxisType.Category;
76  AddSerie(SerieType.Bar, "line1");
77  for (int i = 0; i <= 13; i++)
78  {
79  m_AngleAxes[0].AddData("bar" + i);
80  AddData(0, UnityEngine.Random.Range(0, 10));
81  }
82  }
83 #endif
84 
85  protected override void SetAllComponentDirty()
86  {
87  base.SetAllComponentDirty();
88  foreach (var axis in m_RadiusAxes) axis.SetAllDirty();
89  foreach (var axis in m_AngleAxes) axis.SetAllDirty();
90  CheckMinMaxValue();
91  }
92 
93  protected override void OnSizeChanged()
94  {
95  base.OnSizeChanged();
96  foreach (var axis in m_RadiusAxes) axis.SetAllDirty();
97  foreach (var axis in m_AngleAxes) axis.SetAllDirty();
98  UpdateRuntimeValue();
99  }
100 
101  private void InitPolars()
102  {
103  for (int i = 0; i < m_Polars.Count; i++)
104  {
105  m_Polars[i].index = i;
106  }
107  }
108 
109  private void InitRadiusAxes()
110  {
111  for (int i = 0; i < m_RadiusAxes.Count; i++)
112  {
113  var radiusAxis = m_RadiusAxes[i];
114  radiusAxis.index = i;
115  InitRadiusAxis(radiusAxis);
116  }
117  }
118 
119  private void InitRadiusAxis(RadiusAxis axis)
120  {
121  var m_Polar = GetPolar(axis.index);
122  if (m_Polars == null) return;
123  var m_AngleAxis = GetAngleAxis(m_Polar.index);
124  if (m_AngleAxis == null) return;
125  PolarHelper.UpdatePolarCenter(m_Polar, m_ChartPosition, m_ChartWidth, m_ChartHeight);
126  axis.runtimeAxisLabelList.Clear();
127  var radius = m_Polar.runtimeRadius;
128  var objName = "axis_radius" + axis.index;
129  var axisObj = ChartHelper.AddObject(objName, transform, graphAnchorMin,
130  graphAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
131  axisObj.transform.localPosition = Vector3.zero;
132  axisObj.SetActive(axis.show && axis.axisLabel.show);
133  axisObj.hideFlags = chartHideFlags;
134  ChartHelper.HideAllObject(axisObj);
135  var textStyle = axis.axisLabel.textStyle;
136  var splitNumber = AxisHelper.GetSplitNumber(axis, radius, null);
137  var totalWidth = 0f;
138  var startAngle = m_AngleAxis.runtimeStartAngle;
139  var cenPos = m_Polar.runtimeCenterPos;
140  var txtHig = textStyle.GetFontSize(m_Theme.axis) + 2;
141  var dire = ChartHelper.GetDire(startAngle, true).normalized;
142  var tickWidth = axis.axisTick.GetLength(m_Theme.radiusAxis.tickWidth);
143  var tickVetor = ChartHelper.GetVertialDire(dire)
144  * (tickWidth + axis.axisLabel.margin);
145  for (int i = 0; i < splitNumber; i++)
146  {
147  var labelWidth = AxisHelper.GetScaleWidth(axis, radius, i, null);
148  var inside = axis.axisLabel.inside;
149  var isPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
150  var labelName = AxisHelper.GetLabelName(axis, radius, i, axis.runtimeMinValue, axis.runtimeMaxValue,
151  null, isPercentStack);
152  var label = ChartHelper.AddAxisLabelObject(splitNumber, i, objName + i, axisObj.transform, new Vector2(0.5f, 0.5f),
153  new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(labelWidth, txtHig), axis, theme.axis,
154  labelName);
155  if (i == 0) axis.axisLabel.SetRelatedText(label.label, labelWidth);
156  label.label.SetAlignment(textStyle.GetAlignment(TextAnchor.MiddleCenter));
157  label.SetText(labelName);
158  var pos = ChartHelper.GetPos(cenPos, totalWidth, startAngle, true) + tickVetor;
159  label.SetPosition(pos);
160  AxisHelper.AdjustRadiusAxisLabelPos(label.label, pos, cenPos, txtHig, Vector3.zero);
161  axis.runtimeAxisLabelList.Add(label);
162 
163  totalWidth += labelWidth;
164  }
166  {
167  Vector2 privot = new Vector2(0.5f, 1);
168  var labelParent = tooltip.runtimeGameObject.transform;
169  var labelName = ChartCached.GetAxisTooltipLabel(objName);
170  GameObject labelObj = ChartHelper.AddTooltipLabel(labelName, labelParent, m_Theme, privot);
171  axis.SetTooltipLabel(labelObj);
172  axis.SetTooltipLabelColor(m_Theme.tooltip.labelBackgroundColor, m_Theme.tooltip.labelTextColor);
173  axis.SetTooltipLabelActive(axis.show && tooltip.show && tooltip.type == Tooltip.Type.Corss);
174  }
175  }
176 
177  private AngleAxis GetAngleAxis(int polarIndex)
178  {
179  foreach (var axis in m_AngleAxes)
180  {
181  if (axis.polarIndex == polarIndex) return axis;
182  }
183  return null;
184  }
185  private RadiusAxis GetRadiusAxis(int polarIndex)
186  {
187  foreach (var axis in m_RadiusAxes)
188  {
189  if (axis.polarIndex == polarIndex) return axis;
190  }
191  return null;
192  }
193 
194  private void InitAngleAxes()
195  {
196  for (int i = 0; i < m_AngleAxes.Count; i++)
197  {
198  var angleAxis = m_AngleAxes[i];
199  angleAxis.index = i;
200  InitAngleAxis(angleAxis);
201  }
202  }
203 
204  private void InitAngleAxis(AngleAxis axis)
205  {
206  var m_Polar = GetPolar(axis.polarIndex);
207  if (m_Polars == null) return;
208  PolarHelper.UpdatePolarCenter(m_Polar, m_ChartPosition, m_ChartWidth, m_ChartHeight);
209  var radius = m_Polar.runtimeRadius;
210  axis.runtimeAxisLabelList.Clear();
211 
212  string objName = "axis_angle" + axis.index;
213  var axisObj = ChartHelper.AddObject(objName, transform, graphAnchorMin,
214  graphAnchorMax, chartPivot, new Vector2(chartWidth, chartHeight));
215  axisObj.transform.localPosition = Vector3.zero;
216  axisObj.SetActive(axis.show);
217  axisObj.hideFlags = chartHideFlags;
218  ChartHelper.HideAllObject(axisObj);
219  var splitNumber = AxisHelper.GetSplitNumber(axis, radius, null);
220  var totalAngle = axis.runtimeStartAngle;
221  var total = 360;
222  var cenPos = m_Polar.runtimeCenterPos;
223  var txtHig = axis.axisLabel.textStyle.GetFontSize(m_Theme.axis) + 2;
224  var margin = axis.axisLabel.margin;
225  var isCategory = axis.IsCategory();
226  var isPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
227  for (int i = 0; i < splitNumber; i++)
228  {
229  float scaleAngle = AxisHelper.GetScaleWidth(axis, total, i, null);
230  bool inside = axis.axisLabel.inside;
231  var labelName = AxisHelper.GetLabelName(axis, total, i, axis.runtimeMinValue, axis.runtimeMaxValue,
232  null, isPercentStack);
233  var label = ChartHelper.AddAxisLabelObject(splitNumber, i, objName + i, axisObj.transform, new Vector2(0.5f, 0.5f),
234  new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(scaleAngle, txtHig), axis,
235  theme.axis, labelName);
236  label.label.SetAlignment(axis.axisLabel.textStyle.GetAlignment(TextAnchor.MiddleCenter));
237  var pos = ChartHelper.GetPos(cenPos, radius + margin,
238  isCategory ? (totalAngle + scaleAngle / 2) : totalAngle, true);
239  AxisHelper.AdjustCircleLabelPos(label, pos, cenPos, txtHig, Vector3.zero);
240  if (i == 0) axis.axisLabel.SetRelatedText(label.label, scaleAngle);
241  axis.runtimeAxisLabelList.Add(label);
242 
243  totalAngle += scaleAngle;
244  }
246  {
247  Vector2 privot = new Vector2(0.5f, 0.5f);
248  var labelParent = tooltip.runtimeGameObject.transform;
249  GameObject labelObj = ChartHelper.AddTooltipLabel(ChartCached.GetAxisTooltipLabel(objName), labelParent,
250  m_Theme, privot, privot, privot, new Vector2(10, txtHig));
251  axis.SetTooltipLabel(labelObj);
252  axis.SetTooltipLabelColor(m_Theme.tooltip.labelBackgroundColor, m_Theme.tooltip.labelTextColor);
253  axis.SetTooltipLabelActive(axis.show && tooltip.show && tooltip.type == Tooltip.Type.Corss);
254  }
255  }
256 
257  protected override void Update()
258  {
259  base.Update();
260  CheckMinMaxValue();
261  }
262 
263  private void CheckMinMaxValue()
264  {
265  foreach (var axis in m_RadiusAxes) UpdateAxisMinMaxValue(axis);
266  foreach (var axis in m_AngleAxes) UpdateAxisMinMaxValue(axis);
267  }
268 
269  private void UpdateAxisMinMaxValue(Axis axis, bool updateChart = true)
270  {
271  if (axis.IsCategory() || !axis.show) return;
272  double tempMinValue = 0;
273  double tempMaxValue = 0;
274  if (axis is RadiusAxis)
275  {
276  SeriesHelper.GetXMinMaxValue(m_Series, null, axis.polarIndex, true, axis.inverse, out tempMinValue,
277  out tempMaxValue, true);
278  }
279  else
280  {
281  SeriesHelper.GetYMinMaxValue(m_Series, null, axis.polarIndex, true, axis.inverse, out tempMinValue,
282  out tempMaxValue, true);
283  }
284  AxisHelper.AdjustMinMaxValue(axis, ref tempMinValue, ref tempMaxValue, true);
285  if (tempMinValue != axis.runtimeMinValue || tempMaxValue != axis.runtimeMaxValue)
286  {
287  m_IsPlayingAnimation = true;
288  var needCheck = !m_IsPlayingAnimation && axis.runtimeLastCheckInverse == axis.inverse;
289  axis.UpdateMinValue(tempMinValue, needCheck);
290  axis.UpdateMaxValue(tempMaxValue, needCheck);
291  axis.runtimeZeroXOffset = 0;
292  axis.runtimeZeroYOffset = 0;
293  axis.runtimeLastCheckInverse = axis.inverse;
294  if (updateChart)
295  {
296  UpdateAxisLabelText(axis);
297  RefreshChart();
298  }
299  }
300  if (axis.IsValueChanging(500) && !m_IsPlayingAnimation)
301  {
302  UpdateAxisLabelText(axis);
303  RefreshChart();
304  }
305  }
306 
307  protected void UpdateAxisLabelText(Axis axis)
308  {
309  var polar = GetPolar(axis.polarIndex);
310  var runtimeWidth = axis is RadiusAxis ? polar.runtimeRadius : 360;
311  var isPercentStack = SeriesHelper.IsPercentStack(m_Series, SerieType.Bar);
312  axis.UpdateLabelText(runtimeWidth, null, isPercentStack, 500);
313  }
314 
315  protected override void DrawPainterBase(VertexHelper vh)
316  {
317  base.DrawPainterBase(vh);
318  DrawPolar(vh);
319  DrawAngleAxis(vh);
320  DrawRadiusAxis(vh);
321  DrawSerie(vh);
322  }
323 
324  private void UpdateRuntimeValue()
325  {
326  foreach (var polar in m_Polars)
327  PolarHelper.UpdatePolarCenter(polar, m_ChartPosition, m_ChartWidth, m_ChartHeight);
328  foreach (var axis in m_AngleAxes)
329  axis.runtimeStartAngle = 90 - axis.startAngle;
330  }
331 
332  private void DrawPolar(VertexHelper vh)
333  {
334  UpdateRuntimeValue();
335  foreach (var polar in m_Polars)
336  {
337  if (!ChartHelper.IsClearColor(polar.backgroundColor))
338  {
340  }
341  }
342  }
343 
344  private void DrawRadiusAxis(VertexHelper vh)
345  {
346  foreach (var radiusAxis in m_RadiusAxes)
347  {
348  var polar = GetPolar(radiusAxis.polarIndex);
349  if (polar == null) continue;
350  var angleAxis = GetAngleAxis(polar.index);
351  if (angleAxis == null) continue;
352  var startAngle = angleAxis.runtimeStartAngle;
353  var radius = polar.runtimeRadius;
354  var cenPos = polar.runtimeCenterPos;
355  var size = AxisHelper.GetScaleNumber(radiusAxis, radius, null);
356  var totalWidth = 0f;
357  var dire = ChartHelper.GetDire(startAngle, true).normalized;
358  var tickWidth = radiusAxis.axisTick.GetLength(m_Theme.radiusAxis.tickWidth);
359  var tickLength = radiusAxis.axisTick.GetLength(m_Theme.radiusAxis.tickLength);
360  var tickVetor = ChartHelper.GetVertialDire(dire) * tickLength;
361  for (int i = 0; i < size - 1; i++)
362  {
363  var scaleWidth = AxisHelper.GetScaleWidth(radiusAxis, radius, i);
364  var pos = ChartHelper.GetPos(cenPos, totalWidth, startAngle, true);
366  {
367  var outsideRaidus = totalWidth + radiusAxis.splitLine.GetWidth(m_Theme.radiusAxis.splitLineWidth) * 2;
368  var splitLineColor = radiusAxis.splitLine.GetColor(m_Theme.radiusAxis.splitLineColor);
369  UGL.DrawDoughnut(vh, cenPos, totalWidth, outsideRaidus, splitLineColor, Color.clear);
370  }
372  {
373  UGL.DrawLine(vh, pos, pos + tickVetor, tickWidth, m_Theme.axis.lineColor);
374  }
375  totalWidth += scaleWidth;
376  }
378  {
379  var lineStartPos = polar.runtimeCenterPos - dire * tickWidth;
380  var lineEndPos = polar.runtimeCenterPos + dire * (radius + tickWidth);
381  var lineWidth = radiusAxis.axisLine.GetWidth(m_Theme.polar.lineWidth);
382  UGL.DrawLine(vh, lineStartPos, lineEndPos, lineWidth, m_Theme.axis.lineColor);
383  }
384  }
385  }
386 
387  private void DrawAngleAxis(VertexHelper vh)
388  {
389  foreach (var m_AngleAxis in m_AngleAxes)
390  {
391  var m_Polar = GetPolar(m_AngleAxis.polarIndex);
392  var radius = m_Polar.runtimeRadius;
393  var cenPos = m_Polar.runtimeCenterPos;
394  var total = 360;
395  var size = AxisHelper.GetScaleNumber(m_AngleAxis, total, null);
396  var currAngle = m_AngleAxis.runtimeStartAngle;
397  var tickWidth = m_AngleAxis.axisTick.GetWidth(m_Theme.angleAxis.tickWidth);
398  var tickLength = m_AngleAxis.axisTick.GetLength(m_Theme.angleAxis.tickLength);
399  for (int i = 0; i < size; i++)
400  {
401  var scaleWidth = AxisHelper.GetScaleWidth(m_AngleAxis, total, i);
402  var pos = ChartHelper.GetPos(cenPos, radius, currAngle, true);
403  if (m_AngleAxis.show && m_AngleAxis.splitLine.show)
404  {
405  var splitLineColor = m_AngleAxis.splitLine.GetColor(m_Theme.angleAxis.splitLineColor);
406  var lineWidth = m_AngleAxis.splitLine.GetWidth(m_Theme.angleAxis.splitLineWidth);
407  UGL.DrawLine(vh, cenPos, pos, lineWidth, splitLineColor);
408  }
409  if (m_AngleAxis.show && m_AngleAxis.axisTick.show)
410  {
411  var tickY = radius + tickLength;
412  var tickPos = ChartHelper.GetPos(cenPos, tickY, currAngle, true);
413  UGL.DrawLine(vh, pos, tickPos, tickWidth, m_Theme.axis.lineColor);
414  }
415  currAngle += scaleWidth;
416  }
417  if (m_AngleAxis.show && m_AngleAxis.axisLine.show)
418  {
419  var lineWidth = m_AngleAxis.axisLine.GetWidth(m_Theme.angleAxis.lineWidth);
420  var outsideRaidus = radius + lineWidth * 2;
421  UGL.DrawDoughnut(vh, cenPos, radius, outsideRaidus, m_Theme.axis.lineColor, Color.clear);
422  }
423  }
424  }
425 
426  private void DrawSerie(VertexHelper vh)
427  {
428  for (int i = 0; i < m_Series.Count; i++)
429  {
430  var serie = m_Series.GetSerie(i);
431  serie.index = i;
432  if (!serie.show) continue;
433  switch (serie.type)
434  {
435  case SerieType.Line:
436  DrawPolarLine(vh, serie);
437  break;
438  case SerieType.Bar:
439  break;
440  case SerieType.Scatter:
441  case SerieType.EffectScatter:
442  break;
443  }
444 
445  }
446  DrawPolarLineSymbol(vh);
447  }
448 
449  private void DrawPolarLine(VertexHelper vh, Serie serie)
450  {
451  var m_Polar = GetPolar(serie.polarIndex);
452  if (m_Polar == null) return;
453  var m_AngleAxis = GetAngleAxis(m_Polar.index);
454  var m_RadiusAxis = GetRadiusAxis(m_Polar.index);
455  if (m_AngleAxis == null || m_RadiusAxis == null) return;
456  var startAngle = m_AngleAxis.runtimeStartAngle;
457  var radius = m_Polar.runtimeRadius;
458  var datas = serie.data;
459  if (datas.Count <= 0) return;
460  float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
461  double min = m_RadiusAxis.GetCurrMinValue(dataChangeDuration);
462  double max = m_RadiusAxis.GetCurrMaxValue(dataChangeDuration);
463  var firstSerieData = datas[0];
464  var startPos = GetPolarPos(m_Polar, m_AngleAxis, firstSerieData, min, max, radius);
465  var nextPos = Vector3.zero;
466  var lineColor = SerieHelper.GetLineColor(serie, m_Theme, serie.index, serie.highlighted);
467  var lineWidth = serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
468  float currDetailProgress = 0;
469  float totalDetailProgress = datas.Count;
470  serie.animation.InitProgress(serie.dataPoints.Count, currDetailProgress, totalDetailProgress);
471  serie.animation.SetDataFinish(0);
472  for (int i = 1; i < datas.Count; i++)
473  {
474  if (serie.animation.CheckDetailBreak(i)) break;
475  var serieData = datas[i];
476  nextPos = GetPolarPos(m_Polar, m_AngleAxis, datas[i], min, max, radius);
477  UGL.DrawLine(vh, startPos, nextPos, lineWidth, lineColor);
478  startPos = nextPos;
479  }
480  if (!serie.animation.IsFinish())
481  {
482  serie.animation.CheckProgress(totalDetailProgress);
483  serie.animation.CheckSymbol(serie.symbol.GetSize(null, m_Theme.serie.lineSymbolSize));
484  m_IsPlayingAnimation = true;
485  RefreshChart();
486  }
487  }
488 
489  private void DrawPolarBar(VertexHelper vh, Serie serie)
490  {
491  }
492 
493  private void DrawPolarLineSymbol(VertexHelper vh)
494  {
495  for (int n = 0; n < m_Series.Count; n++)
496  {
497  var serie = m_Series.GetSerie(n);
498  if (!serie.show) continue;
499  if (serie.type != SerieType.Line) continue;
500  var count = serie.dataCount;
501  for (int i = 0; i < count; i++)
502  {
503  var serieData = serie.GetSerieData(i);
504  var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
505  if (ChartHelper.IsIngore(serieData.runtimePosition)) continue;
506  bool highlight = serieData.highlighted || serie.highlighted;
507  if ((!symbol.show || !symbol.ShowSymbol(i, count) || serie.IsPerformanceMode()) && !serieData.highlighted) continue;
508  float symbolSize = highlight
509  ? symbol.GetSelectedSize(serieData.data, m_Theme.serie.lineSymbolSize)
510  : symbol.GetSize(serieData.data, m_Theme.serie.lineSymbolSize);
511  var symbolColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, n, highlight);
512  var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, n, highlight);
513  var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, m_Theme, n, highlight, false);
514  var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, m_Theme, highlight);
515  var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
516  symbolSize = serie.animation.GetSysmbolSize(symbolSize);
517  DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, serieData.runtimePosition, symbolColor,
518  symbolToColor, backgroundColor, symbol.gap, cornerRadius);
519  }
520  }
521  }
522 
523  protected override void DrawTooltip(VertexHelper vh)
524  {
525  if (tooltip.runtimeAngle < 0) return;
526  var m_Polar = GetPolar(tooltip.runtimePolarIndex);
527  var m_AngleAxis = GetAngleAxis(m_Polar.index);
528  var lineColor = TooltipHelper.GetLineColor(tooltip, m_Theme);
529  var lineType = tooltip.lineStyle.GetType(m_Theme.tooltip.lineType);
530  var lineWidth = tooltip.lineStyle.GetWidth(m_Theme.tooltip.lineWidth);
531  var cenPos = m_Polar.runtimeCenterPos;
532  var radius = m_Polar.runtimeRadius;
533  var sp = m_Polar.runtimeCenterPos;
534  var tooltipAngle = tooltip.runtimeAngle + m_AngleAxis.runtimeStartAngle;
535  var ep = ChartHelper.GetPos(sp, radius, tooltipAngle, true);
536 
537  switch (tooltip.type)
538  {
539  case Tooltip.Type.Corss:
540  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
541  var dist = Vector2.Distance(pointerPos, cenPos);
542  if (dist > radius) dist = radius;
543  var outsideRaidus = dist + tooltip.lineStyle.GetWidth(m_Theme.tooltip.lineWidth) * 2;
544  UGL.DrawDoughnut(vh, cenPos, dist, outsideRaidus, lineColor, Color.clear);
545  break;
546  case Tooltip.Type.Line:
547  ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, sp, ep, lineColor);
548  break;
549  case Tooltip.Type.Shadow:
550  UGL.DrawSector(vh, cenPos, radius, lineColor, tooltipAngle - 2, tooltipAngle + 2, settings.cicleSmoothness);
551  break;
552  }
553  }
554 
555  private Vector3 GetPolarPos(Polar m_Polar, AngleAxis m_AngleAxis, SerieData serieData, double min, double max, float polarRadius)
556  {
557  var angle = 0f;
558  if (!m_AngleAxis.clockwise)
559  {
560  angle = m_AngleAxis.runtimeStartAngle - (float)serieData.GetData(1);
561  }
562  else
563  {
564  angle = m_AngleAxis.runtimeStartAngle + (float)serieData.GetData(1);
565  }
566  angle = (angle + 360) % 360;
567  var value = serieData.GetData(0);
568  var radius = (float)((value - min) / (max - min) * polarRadius);
569  serieData.runtimeAngle = angle;
570  serieData.runtimePosition = ChartHelper.GetPos(m_Polar.runtimeCenterPos, radius, angle, true);
571  return serieData.runtimePosition;
572  }
573 
574  protected override void CheckTootipArea(Vector2 local, bool isActivedOther)
575  {
576  if (isActivedOther) return;
577  tooltip.runtimePolarIndex = GetPointerInPoloar(local);
578  if (tooltip.runtimePolarIndex < 0)
579  {
580  tooltip.runtimeAngle = -1;
581  if (tooltip.IsActive())
582  {
583  foreach (var kv in tooltip.runtimeSerieIndex)
584  {
585  var serie = m_Series.GetSerie(kv.Key);
586  foreach (var dataIndex in kv.Value)
587  {
588  serie.GetSerieData(dataIndex).highlighted = false;
589  }
590  }
591  tooltip.ClearSerieDataIndex();
592  tooltip.SetActive(false);
593  foreach (var axis in m_AngleAxes) axis.SetTooltipLabelActive(false);
594  foreach (var axis in m_RadiusAxes) axis.SetTooltipLabelActive(false);
595  RefreshChart();
596  }
597  return;
598  }
599  var m_Polar = GetPolar(tooltip.runtimePolarIndex);
600  var m_AngleAxis = GetAngleAxis(m_Polar.index);
601  tooltip.ClearSerieDataIndex();
602  Vector2 dir = local - new Vector2(m_Polar.runtimeCenterPos.x, m_Polar.runtimeCenterPos.y);
603  float angle = ChartHelper.GetAngle360(Vector2.up, dir);
604 
605  foreach (var serie in m_Series.list)
606  {
607  switch (serie.type)
608  {
609  case SerieType.Line:
610  bool refresh = false;
611  var count = serie.data.Count;
612  SerieHelper.UpdateMinMaxData(serie, 1, -1);
613  var diff = (serie.runtimeDataMax - serie.runtimeDataMin) / (count - 1);
614  for (int j = 0; j < count; j++)
615  {
616  var serieData = serie.data[j];
617  var flag = Math.Abs(serieData.runtimeAngle - angle) < Math.Abs(diff / 2);
618  if (serieData.highlighted != flag)
619  {
620  refresh = true;
621  }
622  serieData.highlighted = flag;
623  if (flag)
624  {
625  tooltip.runtimeAngle = (serieData.runtimeAngle - m_AngleAxis.runtimeStartAngle + 360) % 360;
626  tooltip.AddSerieDataIndex(serie.index, j);
627  }
628  }
629  if (refresh) RefreshChart();
630  break;
631  case SerieType.Bar:
632  break;
633  case SerieType.Scatter:
634  case SerieType.EffectScatter:
635  break;
636  }
637  }
639  UpdateTooltip();
640  if (tooltip.type == Tooltip.Type.Corss)
641  {
642  RefreshChart();
643  }
644  }
645 
646  private int GetPointerInPoloar(Vector2 local)
647  {
648  for (int i = 0; i < m_Polars.Count; i++)
649  {
650  var polar = m_Polars[i];
651  polar.index = i;
652  var dist = Vector2.Distance(local, polar.runtimeCenterPos);
653  if (dist <= polar.runtimeRadius)
654  {
655  return polar.index;
656  }
657  }
658  return -1;
659  }
660 
661  private float GetAngleDiff(SerieData nextData, SerieData serieData, float angle)
662  {
663  var nextAngle = nextData.runtimeAngle;
664  var lastAngle = serieData.runtimeAngle;
665  var diff = 0f;
666  if (nextAngle > 270 && lastAngle < 90)
667  {
668  diff = 360 - nextAngle + lastAngle;
669  }
670  else
671  {
672  diff = nextAngle - lastAngle;
673  }
674  return Mathf.Abs(diff);
675  }
676 
677  protected override void UpdateTooltip()
678  {
679  base.UpdateTooltip();
680  var showTooltip = tooltip.isAnySerieDataIndex();
681  if (showTooltip)
682  {
683  var m_AngleAxis = GetAngleAxis(tooltip.runtimePolarIndex);
684  var content = TooltipHelper.GetPolarFormatterContent(tooltip, this, m_AngleAxis);
685  TooltipHelper.SetContentAndPosition(tooltip, content, chartRect);
686  UdpateTooltipLabel();
687  }
688  tooltip.SetActive(showTooltip);
689  }
690 
691  private void UdpateTooltipLabel()
692  {
693  if (tooltip.type != Tooltip.Type.Corss) return;
694  var m_Polar = GetPolar(tooltip.runtimePolarIndex);
695  if (m_Polar == null) return;
696  var m_AngleAxis = GetAngleAxis(m_Polar.index);
697  var m_RadiusAxis = GetRadiusAxis(m_Polar.index);
698  var cenPos = m_Polar.runtimeCenterPos;
699  var radius = m_Polar.runtimeRadius;
700  m_AngleAxis.SetTooltipLabelActive(true);
701  m_RadiusAxis.SetTooltipLabelActive(true);
702  m_AngleAxis.UpdateTooptipLabelText(ChartCached.FloatToStr(tooltip.runtimeAngle));
703  var tooltipAngle = tooltip.runtimeAngle + m_AngleAxis.runtimeStartAngle;
704  var ep = ChartHelper.GetPos(cenPos, radius + 5, tooltipAngle, true);
705  m_AngleAxis.UpdateTooltipLabelPos(ep);
706 
707  var dist = Vector2.Distance(pointerPos, cenPos);
708  if (dist > radius) dist = radius;
709  double min = m_RadiusAxis.runtimeMinValue;
710  double max = m_RadiusAxis.runtimeMaxValue;
711  var value = min + dist / radius * m_RadiusAxis.runtimeMinMaxRange;
712  m_RadiusAxis.UpdateTooptipLabelText(ChartCached.FloatToStr(value));
713  m_RadiusAxis.UpdateTooltipLabelPos(ChartHelper.GetPos(cenPos, dist, m_AngleAxis.runtimeStartAngle, true));
714  }
715  }
716 }
717 ;
XCharts.AxisLabel.margin
float margin
The margin between the axis label and the axis line. 刻度标签与轴线之间的距离。
Definition: AxisLabel.cs:69
XCharts.Tooltip.Type
Type
Indicator type. 指示器类型。
Definition: Tooltip.cs:25
XCharts.Axis.inverse
bool inverse
Whether the axis are reversed or not. Invalid in Category axis. 是否反向坐标轴。在类目轴中无效。
Definition: Axis.cs:270
XCharts.Tooltip
Tooltip component. 提示框组件。
Definition: Tooltip.cs:19
XCharts.TooltipTheme.lineType
LineStyle.Type lineType
the type of line. 坐标轴线类型。
Definition: TooltipTheme.cs:28
XCharts.BaseAxisTheme.lineWidth
float lineWidth
the width of line. 坐标轴线宽。
Definition: AxisTheme.cs:47
XCharts.BaseAxisTheme.tickLength
float tickLength
the length of tick. 刻度线线长。
Definition: AxisTheme.cs:110
XCharts.Title.text
string text
The main title text, supporting for newlines. 主标题文本,支持使用 换行。
Definition: Title.cs:38
XCharts.AngleAxis
Angle axis of Polar Coordinate. 极坐标系的角度轴。
Definition: Axis.cs:1056
XCharts.Polar
Polar coordinate can be used in scatter and line chart. Every polar coordinate has an angleAxis and a...
Definition: Polar.cs:21
XCharts.BaseAxisTheme.splitLineColor
Color32 splitLineColor
the color of line. 分割线线颜色。
Definition: AxisTheme.cs:101
XCharts.Axis.splitLine
AxisSplitLine splitLine
axis split line. 坐标轴分割线。
Definition: Axis.cs:341
XCharts.BaseChart.AddData
virtual SerieData AddData(string serieName, double data, string dataName=null)
Add a data to serie. If serieName doesn't exist in legend,will be add to legend. 添加一个数据到指定的系列中。
Definition: BaseChart_API.cs:237
XCharts.Axis.runtimeMinValue
double runtimeMinValue
the current minimun value. 当前最小值。
Definition: Axis.cs:401
XCharts.Serie.animation
SerieAnimation animation
The start animation. 起始动画。
Definition: Serie.cs:830
XCharts.SerieType
SerieType
the type of serie. 系列类型。
Definition: Serie.cs:19
XCharts.SerieTheme.lineWidth
float lineWidth
the color of text. 文本颜色。
Definition: SerieTheme.cs:34
XCharts.AxisLabel.inside
bool inside
Set this to true so the axis labels face the inside direction. 刻度标签是否朝内,默认朝外。
Definition: AxisLabel.cs:60
XCharts.Serie.dataPoints
List< Vector3 > dataPoints
数据项位置坐标。
Definition: Serie.cs:1159
XCharts.BaseChart.tooltip
Tooltip? tooltip
The tooltip setting of chart. 提示框组件
Definition: BaseChart_API.cs:61
XCharts.BaseChart.radiusAxis
RadiusAxis? radiusAxis
Radial axis of polar coordinate. 极坐标系的径向轴。
Definition: PolarChart_API.cs:25
XCharts.Axis.axisTick
AxisTick axisTick
axis tick. 坐标轴刻度。
Definition: Axis.cs:323
XCharts.Tooltip.UpdateToTop
void UpdateToTop()
Keep Tooltiop displayed at the top. 保持Tooltiop显示在最顶上
Definition: Tooltip.cs:354
XCharts.Serie.lineStyle
LineStyle lineStyle
The style of line. 线条样式。
Definition: Serie.cs:545
XCharts.Axis.runtimeZeroXOffset
float runtimeZeroXOffset
the x offset of zero position. 坐标轴原点在X轴的偏移。
Definition: Axis.cs:430
XCharts.BaseChart.settings
Settings settings
Global parameter setting component. 全局设置组件。
Definition: BaseChart_API.cs:71
XCharts.Axis.runtimeMaxValue
double runtimeMaxValue
the current maximum value. 当前最大值。
Definition: Axis.cs:416
XCharts.Serie.index
int index
The index of serie,start at 0. 系列的索引,从0开始。
Definition: Serie.cs:1145
XCharts.BaseChart.RefreshChart
void RefreshChart()
Redraw chart in next frame. 在下一帧刷新图表。
Definition: BaseChart_API.cs:140
XCharts.Tooltip.show
bool show
Whether to show the tooltip component. 是否显示提示框组件。
Definition: Tooltip.cs:83
XCharts.BaseAxisTheme.lineColor
Color32 lineColor
the color of line. 坐标轴线颜色。
Definition: AxisTheme.cs:65
XCharts.TooltipTheme.lineWidth
float lineWidth
the width of line. 指示线线宽。
Definition: TooltipTheme.cs:37
XCharts.Polar.runtimeCenterPos
Vector3 runtimeCenterPos
the center position of polar in container. 极坐标在容器中的具体中心点。
Definition: Polar.cs:72
XCharts.Tooltip.runtimeSerieIndex
Dictionary< int, List< int > > runtimeSerieIndex
当前提示框所指示的Serie索引(目前只对散点图有效)。
Definition: Tooltip.cs:250
XCharts
Definition: RewardChart.cs:14
XCharts.Serie.polarIndex
int polarIndex
Index of polar component that serie uses. 所使用的 polar 组件的 index。
Definition: Serie.cs:454
XCharts.Serie.highlighted
bool highlighted
Whether the serie is highlighted. 该系列是否高亮,一般由图例悬停触发。
Definition: Serie.cs:1150
XCharts.TooltipTheme.labelBackgroundColor
Color32 labelBackgroundColor
the background color of tooltip cross indicator's axis label. 十字指示器坐标轴标签的背景颜色。
Definition: TooltipTheme.cs:74
XCharts.Axis
The axis in rectangular coordinate. 直角坐标系的坐标轴组件。
Definition: Axis.cs:20
XCharts.Axis.clockwise
bool clockwise
Whether the positive position of axis is in clockwise. True for clockwise by default....
Definition: Axis.cs:279
XCharts.BaseChart.polar
Polar? polar
极坐标。
Definition: PolarChart_API.cs:15
XCharts.Serie.dataCount
int dataCount
the count of data list. 数据项个数。
Definition: Serie.cs:1155
XCharts.BaseAxisTheme.splitLineWidth
float splitLineWidth
the width of split line. 分割线线宽。
Definition: AxisTheme.cs:83
XCharts.Series.GetSerie
Serie GetSerie(string name)
获得指定系列名的第一个系列
Definition: Series.cs:148
XCharts.Tooltip.lineStyle
LineStyle lineStyle
the line style of indicator line. 指示线样式。
Definition: Tooltip.cs:228
XCharts.Series.list
List< Serie > list
the list of serie 系列列表。
Definition: Series.cs:28
XCharts.RadiusAxis
Radial axis of polar coordinate. 极坐标系的径向轴。
Definition: Axis.cs:1027
XCharts.Polar.runtimeRadius
float runtimeRadius
the true radius of polar. 极坐标的运行时实际半径。
Definition: Polar.cs:77
XCharts.Axis.runtimeZeroYOffset
float runtimeZeroYOffset
the y offset of zero position. 坐标轴原点在Y轴的偏移。
Definition: Axis.cs:435
XCharts.Axis.axisLine
AxisLine axisLine
axis Line. 坐标轴轴线。 ///
Definition: Axis.cs:305
XCharts.AxisLabel.textStyle
TextStyle textStyle
The text style of axis name. 文本样式。
Definition: AxisLabel.cs:162
XCharts.Serie.data
List< SerieData > data
系列中的数据内容数组。SerieData可以设置1到n维数据。
Definition: Serie.cs:1086
XCharts.Serie
系列。每个系列通过 type 决定自己的图表类型。
Definition: Serie.cs:261
XCharts.Axis.show
bool show
Whether to show axis. 是否显示坐标轴。
Definition: Axis.cs:121
XCharts.AxisLabel.show
bool show
Set this to false to prevent the axis label from appearing. 是否显示刻度标签。
Definition: AxisLabel.cs:42
XUGL
Definition: UGL.cs:12
XCharts.Tooltip.SetActive
void SetActive(bool flag)
设置提示框是否显示
Definition: Tooltip.cs:443
XCharts.Tooltip.offset
Vector2 offset
The position offset of tooltip relative to the mouse position. 提示框相对于鼠标位置的偏移。
Definition: Tooltip.cs:213
XCharts.SerieData.highlighted
bool highlighted
Whether the data item is highlighted. 该数据项是否被高亮,一般由鼠标悬停或图例悬停触发高亮。
Definition: SerieData.cs:135
XCharts.Series.Count
int Count
the size of serie list. 系列个数。
Definition: Series.cs:33
XCharts.SerieSymbol.GetSize
float GetSize(List< double > data, float themeSize)
根据指定的sizeType获得标记的大小
Definition: SerieSymbol.cs:322
XCharts.BaseChart.chartHeight
float chartHeight
The height of chart. 图表的高
Definition: BaseChart_API.cs:103
XCharts.BaseChart.AddSerie
virtual Serie AddSerie(SerieType type, string serieName=null, bool show=true, bool addToHead=false)
Add a serie to serie list. 添加一个系列到系列列表中。
Definition: BaseChart_API.cs:199
XCharts.Tooltip.UpdateContentPos
void UpdateContentPos(Vector2 pos)
更新文本框位置
Definition: Tooltip.cs:456
XCharts.Tooltip.runtimeGameObject
GameObject runtimeGameObject
the gameObject of tooltip. 提示框的gameObject。
Definition: Tooltip.cs:293
XCharts.Axis.polarIndex
int polarIndex
The index of the polar on which the axis are located, by default, is in the first polar....
Definition: Axis.cs:157
XCharts.TooltipTheme.labelTextColor
Color32 labelTextColor
the text color of tooltip cross indicator's axis label. 十字指示器坐标轴标签的文本颜色。
Definition: TooltipTheme.cs:64
XCharts.BaseChart.chartWidth
float chartWidth
The width of chart. 图表的宽
Definition: BaseChart_API.cs:98
XCharts.Polar.backgroundColor
Color backgroundColor
[default:Color.clear]Background color of polar, which is transparent by default. 极坐标的背景色,默认透明。
Definition: Polar.cs:63
XCharts.BaseChart.angleAxis
AngleAxis? angleAxis
Angle axis of Polar Coordinate. 极坐标系的角度轴。
Definition: PolarChart_API.cs:20
XCharts.SerieData.data
List< double > data
An arbitrary dimension data list of data item. 可指定任意维数的数值列表。
Definition: SerieData.cs:124
XCharts.BaseLine.show
bool show
Set this to false to prevent the axis line from showing. 是否显示坐标轴轴线。
Definition: BaseLine.cs:27
XCharts.Axis.IsCategory
bool IsCategory()
是否为类目轴。
Definition: Axis.cs:540
XCharts.Tooltip.type
Type type
Indicator type. 提示框指示器类型。
Definition: Tooltip.cs:92
XCharts.Serie.GetSerieData
SerieData GetSerieData(int index, DataZoom dataZoom=null)
获得指定索引的数据项
Definition: Serie.cs:1667
XCharts.Settings.cicleSmoothness
float? cicleSmoothness
the smoothess of cricle. 圆形的平滑度。数越小圆越平滑,但顶点数也会随之增加。
Definition: Settings.cs:111
XCharts.Axis.AxisType
AxisType
the type of axis. 坐标轴类型。
Definition: Axis.cs:26
XCharts.BaseChart
The base class of all charts. 所有Chart的基类。
Definition: BaseChart_API.cs:21
XCharts.BaseChart.title
Title? title
The title setting of chart. 标题组件
Definition: BaseChart_API.cs:49
XCharts.Serie.symbol
SerieSymbol symbol
the symbol of serie data item. 标记的图形。
Definition: Serie.cs:501
XCharts.PolarChart
Definition: PolarChart.cs:20
XCharts.Tooltip.runtimeAngle
float runtimeAngle
当前指示的角度。
Definition: Tooltip.cs:297
XCharts.BaseAxisTheme.tickWidth
float tickWidth
the width of tick. 刻度线线宽。
Definition: AxisTheme.cs:119
XCharts.Tooltip.IsActive
bool IsActive()
提示框是否显示
Definition: Tooltip.cs:434
XCharts.Axis.AxisMinMaxType
AxisMinMaxType
the type of axis min and max value. 坐标轴最大最小刻度显示类型。
Definition: Axis.cs:54
XCharts.Axis.axisLabel
AxisLabel axisLabel
axis label. 坐标轴刻度标签。
Definition: Axis.cs:332
XCharts.BaseChart.RemoveData
virtual void RemoveData()
Remove all data from series and legend. The series list is also cleared. 清除所有系列和图例数据,系列的列表也会被清除。
Definition: BaseChart_API.cs:166
XCharts.BaseChart.theme
ChartTheme theme
The theme.
Definition: BaseChart_API.cs:44
XCharts.SerieData
A data item of serie. 系列中的一个数据项。可存储数据名和1-n维的数据。
Definition: SerieData.cs:19