DrawSerieRadar.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /************************************************/
  2. /* */
  3. /* Copyright (c) 2018 - 2021 monitor1394 */
  4. /* https://github.com/monitor1394 */
  5. /* */
  6. /************************************************/
  7. using UnityEngine;
  8. using UnityEngine.UI;
  9. using UnityEngine.EventSystems;
  10. using XUGL;
  11. using System.Collections.Generic;
  12. namespace XCharts
  13. {
  14. internal class DrawSerieRadar : IDrawSerie
  15. {
  16. public BaseChart chart;
  17. private const string INDICATOR_TEXT = "indicator";
  18. private bool m_IsEnterLegendButtom;
  19. Dictionary<string, int> serieNameSet = new Dictionary<string, int>();
  20. public DrawSerieRadar(BaseChart chart)
  21. {
  22. this.chart = chart;
  23. }
  24. public void InitComponent()
  25. {
  26. InitRadars();
  27. }
  28. public void CheckComponent()
  29. {
  30. }
  31. public void Update()
  32. {
  33. }
  34. public void DrawBase(VertexHelper vh)
  35. {
  36. serieNameSet.Clear();
  37. for (int i = 0; i < chart.radars.Count; i++)
  38. {
  39. var radar = chart.radars[i];
  40. if (!radar.show) continue;
  41. radar.index = i;
  42. radar.UpdateRadarCenter(chart.chartPosition, chart.chartWidth, chart.chartHeight);
  43. if (radar.shape == Radar.Shape.Circle)
  44. {
  45. DrawCricleRadar(vh, radar);
  46. }
  47. else
  48. {
  49. DrawRadar(vh, radar);
  50. }
  51. }
  52. }
  53. public void DrawSerie(VertexHelper vh, Serie serie)
  54. {
  55. if (serie.type != SerieType.Radar) return;
  56. if (!serie.show) return;
  57. switch (serie.radarType)
  58. {
  59. case RadarType.Multiple:
  60. DrawMutipleRadar(vh, serie, serie.index);
  61. break;
  62. case RadarType.Single:
  63. DrawSingleRadar(vh, serie, serie.index);
  64. break;
  65. }
  66. }
  67. public void RefreshLabel()
  68. {
  69. for (int i = 0; i < chart.series.Count; i++)
  70. {
  71. var serie = chart.series.GetSerie(i);
  72. if (serie.type != SerieType.Radar) continue;
  73. if (!serie.show && serie.radarType != RadarType.Single) continue;
  74. var radar = chart.GetRadar(serie.radarIndex);
  75. if (radar == null) continue;
  76. var center = radar.runtimeCenterPos;
  77. for (int n = 0; n < serie.dataCount; n++)
  78. {
  79. var serieData = serie.data[n];
  80. if (serieData.labelObject == null) continue;
  81. var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
  82. var iconStyle = SerieHelper.GetIconStyle(serie, serieData);
  83. var labelPos = serieData.labelPosition;
  84. if (serieLabel.margin != 0)
  85. {
  86. labelPos += serieLabel.margin * (labelPos - center).normalized;
  87. }
  88. serieData.labelObject.SetPosition(labelPos);
  89. serieData.labelObject.UpdateIcon(iconStyle);
  90. if (serie.show && serieLabel.show && serieData.canShowLabel)
  91. {
  92. var value = serieData.GetCurrData(1);
  93. var max = radar.GetIndicatorMax(n);
  94. SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, chart.theme, i);
  95. serieData.SetLabelActive(serieData.labelPosition != Vector3.zero);
  96. serieData.labelObject.SetLabelPosition(serieLabel.offset);
  97. var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, max,
  98. serieLabel, Color.clear);
  99. if (serieData.labelObject.SetText(content))
  100. {
  101. chart.RefreshPainter(serie);
  102. }
  103. }
  104. else
  105. {
  106. serieData.SetLabelActive(false);
  107. }
  108. }
  109. }
  110. }
  111. public bool CheckTootipArea(Vector2 local)
  112. {
  113. if (!chart.series.Contains(SerieType.Radar)) return false;
  114. if (m_IsEnterLegendButtom) return false;
  115. if (!IsInRadar(local)) return false;
  116. bool highlight = false;
  117. chart.tooltip.ClearValue();
  118. for (int i = 0; i < chart.series.Count; i++)
  119. {
  120. var serie = chart.series.GetSerie(i);
  121. if (!serie.show || serie.type != SerieType.Radar) continue;
  122. var radar = chart.radars[serie.radarIndex];
  123. var dist = Vector2.Distance(radar.runtimeCenterPos, local);
  124. if (dist > radar.runtimeRadius + serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize))
  125. {
  126. continue;
  127. }
  128. switch (serie.radarType)
  129. {
  130. case RadarType.Multiple:
  131. for (int n = 0; n < serie.data.Count; n++)
  132. {
  133. var posKey = i * 1000 + n;
  134. if (radar.runtimeDataPosList.ContainsKey(posKey))
  135. {
  136. var posList = radar.runtimeDataPosList[posKey];
  137. var symbolSize = serie.symbol.GetSize(serie.data[n].data, chart.theme.serie.lineSymbolSize);
  138. for (int k = 0; k < posList.Count; k++)
  139. {
  140. if (Vector2.Distance(posList[k], local) <= symbolSize * 1.3f)
  141. {
  142. chart.tooltip.runtimeDataIndex[0] = i;
  143. chart.tooltip.runtimeDataIndex[1] = n;
  144. if (chart.tooltip.runtimeDataIndex.Count >= 3)
  145. chart.tooltip.runtimeDataIndex[2] = k;
  146. else
  147. chart.tooltip.runtimeDataIndex.Add(k);
  148. highlight = true;
  149. break;
  150. }
  151. }
  152. }
  153. }
  154. break;
  155. case RadarType.Single:
  156. for (int n = 0; n < serie.data.Count; n++)
  157. {
  158. var serieData = serie.data[n];
  159. var symbolSize = serie.symbol.GetSize(serie.data[n].data, chart.theme.serie.lineSymbolSize);
  160. if (Vector2.Distance(serieData.labelPosition, local) <= symbolSize * 1.3f)
  161. {
  162. chart.tooltip.runtimeDataIndex[0] = i;
  163. chart.tooltip.runtimeDataIndex[1] = n;
  164. highlight = true;
  165. break;
  166. }
  167. }
  168. break;
  169. }
  170. }
  171. if (!highlight)
  172. {
  173. if (chart.tooltip.IsActive())
  174. {
  175. chart.tooltip.SetActive(false);
  176. chart.RefreshChart();
  177. }
  178. }
  179. else
  180. {
  181. chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
  182. UpdateTooltip();
  183. chart.RefreshChart();
  184. }
  185. return highlight;
  186. }
  187. public bool OnLegendButtonClick(int index, string legendName, bool show)
  188. {
  189. if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
  190. if (!LegendHelper.IsSerieLegend(chart, legendName, SerieType.Radar)) return false;
  191. LegendHelper.CheckDataShow(chart.series, legendName, show);
  192. chart.UpdateLegendColor(legendName, show);
  193. chart.RefreshChart();
  194. return true;
  195. }
  196. public bool OnLegendButtonEnter(int index, string legendName)
  197. {
  198. if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
  199. if (!LegendHelper.IsSerieLegend(chart, legendName, SerieType.Radar)) return false;
  200. m_IsEnterLegendButtom = true;
  201. LegendHelper.CheckDataHighlighted(chart.series, legendName, true);
  202. chart.RefreshChart();
  203. return true;
  204. }
  205. public bool OnLegendButtonExit(int index, string legendName)
  206. {
  207. if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
  208. if (!LegendHelper.IsSerieLegend(chart, legendName, SerieType.Radar)) return false;
  209. m_IsEnterLegendButtom = false;
  210. LegendHelper.CheckDataHighlighted(chart.series, legendName, false);
  211. chart.RefreshChart();
  212. return true;
  213. }
  214. public void OnPointerDown(PointerEventData eventData)
  215. {
  216. }
  217. private void InitRadars()
  218. {
  219. for (int n = 0; n < chart.radars.Count; n++)
  220. {
  221. Radar radar = chart.radars[n];
  222. radar.index = n;
  223. InitRadar(radar);
  224. }
  225. }
  226. private void InitRadar(Radar radar)
  227. {
  228. float txtWid = 100;
  229. float txtHig = 20;
  230. radar.painter = chart.GetPainter(radar.index);
  231. radar.refreshComponent = delegate ()
  232. {
  233. ChartHelper.HideAllObject(chart.transform, INDICATOR_TEXT + "_" + radar.index);
  234. radar.UpdateRadarCenter(chart.chartPosition, chart.chartWidth, chart.chartHeight);
  235. for (int i = 0; i < radar.indicatorList.Count; i++)
  236. {
  237. var indicator = radar.indicatorList[i];
  238. var pos = radar.GetIndicatorPosition(i);
  239. var textStyle = indicator.textStyle;
  240. var objName = INDICATOR_TEXT + "_" + radar.index + "_" + i;
  241. var txt = ChartHelper.AddTextObject(objName, chart.transform, new Vector2(0.5f, 0.5f),
  242. new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(txtWid, txtHig),
  243. textStyle, chart.theme.radar);
  244. txt.gameObject.hideFlags = chart.chartHideFlags;
  245. txt.SetAlignment(textStyle.GetAlignment(TextAnchor.MiddleCenter));
  246. txt.SetText(radar.indicatorList[i].name);
  247. txt.SetActive(radar.indicator);
  248. var offset = new Vector3(textStyle.offset.x, textStyle.offset.y);
  249. AxisHelper.AdjustCircleLabelPos(txt, pos, radar.runtimeCenterPos, txtHig, offset);
  250. }
  251. chart.RefreshBasePainter();
  252. };
  253. radar.refreshComponent.Invoke();
  254. }
  255. private void DrawMutipleRadar(VertexHelper vh, Serie serie, int i)
  256. {
  257. if (!serie.show) return;
  258. var radar = chart.GetRadar(serie.radarIndex);
  259. if (radar == null) return;
  260. var startPoint = Vector3.zero;
  261. var toPoint = Vector3.zero;
  262. var firstPoint = Vector3.zero;
  263. var indicatorNum = radar.indicatorList.Count;
  264. var angle = 2 * Mathf.PI / indicatorNum;
  265. var centerPos = radar.runtimeCenterPos;
  266. var serieNameCount = -1;
  267. serie.animation.InitProgress(1, 0, 1);
  268. if (!chart.IsActive(i) || serie.animation.HasFadeOut())
  269. {
  270. return;
  271. }
  272. var rate = serie.animation.GetCurrRate();
  273. var dataChanging = false;
  274. var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
  275. SerieHelper.GetAllMinMaxData(serie, radar.ceilRate);
  276. for (int j = 0; j < serie.data.Count; j++)
  277. {
  278. var serieData = serie.data[j];
  279. int key = i * 1000 + j;
  280. if (!radar.runtimeDataPosList.ContainsKey(key))
  281. {
  282. radar.runtimeDataPosList.Add(i * 1000 + j, new List<Vector3>(serieData.data.Count));
  283. }
  284. else
  285. {
  286. radar.runtimeDataPosList[key].Clear();
  287. }
  288. string dataName = serieData.name;
  289. int serieIndex = 0;
  290. if (string.IsNullOrEmpty(dataName))
  291. {
  292. serieNameCount++;
  293. serieIndex = serieNameCount;
  294. }
  295. else if (!serieNameSet.ContainsKey(dataName))
  296. {
  297. serieNameSet.Add(dataName, serieNameCount);
  298. serieNameCount++;
  299. serieIndex = serieNameCount;
  300. }
  301. else
  302. {
  303. serieIndex = serieNameSet[dataName];
  304. }
  305. if (!serieData.show)
  306. {
  307. continue;
  308. }
  309. var isHighlight = IsHighlight(radar, serie, serieData, j, 0);
  310. var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, serieIndex, isHighlight);
  311. var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, serieIndex, isHighlight);
  312. var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serieIndex, isHighlight);
  313. var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
  314. int dataCount = radar.indicatorList.Count;
  315. List<Vector3> pointList = radar.runtimeDataPosList[key];
  316. for (int n = 0; n < dataCount; n++)
  317. {
  318. if (n >= serieData.data.Count) break;
  319. var max = radar.GetIndicatorMax(n);
  320. var value = serieData.GetCurrData(n, dataChangeDuration);
  321. if (serieData.IsDataChanged()) dataChanging = true;
  322. if (max == 0)
  323. {
  324. max = serie.runtimeDataMax;
  325. }
  326. var radius = (float)(max < 0 ? radar.runtimeDataRadius - radar.runtimeDataRadius * value / max
  327. : radar.runtimeDataRadius * value / max);
  328. var currAngle = (n + (radar.positionType == Radar.PositionType.Between ? 0.5f : 0)) * angle;
  329. radius *= rate;
  330. if (n == 0)
  331. {
  332. startPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
  333. centerPos.y + radius * Mathf.Cos(currAngle));
  334. firstPoint = startPoint;
  335. }
  336. else
  337. {
  338. toPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
  339. centerPos.y + radius * Mathf.Cos(currAngle));
  340. if (serie.areaStyle.show)
  341. {
  342. UGL.DrawTriangle(vh, startPoint, toPoint, centerPos, areaColor, areaColor, areaToColor);
  343. }
  344. if (serie.lineStyle.show)
  345. {
  346. ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, toPoint, lineColor);
  347. }
  348. startPoint = toPoint;
  349. }
  350. pointList.Add(startPoint);
  351. }
  352. if (serie.areaStyle.show)
  353. {
  354. UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
  355. }
  356. if (serie.lineStyle.show)
  357. {
  358. ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, firstPoint, lineColor);
  359. }
  360. if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
  361. {
  362. for (int m = 0; m < pointList.Count; m++)
  363. {
  364. var point = pointList[m];
  365. isHighlight = IsHighlight(radar, serie, serieData, j, m);
  366. var symbolSize = isHighlight
  367. ? serie.symbol.GetSelectedSize(null, chart.theme.serie.lineSymbolSelectedSize)
  368. : serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize);
  369. var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
  370. var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
  371. var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, serieIndex, isHighlight, false);
  372. var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
  373. var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
  374. chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
  375. symbolToColor, backgroundColor, serie.symbol.gap, cornerRadius);
  376. }
  377. }
  378. }
  379. if (!serie.animation.IsFinish())
  380. {
  381. serie.animation.CheckProgress(1);
  382. chart.RefreshPainter(serie);
  383. }
  384. if (dataChanging)
  385. {
  386. chart.RefreshPainter(serie);
  387. }
  388. }
  389. private bool IsHighlight(Radar radar, Serie serie, SerieData serieData, int dataIndex, int dimension)
  390. {
  391. if (serie.highlighted || serieData.highlighted) return true;
  392. if (!chart.tooltip.show) return false;
  393. var selectedSerieIndex = chart.tooltip.runtimeDataIndex[0];
  394. if (selectedSerieIndex < 0) return false;
  395. if (chart.series.GetSerie(selectedSerieIndex).radarIndex != serie.radarIndex) return false;
  396. switch (serie.radarType)
  397. {
  398. case RadarType.Multiple:
  399. if (radar.isAxisTooltip)
  400. {
  401. var selectedDimension = chart.tooltip.runtimeDataIndex[2];
  402. return selectedDimension == dimension;
  403. }
  404. else if (chart.tooltip.runtimeDataIndex.Count >= 2)
  405. {
  406. return chart.tooltip.runtimeDataIndex[0] == serie.index && chart.tooltip.runtimeDataIndex[1] == dataIndex;
  407. }
  408. else
  409. {
  410. return false;
  411. }
  412. case RadarType.Single:
  413. return chart.tooltip.runtimeDataIndex[1] == dataIndex;
  414. }
  415. return false;
  416. }
  417. private void DrawSingleRadar(VertexHelper vh, Serie serie, int i)
  418. {
  419. var startPoint = Vector3.zero;
  420. var toPoint = Vector3.zero;
  421. var firstPoint = Vector3.zero;
  422. var lastColor = ColorUtil.clearColor32;
  423. var firstColor = ColorUtil.clearColor32;
  424. var radar = chart.radars[serie.radarIndex];
  425. var indicatorNum = radar.indicatorList.Count;
  426. var angle = 2 * Mathf.PI / indicatorNum;
  427. var centerPos = radar.runtimeCenterPos;
  428. var serieNameCount = -1;
  429. serie.animation.InitProgress(1, 0, 1);
  430. if (!chart.IsActive(i) || serie.animation.HasFadeOut())
  431. {
  432. return;
  433. }
  434. var rate = serie.animation.GetCurrRate();
  435. var dataChanging = false;
  436. var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
  437. int key = i * 1000;
  438. if (!radar.runtimeDataPosList.ContainsKey(key))
  439. {
  440. radar.runtimeDataPosList.Add(i * 1000, new List<Vector3>(serie.dataCount));
  441. }
  442. else
  443. {
  444. radar.runtimeDataPosList[key].Clear();
  445. }
  446. var pointList = radar.runtimeDataPosList[key];
  447. var startIndex = GetStartShowIndex(serie);
  448. var endIndex = GetEndShowIndex(serie);
  449. SerieHelper.UpdateMinMaxData(serie, 1, radar.ceilRate);
  450. for (int j = 0; j < serie.data.Count; j++)
  451. {
  452. var serieData = serie.data[j];
  453. serieData.index = j;
  454. string dataName = serieData.name;
  455. int serieIndex = 0;
  456. if (string.IsNullOrEmpty(dataName))
  457. {
  458. serieNameCount++;
  459. serieIndex = serieNameCount;
  460. }
  461. else if (!serieNameSet.ContainsKey(dataName))
  462. {
  463. serieNameSet.Add(dataName, serieNameCount);
  464. serieNameCount++;
  465. serieIndex = serieNameCount;
  466. }
  467. else
  468. {
  469. serieIndex = serieNameSet[dataName];
  470. }
  471. if (!serieData.show)
  472. {
  473. serieData.labelPosition = Vector3.zero;
  474. continue;
  475. }
  476. var isHighlight = IsHighlight(radar, serie, serieData, j, 0);
  477. var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, serieIndex, isHighlight);
  478. var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, serieIndex, isHighlight);
  479. var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serieIndex, isHighlight);
  480. int dataCount = radar.indicatorList.Count;
  481. var index = serieData.index;
  482. var p = radar.runtimeCenterPos;
  483. var max = radar.GetIndicatorMax(index);
  484. var value = serieData.GetCurrData(1, dataChangeDuration);
  485. if (serieData.IsDataChanged()) dataChanging = true;
  486. if (max == 0)
  487. max = serie.runtimeDataMax;
  488. if (!radar.IsInIndicatorRange(j, serieData.GetData(1)))
  489. {
  490. lineColor = radar.outRangeColor;
  491. }
  492. var radius = (float)(max < 0 ? radar.runtimeDataRadius - radar.runtimeDataRadius * value / max
  493. : radar.runtimeDataRadius * value / max);
  494. var currAngle = (index + (radar.positionType == Radar.PositionType.Between ? 0.5f : 0)) * angle;
  495. radius *= rate;
  496. if (index == startIndex)
  497. {
  498. startPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
  499. p.y + radius * Mathf.Cos(currAngle));
  500. firstPoint = startPoint;
  501. lastColor = lineColor;
  502. firstColor = lineColor;
  503. }
  504. else
  505. {
  506. toPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
  507. p.y + radius * Mathf.Cos(currAngle));
  508. if (serie.areaStyle.show)
  509. {
  510. UGL.DrawTriangle(vh, startPoint, toPoint, p, areaColor, areaColor, areaToColor);
  511. }
  512. if (serie.lineStyle.show)
  513. {
  514. if (radar.connectCenter)
  515. ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, centerPos,
  516. chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor);
  517. ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, toPoint, chart.theme.serie.lineWidth,
  518. LineStyle.Type.Solid, radar.lineGradient ? lastColor : lineColor, lineColor);
  519. }
  520. startPoint = toPoint;
  521. lastColor = lineColor;
  522. }
  523. serieData.labelPosition = startPoint;
  524. pointList.Add(startPoint);
  525. if (serie.areaStyle.show && j == endIndex)
  526. {
  527. UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
  528. }
  529. if (serie.lineStyle.show && j == endIndex)
  530. {
  531. if (radar.connectCenter)
  532. ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, centerPos,
  533. chart.theme.serie.lineWidth, LineStyle.Type.Solid, lastColor, lastColor);
  534. ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, firstPoint, chart.theme.serie.lineWidth,
  535. LineStyle.Type.Solid, lineColor, radar.lineGradient ? firstColor : lineColor);
  536. }
  537. }
  538. if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
  539. {
  540. for (int j = 0; j < serie.data.Count; j++)
  541. {
  542. var serieData = serie.data[j];
  543. if (!serieData.show) continue;
  544. var isHighlight = serie.highlighted || serieData.highlighted ||
  545. (chart.tooltip.show && chart.tooltip.runtimeDataIndex[0] == i && chart.tooltip.runtimeDataIndex[1] == j);
  546. var serieIndex = serieData.index;
  547. var symbolSize = isHighlight
  548. ? serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize)
  549. : serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
  550. var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
  551. var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
  552. var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, serieIndex, isHighlight, false);
  553. var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
  554. var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
  555. if (!radar.IsInIndicatorRange(j, serieData.GetData(1)))
  556. {
  557. symbolColor = radar.outRangeColor;
  558. symbolToColor = radar.outRangeColor;
  559. }
  560. chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, serieData.labelPosition, symbolColor,
  561. symbolToColor, backgroundColor, serie.symbol.gap, cornerRadius);
  562. }
  563. }
  564. if (!serie.animation.IsFinish())
  565. {
  566. serie.animation.CheckProgress(1);
  567. chart.RefreshPainter(serie);
  568. }
  569. if (dataChanging)
  570. {
  571. chart.RefreshPainter(serie);
  572. }
  573. }
  574. private int GetStartShowIndex(Serie serie)
  575. {
  576. for (int i = 0; i < serie.dataCount; i++)
  577. {
  578. if (serie.data[i].show) return i;
  579. }
  580. return 0;
  581. }
  582. private int GetEndShowIndex(Serie serie)
  583. {
  584. for (int i = serie.dataCount - 1; i >= 0; i--)
  585. {
  586. if (serie.data[i].show) return i;
  587. }
  588. return 0;
  589. }
  590. private void DrawRadarSymbol(VertexHelper vh, Serie serie, SerieData serieData, int serieIndex, bool isHighlight,
  591. List<Vector3> pointList)
  592. {
  593. if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
  594. {
  595. var symbolSize = isHighlight
  596. ? serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize)
  597. : serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
  598. var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
  599. var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
  600. var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, serieIndex, isHighlight, false);
  601. var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
  602. var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
  603. foreach (var point in pointList)
  604. {
  605. chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
  606. symbolToColor, backgroundColor, serie.symbol.gap, cornerRadius);
  607. }
  608. }
  609. }
  610. private void DrawRadar(VertexHelper vh, Radar radar)
  611. {
  612. if (!radar.splitLine.show && !radar.splitArea.show)
  613. {
  614. return;
  615. }
  616. float insideRadius = 0, outsideRadius = 0;
  617. float block = radar.runtimeRadius / radar.splitNumber;
  618. int indicatorNum = radar.indicatorList.Count;
  619. Vector3 p1, p2, p3, p4;
  620. Vector3 p = radar.runtimeCenterPos;
  621. float angle = 2 * Mathf.PI / indicatorNum;
  622. var lineColor = radar.axisLine.GetColor(chart.theme.radar.lineColor);
  623. var lineWidth = radar.axisLine.GetWidth(chart.theme.radar.lineWidth);
  624. var lineType = radar.axisLine.GetType(chart.theme.radar.lineType);
  625. var splitLineColor = radar.splitLine.GetColor(chart.theme.radar.splitLineColor);
  626. var splitLineWidth = radar.splitLine.GetWidth(chart.theme.radar.splitLineWidth);
  627. var splitLineType = radar.splitLine.GetType(chart.theme.radar.splitLineType);
  628. for (int i = 0; i < radar.splitNumber; i++)
  629. {
  630. var isLast = i == radar.splitNumber - 1;
  631. var color = radar.splitArea.GetColor(i, chart.theme.radar);
  632. outsideRadius = insideRadius + block;
  633. p1 = new Vector3(p.x + insideRadius * Mathf.Sin(0), p.y + insideRadius * Mathf.Cos(0));
  634. p2 = new Vector3(p.x + outsideRadius * Mathf.Sin(0), p.y + outsideRadius * Mathf.Cos(0));
  635. for (int j = 0; j <= indicatorNum; j++)
  636. {
  637. float currAngle = j * angle;
  638. p3 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
  639. p.y + outsideRadius * Mathf.Cos(currAngle));
  640. p4 = new Vector3(p.x + insideRadius * Mathf.Sin(currAngle),
  641. p.y + insideRadius * Mathf.Cos(currAngle));
  642. if (radar.splitArea.show)
  643. {
  644. UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, color);
  645. }
  646. if (radar.splitLine.NeedShow(i))
  647. {
  648. if (isLast)
  649. ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, p2, p3, lineColor);
  650. else
  651. ChartDrawer.DrawLineStyle(vh, splitLineType, splitLineWidth, p2, p3, splitLineColor);
  652. }
  653. p1 = p4;
  654. p2 = p3;
  655. }
  656. insideRadius = outsideRadius;
  657. }
  658. for (int j = 0; j <= indicatorNum; j++)
  659. {
  660. float currAngle = j * angle;
  661. p3 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
  662. p.y + outsideRadius * Mathf.Cos(currAngle));
  663. if (radar.splitLine.show)
  664. {
  665. ChartDrawer.DrawLineStyle(vh, splitLineType, splitLineWidth, p, p3, splitLineColor);
  666. }
  667. }
  668. }
  669. private void DrawCricleRadar(VertexHelper vh, Radar radar)
  670. {
  671. if (!radar.splitLine.show && !radar.splitArea.show)
  672. {
  673. return;
  674. }
  675. float insideRadius = 0, outsideRadius = 0;
  676. float block = radar.runtimeRadius / radar.splitNumber;
  677. int indicatorNum = radar.indicatorList.Count;
  678. Vector3 p = radar.runtimeCenterPos;
  679. Vector3 p1;
  680. float angle = 2 * Mathf.PI / indicatorNum;
  681. var lineColor = radar.axisLine.GetColor(chart.theme.radar.lineColor);
  682. var lineWidth = radar.splitLine.GetWidth(chart.theme.radar.splitLineWidth);
  683. for (int i = 0; i < radar.splitNumber; i++)
  684. {
  685. var color = radar.splitArea.GetColor(i, chart.theme.radiusAxis);
  686. outsideRadius = insideRadius + block;
  687. if (radar.splitArea.show)
  688. {
  689. UGL.DrawDoughnut(vh, p, insideRadius, outsideRadius, color, Color.clear,
  690. 0, 360, chart.settings.cicleSmoothness);
  691. }
  692. if (radar.splitLine.show)
  693. {
  694. UGL.DrawEmptyCricle(vh, p, outsideRadius, lineWidth, lineColor,
  695. Color.clear, chart.settings.cicleSmoothness);
  696. }
  697. insideRadius = outsideRadius;
  698. }
  699. for (int j = 0; j <= indicatorNum; j++)
  700. {
  701. float currAngle = j * angle;
  702. p1 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
  703. p.y + outsideRadius * Mathf.Cos(currAngle));
  704. if (radar.splitLine.show)
  705. {
  706. UGL.DrawLine(vh, p, p1, lineWidth / 2, lineColor);
  707. }
  708. }
  709. }
  710. private bool IsInRadar(Vector2 local)
  711. {
  712. foreach (var radar in chart.radars)
  713. {
  714. var dist = Vector2.Distance(radar.runtimeCenterPos, local);
  715. if (dist < radar.runtimeRadius + chart.theme.serie.lineSymbolSize)
  716. {
  717. return true;
  718. }
  719. }
  720. return false;
  721. }
  722. protected void UpdateTooltip()
  723. {
  724. int serieIndex = chart.tooltip.runtimeDataIndex[0];
  725. if (serieIndex < 0)
  726. {
  727. if (chart.tooltip.IsActive())
  728. {
  729. chart.tooltip.SetActive(false);
  730. chart.RefreshChart();
  731. }
  732. return;
  733. }
  734. chart.tooltip.SetActive(true);
  735. var serie = chart.series.GetSerie(serieIndex);
  736. var radar = chart.radars[serie.radarIndex];
  737. var dataIndex = chart.tooltip.runtimeDataIndex[1];
  738. var content = TooltipHelper.GetFormatterContent(chart.tooltip, dataIndex, chart, null, false, radar);
  739. TooltipHelper.SetContentAndPosition(chart.tooltip, content, chart.chartRect);
  740. }
  741. private bool IsAnyRadarDirty()
  742. {
  743. foreach (var radar in chart.radars)
  744. {
  745. if (radar.anyDirty) return true;
  746. }
  747. return false;
  748. }
  749. }
  750. }