CoordinateChart_DrawLine.cs 87 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726
  1. using System.Runtime.InteropServices.ComTypes;
  2. /************************************************/
  3. /* */
  4. /* Copyright (c) 2018 - 2021 monitor1394 */
  5. /* https://github.com/monitor1394 */
  6. /* */
  7. /************************************************/
  8. using System;
  9. using System.Collections.Generic;
  10. using UnityEngine;
  11. using UnityEngine.UI;
  12. using XUGL;
  13. namespace XCharts
  14. {
  15. public partial class CoordinateChart
  16. {
  17. protected void DrawLinePoint(VertexHelper vh, Serie serie)
  18. {
  19. if (!serie.show || serie.IsPerformanceMode()) return;
  20. if (serie.type != SerieType.Line) return;
  21. var count = serie.dataPoints.Count;
  22. var clip = SeriesHelper.IsAnyClipSerie(m_Series);
  23. var grid = GetSerieGridOrDefault(serie);
  24. for (int i = 0; i < count; i++)
  25. {
  26. var serieData = serie.GetSerieData(i);
  27. var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
  28. if (!symbol.show || !symbol.ShowSymbol(i, count)) continue;
  29. if (serie.lineArrow.show)
  30. {
  31. if (serie.lineArrow.position == LineArrow.Position.Start && i == 0) continue;
  32. if (serie.lineArrow.position == LineArrow.Position.End && i == count - 1) continue;
  33. }
  34. if (ChartHelper.IsIngore(serie.dataPoints[i])) continue;
  35. bool highlight = (tooltip.show && tooltip.IsSelected(i))
  36. || serie.data[i].highlighted || serie.highlighted;
  37. float symbolSize = highlight
  38. ? symbol.GetSelectedSize(serie.data[i].data, m_Theme.serie.lineSymbolSelectedSize)
  39. : symbol.GetSize(serie.data[i].data, m_Theme.serie.lineSymbolSize);
  40. var symbolColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, serie.index, highlight);
  41. var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, serie.index, highlight);
  42. var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, m_Theme, serie.index, highlight, false);
  43. var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, m_Theme, highlight);
  44. var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
  45. symbolSize = serie.animation.GetSysmbolSize(symbolSize);
  46. Internal_CheckClipAndDrawSymbol(vh, symbol.type, symbolSize, symbolBorder, serie.dataPoints[i], symbolColor,
  47. symbolToColor, backgroundColor, symbol.gap, clip, cornerRadius, grid,
  48. i > 0 ? serie.dataPoints[i - 1] : grid.runtimePosition);
  49. }
  50. }
  51. protected void DrawLineArrow(VertexHelper vh, Serie serie)
  52. {
  53. if (serie.type != SerieType.Line) return;
  54. if (!serie.show || !serie.lineArrow.show) return;
  55. if (serie.dataPoints.Count < 2) return;
  56. Color32 lineColor = SerieHelper.GetLineColor(serie, m_Theme, serie.index, false);
  57. Vector3 startPos, arrowPos;
  58. var lineArrow = serie.lineArrow.arrow;
  59. switch (serie.lineArrow.position)
  60. {
  61. case LineArrow.Position.End:
  62. var dataPoints = serie.GetUpSmoothList(serie.dataCount - 1);
  63. if (dataPoints.Count < 3)
  64. {
  65. dataPoints = serie.dataPoints;
  66. startPos = dataPoints[dataPoints.Count - 2];
  67. arrowPos = dataPoints[dataPoints.Count - 1];
  68. }
  69. else
  70. {
  71. startPos = dataPoints[dataPoints.Count - 3];
  72. arrowPos = dataPoints[dataPoints.Count - 2];
  73. }
  74. UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
  75. lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
  76. break;
  77. case LineArrow.Position.Start:
  78. dataPoints = serie.GetUpSmoothList(1);
  79. if (dataPoints.Count < 2) dataPoints = serie.dataPoints;
  80. startPos = dataPoints[1];
  81. arrowPos = dataPoints[0];
  82. UGL.DrawArrow(vh, startPos, arrowPos, lineArrow.width, lineArrow.height,
  83. lineArrow.offset, lineArrow.dent, lineArrow.GetColor(lineColor));
  84. break;
  85. }
  86. }
  87. protected void DrawXLineSerie(VertexHelper vh, Serie serie, int colorIndex)
  88. {
  89. if (!IsActive(serie.index)) return;
  90. if (serie.animation.HasFadeOut()) return;
  91. var yAxis = GetSerieYAxisOrDefault(serie);
  92. var xAxis = GetSerieXAxisOrDefault(serie);
  93. var grid = GetSerieGridOrDefault(serie);
  94. var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(xAxis, dataZooms);
  95. var showData = serie.GetDataList(dataZoom);
  96. if (showData.Count <= 0) return;
  97. Color32 lineColor = SerieHelper.GetLineColor(serie, m_Theme, colorIndex, serie.highlighted);
  98. Color32 srcAreaColor = SerieHelper.GetAreaColor(serie, m_Theme, colorIndex, false);
  99. Color32 srcAreaToColor = SerieHelper.GetAreaToColor(serie, m_Theme, colorIndex, false);
  100. Color32 highlightAreaColor = SerieHelper.GetAreaColor(serie, m_Theme, colorIndex, true);
  101. Color32 highlightAreaToColor = SerieHelper.GetAreaToColor(serie, m_Theme, colorIndex, true);
  102. Color32 areaColor, areaToColor;
  103. Vector3 lp = Vector3.zero, np = Vector3.zero, llp = Vector3.zero, nnp = Vector3.zero;
  104. var zeroPos = new Vector3(grid.runtimeX, grid.runtimeY + yAxis.runtimeZeroYOffset);
  105. var isStack = SeriesHelper.IsStack(m_Series, serie.stack, SerieType.Line);
  106. m_StackSerieData.Clear();
  107. if (isStack) SeriesHelper.UpdateStackDataList(m_Series, serie, dataZoom, m_StackSerieData);
  108. float scaleWid = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
  109. xAxis.runtimeScaleWidth = scaleWid;
  110. float startX = grid.runtimeX + (xAxis.boundaryGap ? scaleWid / 2 : 0);
  111. int maxCount = serie.maxShow > 0 ?
  112. (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
  113. : showData.Count;
  114. int i;
  115. int rate = 1;
  116. var sampleDist = serie.sampleDist;
  117. if (sampleDist > 0) rate = (int)((maxCount - serie.minShow) / (grid.runtimeWidth / sampleDist));
  118. if (rate < 1) rate = 1;
  119. var includeLastData = false;
  120. var totalAverage = serie.sampleAverage > 0 ? serie.sampleAverage :
  121. DataAverage(ref showData, serie.sampleType, serie.minShow, maxCount, rate);
  122. var dataChanging = false;
  123. var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
  124. for (i = serie.minShow; i < maxCount; i += rate)
  125. {
  126. if (i == maxCount - 1) includeLastData = true;
  127. if (serie.IsIgnoreValue(showData[i]))
  128. {
  129. serie.dataPoints.Add(Vector3.zero);
  130. showData[i].runtimeStackHig = 0;
  131. }
  132. else
  133. {
  134. double yValue = SampleValue(ref showData, serie.sampleType, rate, serie.minShow, maxCount, totalAverage,
  135. i, dataChangeDuration, ref dataChanging, yAxis);
  136. showData[i].runtimeStackHig = GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, isStack,
  137. ref np, dataChangeDuration);
  138. serie.dataPoints.Add(np);
  139. }
  140. }
  141. if (dataChanging)
  142. {
  143. RefreshPainter(serie);
  144. }
  145. if (!includeLastData)
  146. {
  147. i = maxCount - 1;
  148. if (serie.IsIgnoreValue(showData[i]))
  149. {
  150. serie.dataPoints.Add(Vector3.zero);
  151. showData[i].runtimeStackHig = 0;
  152. }
  153. else
  154. {
  155. double yValue = showData[i].GetCurrData(1, dataChangeDuration, yAxis.inverse, yAxis.runtimeMinValue, yAxis.runtimeMaxValue);
  156. showData[i].runtimeStackHig = GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, isStack, ref np,
  157. dataChangeDuration);
  158. serie.dataPoints.Add(np);
  159. }
  160. }
  161. if (serie.dataPoints.Count <= 0)
  162. {
  163. return;
  164. }
  165. var startIndex = 0;
  166. var endIndex = serie.dataPoints.Count;
  167. var startPos = GetStartPos(serie.dataPoints, ref startIndex, serie.ignoreLineBreak);
  168. var endPos = GetEndPos(serie.dataPoints, ref endIndex, serie.ignoreLineBreak);
  169. lp = startPos;
  170. stPos1 = stPos2 = lastDir = lastDnPos = Vector3.zero;
  171. smoothStartPosUp = smoothStartPosDn = Vector3.zero;
  172. Vector3 firstLastPos = Vector3.zero, lastNextPos = Vector3.zero;
  173. if (serie.minShow > 0 && serie.minShow < showData.Count)
  174. {
  175. i = serie.minShow - 1;
  176. if (serie.IsIgnoreValue(showData[i]))
  177. {
  178. serie.dataPoints.Add(Vector3.zero);
  179. showData[i].runtimeStackHig = 0;
  180. }
  181. else
  182. {
  183. double yValue = showData[i].GetCurrData(1, dataChangeDuration, yAxis.inverse, yAxis.runtimeMinValue, yAxis.runtimeMaxValue);
  184. showData[i].runtimeStackHig = GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, isStack, ref firstLastPos, dataChangeDuration);
  185. }
  186. }
  187. else
  188. {
  189. firstLastPos = lp;
  190. }
  191. if (serie.maxShow > 0 && serie.maxShow < showData.Count)
  192. {
  193. i = serie.maxShow;
  194. if (serie.IsIgnoreValue(showData[i]))
  195. {
  196. serie.dataPoints.Add(Vector3.zero);
  197. showData[i].runtimeStackHig = 0;
  198. }
  199. else
  200. {
  201. double yValue = showData[i].GetCurrData(1, dataChangeDuration, yAxis.inverse, yAxis.runtimeMinValue, yAxis.runtimeMaxValue);
  202. showData[i].runtimeStackHig = GetDataPoint(xAxis, yAxis, showData, yValue, startX, i, scaleWid, isStack, ref lastNextPos, dataChangeDuration);
  203. }
  204. }
  205. else
  206. {
  207. lastNextPos = endPos;
  208. }
  209. VisualMapHelper.AutoSetLineMinMax(visualMap, serie, xAxis, yAxis);
  210. float currDetailProgress = lp.x;
  211. float totalDetailProgress = endPos.x;
  212. if (serie.animation.alongWithLinePath)
  213. {
  214. currDetailProgress = 0;
  215. totalDetailProgress = 0;
  216. var tempLp = startPos;
  217. for (i = startIndex + 1; i < serie.dataPoints.Count; i++)
  218. {
  219. np = serie.dataPoints[i];
  220. if (np != Vector3.zero)
  221. {
  222. totalDetailProgress += Vector3.Distance(np, tempLp);
  223. tempLp = np;
  224. }
  225. }
  226. serie.animation.SetLinePathStartPos(startPos);
  227. }
  228. serie.animation.InitProgress(serie.dataPoints.Count, currDetailProgress, totalDetailProgress);
  229. serie.animation.SetDataFinish(startIndex);
  230. for (i = startIndex + 1; i < serie.dataPoints.Count; i++)
  231. {
  232. np = serie.dataPoints[i];
  233. serie.ClearSmoothList(i);
  234. var isIgnoreBreak = false;
  235. if (np == Vector3.zero)
  236. {
  237. if (serie.ignoreLineBreak)
  238. isIgnoreBreak = true;
  239. else
  240. {
  241. serie.animation.SetDataFinish(i);
  242. continue;
  243. }
  244. }
  245. if (!serie.animation.NeedAnimation(i)) break;
  246. bool isFinish = true;
  247. if (serie.areaStyle.tooltipHighlight && tooltip.show && i <= tooltip.runtimeDataIndex[0])
  248. {
  249. areaColor = highlightAreaColor;
  250. areaToColor = highlightAreaToColor;
  251. }
  252. else
  253. {
  254. areaColor = srcAreaColor;
  255. areaToColor = srcAreaToColor;
  256. }
  257. switch (serie.lineType)
  258. {
  259. case LineType.Normal:
  260. lp = GetLastPos(serie.dataPoints, i, np, serie.ignoreLineBreak);
  261. nnp = GetNNPos(serie.dataPoints, i, np, serie.ignoreLineBreak);
  262. if (lp == Vector3.zero && serie.ignoreLineBreak) isIgnoreBreak = true;
  263. isFinish = DrawNormalLine(vh, serie, xAxis, lp, np, nnp, i,
  264. isIgnoreBreak ? ColorUtil.clearColor32 : lineColor,
  265. isIgnoreBreak ? ColorUtil.clearColor32 : areaColor,
  266. isIgnoreBreak ? ColorUtil.clearColor32 : areaToColor,
  267. zeroPos, startIndex);
  268. break;
  269. case LineType.Smooth:
  270. case LineType.SmoothDash:
  271. llp = GetLLPos(serie.dataPoints, i, firstLastPos, serie.ignoreLineBreak);
  272. nnp = GetNNPos(serie.dataPoints, i, lastNextPos, serie.ignoreLineBreak);
  273. if (lp == Vector3.zero && serie.ignoreLineBreak) isIgnoreBreak = true;
  274. isFinish = DrawSmoothLine(vh, serie, xAxis, lp, np, llp, nnp, i,
  275. isIgnoreBreak ? ColorUtil.clearColor32 : lineColor,
  276. isIgnoreBreak ? ColorUtil.clearColor32 : areaColor,
  277. isIgnoreBreak ? ColorUtil.clearColor32 : areaToColor,
  278. isStack, zeroPos, startIndex);
  279. break;
  280. case LineType.StepStart:
  281. case LineType.StepMiddle:
  282. case LineType.StepEnd:
  283. nnp = GetNNPos(serie.dataPoints, i, np, serie.ignoreLineBreak);
  284. if (lp == Vector3.zero && serie.ignoreLineBreak) isIgnoreBreak = true;
  285. isFinish = DrawStepLine(vh, serie, xAxis, lp, np, nnp, i,
  286. isIgnoreBreak ? ColorUtil.clearColor32 : lineColor,
  287. isIgnoreBreak ? ColorUtil.clearColor32 : areaColor,
  288. isIgnoreBreak ? ColorUtil.clearColor32 : areaToColor,
  289. zeroPos);
  290. break;
  291. case LineType.Dash:
  292. case LineType.Dot:
  293. case LineType.DashDot:
  294. case LineType.DashDotDot:
  295. if (lp == Vector3.zero && serie.ignoreLineBreak) isIgnoreBreak = true;
  296. DrawOtherLine(vh, serie, xAxis, lp, np, i,
  297. isIgnoreBreak ? ColorUtil.clearColor32 : lineColor,
  298. isIgnoreBreak ? ColorUtil.clearColor32 : areaColor,
  299. isIgnoreBreak ? ColorUtil.clearColor32 : areaToColor,
  300. zeroPos);
  301. break;
  302. }
  303. if (isFinish) serie.animation.SetDataFinish(i);
  304. if (np != Vector3.zero || serie.ignoreLineBreak)
  305. {
  306. lp = np;
  307. }
  308. }
  309. if (!serie.animation.IsFinish())
  310. {
  311. serie.animation.CheckProgress(totalDetailProgress - currDetailProgress);
  312. serie.animation.CheckSymbol(serie.symbol.GetSize(null, m_Theme.serie.lineSymbolSize));
  313. m_IsPlayingAnimation = true;
  314. RefreshPainter(serie);
  315. }
  316. }
  317. private Vector3 GetNNPos(List<Vector3> dataPoints, int index, Vector3 np, bool ignoreLineBreak)
  318. {
  319. int size = dataPoints.Count;
  320. if (index >= size) return np;
  321. for (int i = index + 1; i < size; i++)
  322. {
  323. if (dataPoints[i] != Vector3.zero || ignoreLineBreak) return dataPoints[i];
  324. }
  325. return np;
  326. }
  327. private Vector3 GetStartPos(List<Vector3> dataPoints, ref int start, bool ignoreLineBreak)
  328. {
  329. for (int i = 0; i < dataPoints.Count; i++)
  330. {
  331. if (dataPoints[i] != Vector3.zero || ignoreLineBreak)
  332. {
  333. start = i;
  334. return dataPoints[i];
  335. }
  336. }
  337. return Vector3.zero;
  338. }
  339. private Vector3 GetEndPos(List<Vector3> dataPoints, ref int end, bool ignoreLineBreak)
  340. {
  341. for (int i = dataPoints.Count - 1; i >= 0; i--)
  342. {
  343. if (dataPoints[i] != Vector3.zero || ignoreLineBreak)
  344. {
  345. end = i;
  346. return dataPoints[i];
  347. }
  348. }
  349. return Vector3.zero;
  350. }
  351. private Vector3 GetLastPos(List<Vector3> dataPoints, int index, Vector3 pos, bool ignoreLineBreak)
  352. {
  353. if (index <= 0) return pos;
  354. for (int i = index - 1; i >= 0; i--)
  355. {
  356. if (dataPoints[i] != Vector3.zero || ignoreLineBreak) return dataPoints[i];
  357. }
  358. return pos;
  359. }
  360. private Vector3 GetLLPos(List<Vector3> dataPoints, int index, Vector3 lp, bool ignoreLineBreak)
  361. {
  362. if (index <= 1) return lp;
  363. for (int i = index - 2; i >= 0; i--)
  364. {
  365. if (dataPoints[i] != Vector3.zero || ignoreLineBreak) return dataPoints[i];
  366. }
  367. return lp;
  368. }
  369. internal double DataAverage(ref List<SerieData> showData, SampleType sampleType, int minCount, int maxCount, int rate)
  370. {
  371. double totalAverage = 0;
  372. if (rate > 1 && sampleType == SampleType.Peak)
  373. {
  374. double total = 0;
  375. for (int i = minCount; i < maxCount; i++)
  376. {
  377. total += showData[i].data[1];
  378. }
  379. totalAverage = total / (maxCount - minCount);
  380. }
  381. return totalAverage;
  382. }
  383. internal double SampleValue(ref List<SerieData> showData, SampleType sampleType, int rate,
  384. int minCount, int maxCount, double totalAverage, int index, float dataChangeDuration,
  385. ref bool dataChanging, Axis axis)
  386. {
  387. var inverse = axis.inverse;
  388. double minValue = axis.runtimeMinValue;
  389. double MaxValue = axis.runtimeMaxValue;
  390. if (rate <= 1 || index == minCount)
  391. {
  392. if (showData[index].IsDataChanged()) dataChanging = true;
  393. return showData[index].GetCurrData(1, dataChangeDuration, inverse, minValue, MaxValue);
  394. }
  395. switch (sampleType)
  396. {
  397. case SampleType.Sum:
  398. case SampleType.Average:
  399. double total = 0;
  400. for (int i = index; i > index - rate; i--)
  401. {
  402. total += showData[i].GetCurrData(1, dataChangeDuration, inverse, minValue, MaxValue);
  403. if (showData[i].IsDataChanged()) dataChanging = true;
  404. }
  405. if (sampleType == SampleType.Average) return total / rate;
  406. else return total;
  407. case SampleType.Max:
  408. double max = double.MinValue;
  409. for (int i = index; i > index - rate; i--)
  410. {
  411. var value = showData[i].GetCurrData(1, dataChangeDuration, inverse, minValue, MaxValue);
  412. if (value > max) max = value;
  413. if (showData[i].IsDataChanged()) dataChanging = true;
  414. }
  415. return max;
  416. case SampleType.Min:
  417. double min = double.MaxValue;
  418. for (int i = index; i > index - rate; i--)
  419. {
  420. var value = showData[i].GetCurrData(1, dataChangeDuration, inverse, minValue, MaxValue);
  421. if (value < min) min = value;
  422. if (showData[i].IsDataChanged()) dataChanging = true;
  423. }
  424. return min;
  425. case SampleType.Peak:
  426. max = double.MinValue;
  427. min = double.MaxValue;
  428. total = 0;
  429. for (int i = index; i > index - rate; i--)
  430. {
  431. var value = showData[i].GetCurrData(1, dataChangeDuration, inverse, minValue, MaxValue);
  432. total += value;
  433. if (value < min) min = value;
  434. if (value > max) max = value;
  435. if (showData[i].IsDataChanged()) dataChanging = true;
  436. }
  437. var average = total / rate;
  438. if (average >= totalAverage) return max;
  439. else return min;
  440. }
  441. if (showData[index].IsDataChanged()) dataChanging = true;
  442. return showData[index].GetCurrData(1, dataChangeDuration, inverse, minValue, MaxValue);
  443. }
  444. private float GetDataPoint(Axis xAxis, Axis yAxis, List<SerieData> showData, double yValue, float startX, int i,
  445. float scaleWid, bool isStack, ref Vector3 np, float duration, bool isIngoreValue = false)
  446. {
  447. if (isIngoreValue)
  448. {
  449. np = Vector3.zero;
  450. return 0;
  451. }
  452. float xDataHig, yDataHig;
  453. double xMinValue = xAxis.GetCurrMinValue(duration);
  454. double xMaxValue = xAxis.GetCurrMaxValue(duration);
  455. double yMinValue = yAxis.GetCurrMinValue(duration);
  456. double yMaxValue = yAxis.GetCurrMaxValue(duration);
  457. if (xAxis.IsValue() || xAxis.IsLog())
  458. {
  459. var grid = GetAxisGridOrDefault(xAxis);
  460. var axisLineWidth = xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
  461. double xValue = i > showData.Count - 1 ? 0 : showData[i].GetData(0, xAxis.inverse);
  462. float pX = grid.runtimeX + axisLineWidth;
  463. float pY = grid.runtimeY + axisLineWidth;
  464. if (isStack)
  465. {
  466. for (int n = 0; n < m_StackSerieData.Count - 1; n++)
  467. {
  468. pY += m_StackSerieData[n][i].runtimeStackHig;
  469. }
  470. }
  471. if (xAxis.IsLog())
  472. {
  473. int minIndex = xAxis.runtimeMinLogIndex;
  474. float nowIndex = xAxis.GetLogValue(xValue);
  475. xDataHig = (nowIndex - minIndex) / xAxis.splitNumber * grid.runtimeWidth;
  476. }
  477. else
  478. {
  479. if ((xMaxValue - xMinValue) <= 0) xDataHig = 0;
  480. else xDataHig = (float)((xValue - xMinValue) / (xMaxValue - xMinValue)) * grid.runtimeWidth;
  481. }
  482. if (yAxis.IsLog())
  483. {
  484. int minIndex = yAxis.runtimeMinLogIndex;
  485. float nowIndex = yAxis.GetLogValue(yValue);
  486. yDataHig = (nowIndex - minIndex) / yAxis.splitNumber * grid.runtimeHeight;
  487. }
  488. else
  489. {
  490. double valueTotal = yMaxValue - yMinValue;
  491. if (valueTotal <= 0) yDataHig = 0;
  492. else yDataHig = (float)((yValue - yMinValue) / valueTotal) * grid.runtimeHeight;
  493. }
  494. np = new Vector3(pX + xDataHig, pY + yDataHig);
  495. }
  496. else
  497. {
  498. var grid = GetAxisGridOrDefault(yAxis);
  499. var axisLineWidth = yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
  500. float pX = startX + i * scaleWid;
  501. float pY = grid.runtimeY + axisLineWidth;
  502. if (isStack)
  503. {
  504. for (int n = 0; n < m_StackSerieData.Count - 1; n++)
  505. {
  506. pY += m_StackSerieData[n][i].runtimeStackHig;
  507. }
  508. }
  509. if (yAxis.IsLog())
  510. {
  511. int minIndex = yAxis.runtimeMinLogIndex;
  512. float nowIndex = yAxis.GetLogValue(yValue);
  513. yDataHig = (nowIndex - minIndex) / yAxis.splitNumber * grid.runtimeHeight;
  514. }
  515. else
  516. {
  517. double valueTotal = yMaxValue - yMinValue;
  518. if (valueTotal <= 0) yDataHig = 0;
  519. else yDataHig = (float)((yValue - yMinValue) / valueTotal * grid.runtimeHeight);
  520. }
  521. np = new Vector3(pX, pY + yDataHig);
  522. }
  523. return yDataHig;
  524. }
  525. List<List<SerieData>> m_StackSerieData = new List<List<SerieData>>();
  526. protected void DrawYLineSerie(VertexHelper vh, Serie serie, int colorIndex)
  527. {
  528. if (!IsActive(serie.index)) return;
  529. if (serie.animation.HasFadeOut()) return;
  530. Vector3 lp = Vector3.zero;
  531. Vector3 np = Vector3.zero;
  532. Vector3 llp = Vector3.zero;
  533. Vector3 nnp = Vector3.zero;
  534. var lineColor = SerieHelper.GetLineColor(serie, m_Theme, colorIndex, serie.highlighted);
  535. var srcAreaColor = SerieHelper.GetAreaColor(serie, m_Theme, colorIndex, false);
  536. var srcAreaToColor = SerieHelper.GetAreaToColor(serie, m_Theme, colorIndex, false);
  537. var highlightAreaColor = SerieHelper.GetAreaColor(serie, m_Theme, colorIndex, true);
  538. var highlightAreaToColor = SerieHelper.GetAreaToColor(serie, m_Theme, colorIndex, true);
  539. Color32 areaColor, areaToColor;
  540. var xAxis = m_XAxes[serie.xAxisIndex];
  541. var yAxis = m_YAxes[serie.yAxisIndex];
  542. var grid = GetSerieGridOrDefault(serie);
  543. var dataZoom = DataZoomHelper.GetAxisRelatedDataZoom(yAxis, dataZooms);
  544. var showData = serie.GetDataList(dataZoom);
  545. var zeroPos = new Vector3(grid.runtimeX + xAxis.runtimeZeroXOffset, grid.runtimeY);
  546. var isStack = SeriesHelper.IsStack(m_Series, serie.stack, SerieType.Line);
  547. m_StackSerieData.Clear();
  548. if (isStack) SeriesHelper.UpdateStackDataList(m_Series, serie, dataZoom, m_StackSerieData);
  549. if (!yAxis.show) yAxis = m_YAxes[(serie.yAxisIndex + 1) % m_YAxes.Count];
  550. float scaleWid = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, showData.Count, dataZoom);
  551. float startY = grid.runtimeY + (yAxis.boundaryGap ? scaleWid / 2 : 0);
  552. int maxCount = serie.maxShow > 0 ?
  553. (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
  554. : showData.Count;
  555. int i = 0;
  556. int rate = 1;
  557. var sampleDist = serie.sampleDist;
  558. if (sampleDist > 0) rate = (int)((maxCount - serie.minShow) / (grid.runtimeWidth / sampleDist));
  559. if (rate < 1) rate = 1;
  560. var dataChanging = false;
  561. float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
  562. double xMinValue = xAxis.GetCurrMinValue(dataChangeDuration);
  563. double xMaxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
  564. for (i = serie.minShow; i < maxCount; i += rate)
  565. {
  566. double value = showData[i].GetCurrData(1, dataChangeDuration, xAxis.inverse, xAxis.runtimeMinValue, xAxis.runtimeMaxValue);
  567. float pY = startY + i * scaleWid;
  568. float pX = grid.runtimeX + yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
  569. if (isStack)
  570. {
  571. for (int n = 0; n < m_StackSerieData.Count - 1; n++)
  572. {
  573. pX += m_StackSerieData[n][i].runtimeStackHig;
  574. }
  575. }
  576. float dataHig = 0;
  577. if (xAxis.IsLog())
  578. {
  579. int minIndex = xAxis.runtimeMinLogIndex;
  580. float nowIndex = xAxis.GetLogValue(value);
  581. dataHig = (nowIndex - minIndex) / (xAxis.splitNumber - 1) * grid.runtimeWidth;
  582. }
  583. else
  584. {
  585. dataHig = (float)((value - xMinValue) / (xMaxValue - xMinValue) * grid.runtimeWidth);
  586. }
  587. showData[i].runtimeStackHig = dataHig;
  588. np = new Vector3(pX + dataHig, pY);
  589. serie.dataPoints.Add(np);
  590. if (showData[i].IsDataChanged()) dataChanging = true;
  591. }
  592. if (dataChanging)
  593. {
  594. RefreshPainter(serie);
  595. }
  596. if (maxCount % rate != 0)
  597. {
  598. i = maxCount - 1;
  599. double value = showData[i].GetCurrData(1, dataChangeDuration, xAxis.inverse, xAxis.runtimeMinValue, xAxis.runtimeMaxValue);
  600. float pY = startY + i * scaleWid;
  601. float pX = grid.runtimeX + yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
  602. if (isStack)
  603. {
  604. for (int n = 0; n < m_StackSerieData.Count - 1; n++)
  605. {
  606. pX += m_StackSerieData[n][i].runtimeStackHig;
  607. }
  608. }
  609. float dataHig = 0;
  610. if (xAxis.IsLog())
  611. {
  612. int minIndex = xAxis.runtimeMinLogIndex;
  613. float nowIndex = xAxis.GetLogValue(value);
  614. dataHig = (nowIndex - minIndex) / xAxis.splitNumber * grid.runtimeWidth;
  615. }
  616. else
  617. {
  618. dataHig = (float)((value - xMinValue) / (xMaxValue - xMinValue)) * grid.runtimeWidth;
  619. }
  620. showData[i].runtimeStackHig = dataHig;
  621. np = new Vector3(pX + dataHig, pY);
  622. serie.dataPoints.Add(np);
  623. }
  624. lp = serie.dataPoints[0];
  625. int dataCount = serie.dataPoints.Count;
  626. float currDetailProgress = lp.y;
  627. float totalDetailProgress = serie.dataPoints[dataCount - 1].y;
  628. serie.animation.InitProgress(dataCount, currDetailProgress, totalDetailProgress);
  629. for (i = 1; i < serie.dataPoints.Count; i++)
  630. {
  631. np = serie.dataPoints[i];
  632. serie.ClearSmoothList(i);
  633. if (!serie.animation.NeedAnimation(i)) break;
  634. bool isFinish = true;
  635. if (serie.areaStyle.tooltipHighlight && tooltip.show && i < tooltip.runtimeDataIndex[0])
  636. {
  637. areaColor = highlightAreaColor;
  638. areaToColor = highlightAreaToColor;
  639. }
  640. else
  641. {
  642. areaColor = srcAreaColor;
  643. areaToColor = srcAreaToColor;
  644. }
  645. switch (serie.lineType)
  646. {
  647. case LineType.Normal:
  648. nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : np;
  649. isFinish = DrawNormalLine(vh, serie, yAxis, lp, np, nnp, i, lineColor,
  650. areaColor, areaToColor, zeroPos, 0);
  651. break;
  652. case LineType.Smooth:
  653. case LineType.SmoothDash:
  654. llp = i > 1 ? serie.dataPoints[i - 2] : lp;
  655. nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : np;
  656. isFinish = DrawSmoothLine(vh, serie, yAxis, lp, np, llp, nnp, i,
  657. lineColor, areaColor, areaToColor, isStack, zeroPos);
  658. break;
  659. case LineType.StepStart:
  660. case LineType.StepMiddle:
  661. case LineType.StepEnd:
  662. nnp = i < serie.dataPoints.Count - 1 ? serie.dataPoints[i + 1] : np;
  663. isFinish = DrawStepLine(vh, serie, yAxis, lp, np, nnp, i, lineColor,
  664. areaColor, areaToColor, zeroPos);
  665. break;
  666. case LineType.Dash:
  667. UGL.DrawDashLine(vh, lp, np, serie.lineStyle.GetWidth(m_Theme.serie.lineWidth), lineColor, lineColor);
  668. isFinish = true;
  669. break;
  670. case LineType.Dot:
  671. UGL.DrawDotLine(vh, lp, np, serie.lineStyle.GetWidth(m_Theme.serie.lineWidth), lineColor, lineColor);
  672. isFinish = true;
  673. break;
  674. case LineType.DashDot:
  675. UGL.DrawDashDotLine(vh, lp, np, serie.lineStyle.GetWidth(m_Theme.serie.lineWidth), lineColor);
  676. isFinish = true;
  677. break;
  678. case LineType.DashDotDot:
  679. UGL.DrawDashDotDotLine(vh, lp, np, serie.lineStyle.GetWidth(m_Theme.serie.lineWidth), lineColor);
  680. isFinish = true;
  681. break;
  682. }
  683. if (isFinish) serie.animation.SetDataFinish(i);
  684. lp = np;
  685. }
  686. if (!serie.animation.IsFinish())
  687. {
  688. float total = totalDetailProgress - currDetailProgress - dataCount * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth) * 0.5f;
  689. serie.animation.CheckProgress(total);
  690. serie.animation.CheckSymbol(serie.symbol.GetSize(null, m_Theme.serie.lineSymbolSize));
  691. m_IsPlayingAnimation = true;
  692. RefreshPainter(serie);
  693. }
  694. }
  695. private double GetStackValue(List<List<SerieData>> stackDataList, int dataIndex, float dataChangeDuration, Axis xAxis)
  696. {
  697. double value = 0;
  698. foreach (var dataList in stackDataList)
  699. {
  700. value += dataList[dataIndex].GetCurrData(1, dataChangeDuration, xAxis.inverse, xAxis.runtimeMinValue, xAxis.runtimeMaxValue);
  701. }
  702. return value;
  703. }
  704. private Vector3 stPos1, stPos2, lastDir, lastDnPos;
  705. private bool lastIsDown;
  706. private bool DrawNormalLine(VertexHelper vh, Serie serie, Axis axis, Vector3 lp, Vector3 np, Vector3 nnp,
  707. int dataIndex, Color32 lineColor, Color32 areaColor, Color32 areaToColor,
  708. Vector3 zeroPos, int startIndex)
  709. {
  710. var defaultLineColor = lineColor;
  711. var isSecond = dataIndex == startIndex + 1;
  712. var isTheLastPos = np == nnp;
  713. bool isYAxis = axis is YAxis;
  714. var isTurnBack = IsInRightOrUp(isYAxis, np, lp);
  715. var lineWidth = serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  716. var grid = GetSerieGridOrDefault(serie);
  717. Vector3 dnPos, upPos1, upPos2, dir1v, dir2v;
  718. bool isDown;
  719. var dir1 = (np - lp).normalized;
  720. dir1v = Vector3.Cross(dir1, Vector3.forward).normalized * (isYAxis ? -1 : 1);
  721. if (np != nnp)
  722. {
  723. var dir2 = (nnp - np).normalized;
  724. var dir3 = (dir1 + dir2).normalized;
  725. var normal = Vector3.Cross(dir1, dir2);
  726. isDown = isYAxis ? normal.z >= 0 : normal.z <= 0;
  727. var angle = (180 - Vector3.Angle(dir1, dir2)) * Mathf.Deg2Rad / 2;
  728. var diff = serie.lineStyle.GetWidth(m_Theme.serie.lineWidth) / Mathf.Sin(angle);
  729. var dirDp = Vector3.Cross(dir3, Vector3.forward).normalized * (isYAxis ? -1 : 1);
  730. dir2v = Vector3.Cross(dir2, Vector3.forward).normalized * (isYAxis ? -1 : 1);
  731. dnPos = np + (isDown ? dirDp : -dirDp) * diff;
  732. upPos1 = np + (isDown ? -dir1v : dir1v) * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  733. upPos2 = np + (isDown ? -dir2v : dir2v) * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  734. lastDir = dir1;
  735. if (isDown)
  736. {
  737. if (isYAxis && dnPos.x < lp.x && dnPos.x < nnp.x) dnPos.x = lp.x;
  738. if (!isYAxis && dnPos.y < lp.y && dnPos.y < nnp.y) dnPos.y = lp.y;
  739. }
  740. else
  741. {
  742. if (isYAxis && dnPos.x > lp.x && dnPos.x > nnp.x) dnPos.x = lp.x;
  743. if (!isYAxis && dnPos.y > lp.y && dnPos.y > nnp.y) dnPos.y = lp.y;
  744. }
  745. }
  746. else
  747. {
  748. isDown = Vector3.Cross(dir1, lastDir).z <= 0;
  749. if (isYAxis) isDown = !isDown;
  750. dir1v = Vector3.Cross(dir1, Vector3.forward).normalized * (isYAxis ? -1 : 1);
  751. upPos1 = np - dir1v * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  752. upPos2 = np + dir1v * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  753. dnPos = isDown ? upPos2 : upPos1;
  754. }
  755. if (isSecond)
  756. {
  757. stPos1 = lp - dir1v * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  758. stPos2 = lp + dir1v * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  759. }
  760. var smoothPoints = serie.GetUpSmoothList(dataIndex);
  761. var smoothDownPoints = serie.GetDownSmoothList(dataIndex);
  762. var dist = Vector3.Distance(lp, np);
  763. var lastSmoothPoint = Vector3.zero;
  764. var lastSmoothDownPoint = Vector3.zero;
  765. int segment = (int)(dist / settings.lineSegmentDistance);
  766. if (segment <= 3) segment = (int)(dist / lineWidth);
  767. if (segment < 2) segment = 2;
  768. if (dataIndex > startIndex)
  769. {
  770. lastSmoothPoint = ChartHelper.GetLastPoint(serie.GetUpSmoothList(dataIndex - 1));
  771. lastSmoothDownPoint = ChartHelper.GetLastPoint(serie.GetDownSmoothList(dataIndex - 1));
  772. }
  773. smoothPoints.Clear();
  774. smoothDownPoints.Clear();
  775. if (!TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, stPos1, false))
  776. {
  777. smoothPoints.Add(lastSmoothPoint);
  778. }
  779. if (!TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, stPos2, false))
  780. {
  781. smoothDownPoints.Add(lastSmoothDownPoint);
  782. }
  783. var start = lp;
  784. Vector3 ltp1 = stPos1, ltp2 = stPos2;
  785. bool isBreak = false;
  786. bool isStart = false;
  787. bool isShort = false;
  788. for (int i = 1; i < segment; i++)
  789. {
  790. var isEndPos = i == segment - 1;
  791. var cp = lp + dir1 * (dist * i / segment);
  792. if (serie.animation.CheckDetailBreak(cp, isYAxis)) isBreak = true;
  793. var tp1 = cp - dir1v * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  794. var tp2 = cp + dir1v * serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  795. CheckLineGradientColor(cp, serie.lineStyle, axis, defaultLineColor, ref lineColor);
  796. if (isDown)
  797. {
  798. if (!isBreak)
  799. {
  800. if (!isStart)
  801. {
  802. if (isEndPos)
  803. {
  804. isShort = true;
  805. isStart = true;
  806. Internal_CheckClipAndDrawPolygon(vh, stPos1, upPos1, upPos2, stPos2, lineColor, serie.clip, grid);
  807. Internal_CheckClipAndDrawTriangle(vh, stPos2, upPos2, dnPos, lineColor, serie.clip, grid);
  808. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, stPos1, isEndPos);
  809. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, upPos1, isEndPos);
  810. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, dnPos, isEndPos);
  811. }
  812. else if (isSecond || isTurnBack ||
  813. (lastIsDown && IsInRightOrUp(isYAxis, lastDnPos, tp2)) ||
  814. (!lastIsDown && IsInRightOrUp(isYAxis, lastDnPos, tp1)))
  815. {
  816. isStart = true;
  817. if (stPos1 != Vector3.zero && stPos2 != Vector3.zero)
  818. Internal_CheckClipAndDrawPolygon(vh, stPos1, tp1, tp2, stPos2, lineColor, serie.clip, grid);
  819. }
  820. }
  821. else
  822. {
  823. if (isEndPos)
  824. {
  825. if (np != nnp)
  826. {
  827. Internal_CheckClipAndDrawPolygon(vh, ltp1, upPos1, dnPos, ltp2, lineColor, serie.clip, grid);
  828. Internal_CheckClipAndDrawTriangle(vh, upPos1, upPos2, dnPos, lineColor, serie.clip, grid);
  829. }
  830. else
  831. {
  832. Internal_CheckClipAndDrawPolygon(vh, ltp1, upPos1, upPos2, ltp2, lineColor, serie.clip, grid);
  833. }
  834. }
  835. else
  836. {
  837. if (IsInRightOrUp(isYAxis, tp2, dnPos) || isTurnBack)
  838. {
  839. Internal_CheckClipAndDrawLine(vh, start, cp, serie.lineStyle.GetWidth(m_Theme.serie.lineWidth), lineColor, serie.clip, grid);
  840. }
  841. else
  842. {
  843. Internal_CheckClipAndDrawPolygon(vh, ltp1, upPos1, dnPos, ltp2, lineColor, serie.clip, grid);
  844. Internal_CheckClipAndDrawTriangle(vh, upPos1, upPos2, dnPos, lineColor, serie.clip, grid);
  845. i = segment;
  846. }
  847. }
  848. }
  849. }
  850. if (!isShort)
  851. {
  852. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, tp1, isEndPos);
  853. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, tp2, isEndPos);
  854. }
  855. }
  856. else
  857. {
  858. if (!isBreak)
  859. {
  860. if (!isStart)
  861. {
  862. if (isEndPos)
  863. {
  864. isStart = true;
  865. isShort = true;
  866. if (np == nnp)
  867. Internal_CheckClipAndDrawPolygon(vh, stPos1, dnPos, upPos2, stPos2, lineColor, serie.clip, grid);
  868. else
  869. {
  870. Internal_CheckClipAndDrawPolygon(vh, stPos1, dnPos, upPos1, stPos2, lineColor, serie.clip, grid);
  871. Internal_CheckClipAndDrawTriangle(vh, dnPos, upPos1, upPos2, lineColor, serie.clip, grid);
  872. }
  873. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, dnPos, isEndPos);
  874. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, stPos2, isEndPos);
  875. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, upPos2, isEndPos);
  876. }
  877. else if (isSecond || isTurnBack ||
  878. (lastIsDown && IsInRightOrUp(isYAxis, lastDnPos, tp2)) ||
  879. (!lastIsDown && IsInRightOrUp(isYAxis, lastDnPos, tp1)))
  880. {
  881. isStart = true;
  882. if (stPos2 != Vector3.zero)
  883. {
  884. Internal_CheckClipAndDrawPolygon(vh, stPos1, tp1, tp2, stPos2, lineColor, serie.clip, grid);
  885. }
  886. }
  887. }
  888. else
  889. {
  890. if (isEndPos)
  891. {
  892. if (np != nnp)
  893. {
  894. Internal_CheckClipAndDrawPolygon(vh, ltp1, dnPos, upPos1, ltp2, lineColor, serie.clip, grid);
  895. Internal_CheckClipAndDrawTriangle(vh, dnPos, upPos2, upPos1, lineColor, serie.clip, grid);
  896. }
  897. else Internal_CheckClipAndDrawPolygon(vh, ltp1, upPos1, upPos2, ltp2, lineColor, serie.clip, grid);
  898. }
  899. else
  900. {
  901. if (IsInRightOrUp(isYAxis, tp1, dnPos) || isTurnBack)
  902. {
  903. Internal_CheckClipAndDrawLine(vh, start, cp, serie.lineStyle.GetWidth(m_Theme.serie.lineWidth), lineColor, serie.clip, grid);
  904. }
  905. else
  906. {
  907. Internal_CheckClipAndDrawPolygon(vh, ltp1, dnPos, upPos1, ltp2, lineColor, serie.clip, grid);
  908. Internal_CheckClipAndDrawTriangle(vh, dnPos, upPos2, upPos1, lineColor, serie.clip, grid);
  909. i = segment;
  910. }
  911. }
  912. }
  913. }
  914. if (!isShort)
  915. {
  916. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, tp1, isEndPos);
  917. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, tp2, isEndPos);
  918. }
  919. }
  920. start = cp;
  921. ltp1 = tp1;
  922. ltp2 = tp2;
  923. }
  924. if (!isBreak && !isShort)
  925. {
  926. if (isDown)
  927. {
  928. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, upPos1, true);
  929. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, upPos2, true);
  930. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, dnPos, true);
  931. }
  932. else
  933. {
  934. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, dnPos, true);
  935. if (isYAxis)
  936. {
  937. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, isTheLastPos ? upPos1 : upPos2, true);
  938. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, isTheLastPos ? upPos2 : upPos1, true);
  939. }
  940. else
  941. {
  942. if (isTheLastPos)
  943. {
  944. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, upPos2, true);
  945. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, upPos1, true);
  946. }
  947. else
  948. {
  949. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, upPos1, true);
  950. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, upPos2, true);
  951. }
  952. }
  953. }
  954. }
  955. if (serie.areaStyle.show)
  956. {
  957. var lastSerie = SeriesHelper.GetLastStackSerie(m_Series, serie);
  958. if (lastSerie != null)
  959. {
  960. var lastSmoothPoints = lastSerie.GetUpSmoothList(dataIndex);
  961. DrawStackArea(vh, serie, axis, smoothDownPoints, lastSmoothPoints, areaColor, areaToColor);
  962. }
  963. else
  964. {
  965. var points = ((isYAxis && lp.x < zeroPos.x) || (!isYAxis && lp.y < zeroPos.y)) ? smoothPoints : smoothDownPoints;
  966. Vector3 aep = isYAxis ? new Vector3(zeroPos.x, zeroPos.y + grid.runtimeHeight) : new Vector3(zeroPos.x + grid.runtimeWidth, zeroPos.y);
  967. var sindex = 0;
  968. var eindex = 0;
  969. var sp = GetStartPos(points, ref sindex, serie.ignoreLineBreak);
  970. var ep = GetEndPos(points, ref eindex, serie.ignoreLineBreak);
  971. var cross = ChartHelper.GetIntersection(lp, np, zeroPos, aep);
  972. if (cross == Vector3.zero || smoothDownPoints.Count <= 3)
  973. {
  974. sp = points[sindex];
  975. for (int i = sindex + 1; i <= eindex; i++)
  976. {
  977. ep = points[i];
  978. if (serie.animation.CheckDetailBreak(ep, isYAxis)) break;
  979. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, Vector3.zero);
  980. sp = ep;
  981. }
  982. }
  983. else
  984. {
  985. var sp1 = smoothDownPoints[0];
  986. var ep1 = smoothDownPoints[smoothDownPoints.Count - 1];
  987. var axisLineWidth = axis.axisLine.GetWidth(m_Theme.axis.lineWidth);
  988. var axisUpStart = zeroPos + (isYAxis ? Vector3.right : Vector3.up) * axisLineWidth;
  989. var axisUpEnd = axisUpStart + (isYAxis ? Vector3.up * grid.runtimeHeight : Vector3.right * grid.runtimeWidth);
  990. var axisDownStart = zeroPos - (isYAxis ? Vector3.right : Vector3.up) * axisLineWidth;
  991. var axisDownEnd = axisDownStart + (isYAxis ? Vector3.up * grid.runtimeHeight : Vector3.right * grid.runtimeWidth);
  992. var luPos = ChartHelper.GetIntersection(sp1, ep1, axisUpStart, axisUpEnd);
  993. sp1 = smoothPoints[0];
  994. ep1 = smoothPoints[smoothPoints.Count - 2];
  995. var rdPos = ChartHelper.GetIntersection(sp1, ep1, axisDownStart, axisDownEnd);
  996. if ((isYAxis && lp.x >= zeroPos.x) || (!isYAxis && lp.y >= zeroPos.y))
  997. {
  998. sp = smoothDownPoints[0];
  999. for (int i = 1; i < smoothDownPoints.Count; i++)
  1000. {
  1001. ep = smoothDownPoints[i];
  1002. if (serie.animation.CheckDetailBreak(ep, isYAxis)) break;
  1003. if (luPos == Vector3.zero)
  1004. {
  1005. sp = ep;
  1006. continue;
  1007. }
  1008. if ((isYAxis && ep.y > luPos.y) || (!isYAxis && ep.x > luPos.x))
  1009. {
  1010. var tp = isYAxis ? new Vector3(luPos.x, sp.y) : new Vector3(sp.x, luPos.y);
  1011. Internal_CheckClipAndDrawTriangle(vh, sp, luPos, tp, areaColor, areaToColor, areaToColor, serie.clip, grid);
  1012. break;
  1013. }
  1014. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1015. sp = ep;
  1016. }
  1017. sp = smoothPoints[0];
  1018. bool first = false;
  1019. for (int i = 1; i < smoothPoints.Count; i++)
  1020. {
  1021. ep = smoothPoints[i];
  1022. if (serie.animation.CheckDetailBreak(ep, isYAxis)) break;
  1023. if ((isYAxis && ep.y <= rdPos.y) || (!isYAxis && ep.x <= rdPos.x)) continue;
  1024. if (rdPos == Vector3.zero)
  1025. {
  1026. sp = ep;
  1027. continue;
  1028. }
  1029. if (!first)
  1030. {
  1031. first = true;
  1032. var tp = isYAxis ? new Vector3(rdPos.x, ep.y) : new Vector3(ep.x, rdPos.y);
  1033. Internal_CheckClipAndDrawTriangle(vh, rdPos, tp, ep, areaToColor, areaToColor, areaColor, serie.clip, grid);
  1034. sp = ep;
  1035. continue;
  1036. }
  1037. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1038. sp = ep;
  1039. }
  1040. }
  1041. else
  1042. {
  1043. sp = smoothPoints[0];
  1044. for (int i = 1; i < smoothPoints.Count; i++)
  1045. {
  1046. ep = smoothPoints[i];
  1047. if (serie.animation.CheckDetailBreak(ep, isYAxis)) break;
  1048. if (rdPos == Vector3.zero)
  1049. {
  1050. sp = ep;
  1051. continue;
  1052. }
  1053. if ((isYAxis && ep.y > rdPos.y) || (!isYAxis && ep.x > rdPos.x))
  1054. {
  1055. var tp = isYAxis ? new Vector3(rdPos.x, sp.y) : new Vector3(sp.x, rdPos.y);
  1056. Internal_CheckClipAndDrawTriangle(vh, sp, rdPos, tp, areaColor, areaToColor, areaToColor, serie.clip, grid);
  1057. break;
  1058. }
  1059. if (rdPos != Vector3.zero) DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1060. sp = ep;
  1061. }
  1062. sp = smoothDownPoints[0];
  1063. bool first = false;
  1064. for (int i = 1; i < smoothDownPoints.Count; i++)
  1065. {
  1066. ep = smoothDownPoints[i];
  1067. if (serie.animation.CheckDetailBreak(ep, isYAxis)) break;
  1068. if ((isYAxis && ep.y < luPos.y) || (!isYAxis && ep.x < luPos.x)) continue;
  1069. if (luPos == Vector3.zero)
  1070. {
  1071. sp = ep;
  1072. continue;
  1073. }
  1074. if (!first)
  1075. {
  1076. first = true;
  1077. var tp = isYAxis ? new Vector3(luPos.x, ep.y) : new Vector3(ep.x, luPos.y);
  1078. Internal_CheckClipAndDrawTriangle(vh, ep, luPos, tp, areaColor, areaToColor, areaToColor, serie.clip, grid);
  1079. sp = ep;
  1080. continue;
  1081. }
  1082. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1083. sp = ep;
  1084. }
  1085. }
  1086. }
  1087. }
  1088. }
  1089. stPos1 = isDown ? upPos2 : dnPos;
  1090. stPos2 = isDown ? dnPos : upPos2;
  1091. lastDnPos = dnPos;
  1092. lastIsDown = isDown;
  1093. return !isBreak;
  1094. }
  1095. private bool TryAddToList(bool isTurnBack, bool isYAxis, List<Vector3> list, Vector3 lastPos, Vector3 pos, bool ignoreClose = false)
  1096. {
  1097. if (ChartHelper.IsZeroVector(pos)) return false;
  1098. if (isTurnBack)
  1099. {
  1100. list.Add(pos);
  1101. return true;
  1102. }
  1103. else if (!ChartHelper.IsZeroVector(lastPos) && IsInRightOrUpNotCheckZero(isYAxis, pos, lastPos))
  1104. {
  1105. return false;
  1106. }
  1107. else if (list.Count <= 0)
  1108. {
  1109. list.Add(pos);
  1110. return true;
  1111. }
  1112. else
  1113. {
  1114. var end = list[list.Count - 1];
  1115. if (IsInRightOrUpNotCheckZero(isYAxis, end, pos) && (!ignoreClose || !WasTooClose(isYAxis, end, pos, ignoreClose)))
  1116. {
  1117. list.Add(pos);
  1118. return true;
  1119. }
  1120. }
  1121. return false;
  1122. }
  1123. private void CheckLineGradientColor(Vector3 cp, LineStyle lineStyle, Axis axis, Color32 defaultLineColor, ref Color32 lineColor)
  1124. {
  1125. if (VisualMapHelper.IsNeedGradient(visualMap))
  1126. lineColor = VisualMapHelper.GetLineGradientColor(visualMap, cp, this, axis, defaultLineColor);
  1127. else if (lineStyle.IsNeedGradient())
  1128. lineColor = VisualMapHelper.GetLineStyleGradientColor(lineStyle, cp, this, axis, defaultLineColor);
  1129. }
  1130. private bool IsInRightOrUp(bool isYAxis, Vector3 lp, Vector3 rp)
  1131. {
  1132. return ChartHelper.IsZeroVector(lp) || ((isYAxis && rp.y > lp.y) || (!isYAxis && rp.x > lp.x));
  1133. }
  1134. private bool IsInRightOrUpNotCheckZero(bool isYAxis, Vector3 lp, Vector3 rp)
  1135. {
  1136. return (isYAxis && rp.y > lp.y) || (!isYAxis && rp.x > lp.x);
  1137. }
  1138. private bool WasTooClose(bool isYAxis, Vector3 lp, Vector3 rp, bool ignore)
  1139. {
  1140. if (ignore) return false;
  1141. if (lp == Vector3.zero || rp == Vector3.zero) return false;
  1142. if (isYAxis) return Mathf.Abs(rp.y - lp.y) < 1f;
  1143. else return Mathf.Abs(rp.x - lp.x) < 1f;
  1144. }
  1145. private void DrawPolygonToZero(VertexHelper vh, Vector3 sp, Vector3 ep, Axis axis, Vector3 zeroPos,
  1146. Color32 areaColor, Color32 areaToColor, Vector3 areaDiff, bool clip = false)
  1147. {
  1148. float diff = 0;
  1149. var grid = GetAxisGridOrDefault(axis);
  1150. var lineWidth = axis.axisLine.GetWidth(m_Theme.axis.lineWidth);
  1151. if (axis is YAxis)
  1152. {
  1153. var isLessthan0 = (sp.x < zeroPos.x || ep.x < zeroPos.x);
  1154. diff = isLessthan0 ? -lineWidth : lineWidth;
  1155. areaColor = GetYLerpColor(areaColor, areaToColor, sp, grid);
  1156. if (isLessthan0) areaDiff = -areaDiff;
  1157. Internal_CheckClipAndDrawPolygon(vh, new Vector3(zeroPos.x + diff, sp.y), new Vector3(zeroPos.x + diff, ep.y),
  1158. ep + areaDiff, sp + areaDiff, areaToColor, areaColor, clip, grid);
  1159. }
  1160. else
  1161. {
  1162. var isLessthan0 = (sp.y < zeroPos.y || ep.y < zeroPos.y);
  1163. diff = isLessthan0 ? -lineWidth : lineWidth;
  1164. areaColor = GetXLerpColor(areaColor, areaToColor, sp, grid);
  1165. if (isLessthan0) areaDiff = -areaDiff;
  1166. if (isLessthan0)
  1167. {
  1168. Internal_CheckClipAndDrawPolygon(vh, ep + areaDiff, sp + areaDiff, new Vector3(sp.x, zeroPos.y + diff),
  1169. new Vector3(ep.x, zeroPos.y + diff), areaColor, areaToColor, clip, grid);
  1170. }
  1171. else
  1172. {
  1173. Internal_CheckClipAndDrawPolygon(vh, sp + areaDiff, ep + areaDiff, new Vector3(ep.x, zeroPos.y + diff),
  1174. new Vector3(sp.x, zeroPos.y + diff), areaColor, areaToColor, clip, grid);
  1175. }
  1176. }
  1177. }
  1178. private List<Vector3> posList = new List<Vector3>();
  1179. private bool DrawOtherLine(VertexHelper vh, Serie serie, Axis axis, Vector3 lp,
  1180. Vector3 np, int dataIndex, Color32 lineColor, Color32 areaColor,
  1181. Color32 areaToColor, Vector3 zeroPos)
  1182. {
  1183. //lp = ClampInChart(lp);
  1184. //np = ClampInChart(np);
  1185. bool isYAxis = axis is YAxis;
  1186. var lineWidth = serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  1187. posList.Clear();
  1188. switch (serie.lineType)
  1189. {
  1190. case LineType.Dash:
  1191. UGL.DrawDashLine(vh, lp, np, lineWidth, lineColor, lineColor, 0, 0, posList);
  1192. break;
  1193. case LineType.Dot:
  1194. UGL.DrawDotLine(vh, lp, np, lineWidth, lineColor, lineColor, 0, 0, posList);
  1195. break;
  1196. case LineType.DashDot:
  1197. UGL.DrawDashDotLine(vh, lp, np, lineWidth, lineColor, 0, 0, 0, posList);
  1198. break;
  1199. case LineType.DashDotDot:
  1200. UGL.DrawDashDotDotLine(vh, lp, np, lineWidth, lineColor, 0, 0, 0, posList);
  1201. break;
  1202. }
  1203. if (serie.areaStyle.show && !isYAxis && posList.Count > 0)
  1204. {
  1205. lp = posList[0];
  1206. var value = serie.GetSerieData(dataIndex).data[1];
  1207. for (int i = 0; i < posList.Count; i++)
  1208. {
  1209. np = posList[i];
  1210. var start = new Vector3(lp.x, value > 0 ? (lp.y - lineWidth) : (lp.y + lineWidth));
  1211. var end = new Vector3(np.x, value > 0 ? (np.y - lineWidth) : (np.y + lineWidth));
  1212. DrawPolygonToZero(vh, start, end, axis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1213. lp = np;
  1214. }
  1215. }
  1216. return true;
  1217. }
  1218. private List<Vector3> bezierPoints = new List<Vector3>();
  1219. private Vector3 smoothStartPosUp, smoothStartPosDn;
  1220. private bool DrawSmoothLine(VertexHelper vh, Serie serie, Axis xAxis, Vector3 lp,
  1221. Vector3 np, Vector3 llp, Vector3 nnp, int dataIndex, Color32 lineColor, Color32 areaColor,
  1222. Color32 areaToColor, bool isStack, Vector3 zeroPos, int startIndex = 0)
  1223. {
  1224. var defaultLineColor = lineColor;
  1225. bool isYAxis = xAxis is YAxis;
  1226. var isTurnBack = IsInRightOrUp(isYAxis, np, lp);
  1227. var lineWidth = serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  1228. var smoothPoints = serie.GetUpSmoothList(dataIndex);
  1229. var smoothDownPoints = serie.GetDownSmoothList(dataIndex);
  1230. var lastSmoothPoint = Vector3.zero;
  1231. var lastSmoothDownPoint = Vector3.zero;
  1232. var grid = GetSerieGridOrDefault(serie);
  1233. if (dataIndex > startIndex)
  1234. {
  1235. lastSmoothPoint = ChartHelper.GetLastPoint(serie.GetUpSmoothList(dataIndex - 1));
  1236. lastSmoothDownPoint = ChartHelper.GetLastPoint(serie.GetDownSmoothList(dataIndex - 1));
  1237. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, lastSmoothPoint, true);
  1238. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, lastSmoothDownPoint, true);
  1239. }
  1240. if (isYAxis) ChartHelper.GetBezierListVertical(ref bezierPoints, lp, np, settings.lineSmoothness, settings.lineSmoothStyle);
  1241. else ChartHelper.GetBezierList(ref bezierPoints, lp, np, llp, nnp, settings.lineSmoothness, settings.lineSmoothStyle);
  1242. Vector3 start, to;
  1243. if (serie.lineType == LineType.SmoothDash)
  1244. {
  1245. for (int i = 0; i < bezierPoints.Count - 2; i += 2)
  1246. {
  1247. start = bezierPoints[i];
  1248. to = bezierPoints[i + 1];
  1249. CheckLineGradientColor(start, serie.lineStyle, xAxis, defaultLineColor, ref lineColor);
  1250. Internal_CheckClipAndDrawLine(vh, start, to, lineWidth, lineColor, serie.clip, grid);
  1251. }
  1252. return true;
  1253. }
  1254. start = bezierPoints[0];
  1255. var dir = bezierPoints[1] - start;
  1256. var dir1v = Vector3.Cross(dir, Vector3.forward).normalized * (isYAxis ? -1 : 1);
  1257. var diff = dir1v * lineWidth;
  1258. var startUp = start - diff;
  1259. var startDn = start + diff;
  1260. var startAreaDn = Vector3.zero;
  1261. var startAreaUp = Vector3.zero;
  1262. Vector3 toUp, toDn;
  1263. bool isFinish = true;
  1264. if (dataIndex > startIndex + 1)
  1265. {
  1266. if (smoothStartPosDn != Vector3.zero && smoothStartPosUp != Vector3.zero)
  1267. {
  1268. if (!serie.animation.IsInFadeOut())
  1269. {
  1270. CheckLineGradientColor(lp, serie.lineStyle, xAxis, defaultLineColor, ref lineColor);
  1271. Internal_CheckClipAndDrawTriangle(vh, smoothStartPosUp, startUp, lp, lineColor, serie.clip, grid);
  1272. Internal_CheckClipAndDrawTriangle(vh, smoothStartPosDn, startDn, lp, lineColor, serie.clip, grid);
  1273. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, smoothStartPosUp, false);
  1274. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, smoothStartPosDn, false);
  1275. }
  1276. }
  1277. }
  1278. else
  1279. {
  1280. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, startUp, false);
  1281. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, startDn, false);
  1282. }
  1283. var bezierPointsCount = bezierPoints.Count;
  1284. for (int k = 1; k < bezierPointsCount; k++)
  1285. {
  1286. var isEndPos = k == bezierPointsCount - 1;
  1287. to = bezierPoints[k];
  1288. if (serie.animation.CheckDetailBreak(to, isYAxis))
  1289. {
  1290. isFinish = false;
  1291. break;
  1292. }
  1293. dir = to - start;
  1294. dir1v = Vector3.Cross(dir, Vector3.forward).normalized * (isYAxis ? -1 : 1);
  1295. diff = dir1v * lineWidth;
  1296. toUp = to - diff;
  1297. toDn = to + diff;
  1298. CheckLineGradientColor(to, serie.lineStyle, xAxis, defaultLineColor, ref lineColor);
  1299. if (isYAxis) Internal_CheckClipAndDrawPolygon(vh, startDn, toDn, toUp, startUp, lineColor, serie.clip, grid);
  1300. else Internal_CheckClipAndDrawPolygon(vh, startUp, toUp, toDn, startDn, lineColor, serie.clip, grid);
  1301. TryAddToList(isTurnBack, isYAxis, smoothPoints, lastSmoothPoint, toUp, true);
  1302. TryAddToList(isTurnBack, isYAxis, smoothDownPoints, lastSmoothDownPoint, toDn, true);
  1303. if (isEndPos)
  1304. {
  1305. smoothStartPosUp = toUp;
  1306. smoothStartPosDn = toDn;
  1307. }
  1308. start = to;
  1309. startUp = toUp;
  1310. startDn = toDn;
  1311. }
  1312. if (serie.areaStyle.show && (serie.index == 0 || !isStack))
  1313. {
  1314. if (smoothDownPoints.Count > 0)
  1315. {
  1316. start = smoothDownPoints[0];
  1317. for (int i = 1; i < smoothDownPoints.Count; i++)
  1318. {
  1319. to = smoothDownPoints[i];
  1320. if (IsInRightOrUp(!isYAxis, zeroPos, to))
  1321. {
  1322. DrawPolygonToZero(vh, start, to, xAxis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1323. }
  1324. start = to;
  1325. }
  1326. }
  1327. if (smoothPoints.Count > 0)
  1328. {
  1329. start = smoothPoints[smoothPoints.Count - 1];
  1330. for (int i = smoothPoints.Count - 1; i >= 0; i--)
  1331. {
  1332. to = smoothPoints[i];
  1333. if (!IsInRightOrUp(!isYAxis, zeroPos, to))
  1334. {
  1335. DrawPolygonToZero(vh, to, start, xAxis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1336. }
  1337. start = to;
  1338. }
  1339. }
  1340. }
  1341. if (serie.areaStyle.show)
  1342. {
  1343. var lastSerie = SeriesHelper.GetLastStackSerie(m_Series, serie);
  1344. if (lastSerie != null)
  1345. {
  1346. var lastSmoothPoints = lastSerie.GetUpSmoothList(dataIndex);
  1347. DrawStackArea(vh, serie, xAxis, smoothDownPoints, lastSmoothPoints, areaColor, areaToColor);
  1348. }
  1349. }
  1350. return isFinish;
  1351. }
  1352. private bool IsAllLessthen0(bool isYAxis, Vector3 zeroPos, Vector3 start, Vector3 to)
  1353. {
  1354. if (isYAxis) return start.x < zeroPos.x && to.x < zeroPos.x;
  1355. else return start.y < zeroPos.y && to.y < zeroPos.y;
  1356. }
  1357. private Vector3 GetLastSmoothPos(List<Vector3> list, bool isYAxis)
  1358. {
  1359. var count = list.Count;
  1360. if (count <= 0) return Vector3.zero;
  1361. var pos = list[count - 1];
  1362. for (int i = count - 2; i > count - 4 && i > 0; i--)
  1363. {
  1364. if (isYAxis)
  1365. {
  1366. if (list[i].y > pos.y) pos = list[i];
  1367. }
  1368. else
  1369. {
  1370. if (list[i].x > pos.x) pos = list[i];
  1371. }
  1372. }
  1373. return pos;
  1374. }
  1375. private void DrawStackArea(VertexHelper vh, Serie serie, Axis axis, List<Vector3> smoothPoints,
  1376. List<Vector3> lastSmoothPoints, Color32 areaColor, Color32 areaToColor)
  1377. {
  1378. if (!serie.areaStyle.show || lastSmoothPoints.Count <= 0) return;
  1379. Vector3 start, to;
  1380. var isYAxis = axis is YAxis;
  1381. var lastCount = 1;
  1382. start = smoothPoints[0];
  1383. var sourAreaColor = areaColor;
  1384. var grid = GetAxisGridOrDefault(axis);
  1385. for (int k = 1; k < smoothPoints.Count; k++)
  1386. {
  1387. to = smoothPoints[k];
  1388. if (!IsInRightOrUp(isYAxis, start, to)) continue;
  1389. if (serie.animation.CheckDetailBreak(to, isYAxis)) break;
  1390. Vector3 tnp, tlp;
  1391. if (isYAxis) areaColor = GetYLerpColor(sourAreaColor, areaToColor, to, grid);
  1392. else areaColor = GetXLerpColor(sourAreaColor, areaToColor, to, grid);
  1393. if (k == smoothPoints.Count - 1)
  1394. {
  1395. if (k < lastSmoothPoints.Count - 1)
  1396. {
  1397. tnp = lastSmoothPoints[lastCount - 1];
  1398. Internal_CheckClipAndDrawTriangle(vh, start, to, tnp, areaColor, areaColor, areaToColor, serie.clip, grid);
  1399. while (lastCount < lastSmoothPoints.Count)
  1400. {
  1401. tlp = lastSmoothPoints[lastCount];
  1402. if (serie.animation.CheckDetailBreak(tlp, isYAxis)) break;
  1403. Internal_CheckClipAndDrawTriangle(vh, tnp, to, tlp, areaToColor, areaColor, areaToColor, serie.clip, grid);
  1404. lastCount++;
  1405. tnp = tlp;
  1406. }
  1407. start = to;
  1408. continue;
  1409. }
  1410. }
  1411. if (lastCount >= lastSmoothPoints.Count)
  1412. {
  1413. tlp = lastSmoothPoints[lastSmoothPoints.Count - 1];
  1414. if (serie.animation.CheckDetailBreak(tlp, isYAxis)) break;
  1415. Internal_CheckClipAndDrawTriangle(vh, to, start, tlp, areaColor, areaColor, areaToColor, serie.clip, grid);
  1416. start = to;
  1417. continue;
  1418. }
  1419. tnp = lastSmoothPoints[lastCount];
  1420. var diff = isYAxis ? tnp.y - to.y : tnp.x - to.x;
  1421. if (Math.Abs(diff) < 1)
  1422. {
  1423. tlp = lastSmoothPoints[lastCount - 1];
  1424. if (serie.animation.CheckDetailBreak(tlp, isYAxis)) break;
  1425. Internal_CheckClipAndDrawPolygon(vh, start, to, tnp, tlp, areaColor, areaToColor, serie.clip, grid);
  1426. lastCount++;
  1427. }
  1428. else
  1429. {
  1430. if (diff < 0)
  1431. {
  1432. tnp = lastSmoothPoints[lastCount - 1];
  1433. Internal_CheckClipAndDrawTriangle(vh, start, to, tnp, areaColor, areaColor, areaToColor, serie.clip, grid);
  1434. while (diff < 0 && lastCount < lastSmoothPoints.Count)
  1435. {
  1436. tlp = lastSmoothPoints[lastCount];
  1437. if (serie.animation.CheckDetailBreak(tlp, isYAxis)) break;
  1438. Internal_CheckClipAndDrawTriangle(vh, tnp, to, tlp, areaToColor, areaColor, areaToColor, serie.clip, grid);
  1439. lastCount++;
  1440. diff = isYAxis ? tlp.y - to.y : tlp.x - to.x;
  1441. tnp = tlp;
  1442. }
  1443. }
  1444. else
  1445. {
  1446. tlp = lastSmoothPoints[lastCount - 1];
  1447. if (serie.animation.CheckDetailBreak(tlp, isYAxis)) break;
  1448. Internal_CheckClipAndDrawTriangle(vh, start, to, tlp, areaColor, areaColor, areaToColor, serie.clip, grid);
  1449. }
  1450. }
  1451. start = to;
  1452. }
  1453. if (lastCount < lastSmoothPoints.Count)
  1454. {
  1455. var p1 = lastSmoothPoints[lastCount - 1];
  1456. var p2 = lastSmoothPoints[lastSmoothPoints.Count - 1];
  1457. if (!serie.animation.CheckDetailBreak(p1, isYAxis) && !serie.animation.CheckDetailBreak(p2, isYAxis))
  1458. {
  1459. Internal_CheckClipAndDrawTriangle(vh, p1, start, p2, areaToColor, areaColor, areaToColor, serie.clip, grid);
  1460. }
  1461. }
  1462. }
  1463. private List<Vector3> linePointList = new List<Vector3>();
  1464. private bool DrawStepLine(VertexHelper vh, Serie serie, Axis axis, Vector3 lp, Vector3 np,
  1465. Vector3 nnp, int dataIndex, Color32 lineColor, Color32 areaColor, Color32 areaToColor, Vector3 zeroPos)
  1466. {
  1467. bool isYAxis = axis is YAxis;
  1468. float lineWidth = serie.lineStyle.GetWidth(m_Theme.serie.lineWidth);
  1469. Vector3 start, end, middle, middleZero, middle1, middle2;
  1470. Vector3 sp, ep, diff1, diff2;
  1471. var areaDiff = isYAxis ? Vector3.left * lineWidth : Vector3.down * lineWidth;
  1472. var grid = GetAxisGridOrDefault(axis);
  1473. switch (serie.lineType)
  1474. {
  1475. case LineType.StepStart:
  1476. middle = isYAxis ? new Vector3(np.x, lp.y) : new Vector3(lp.x, np.y);
  1477. middleZero = isYAxis ? new Vector3(zeroPos.x, middle.y) : new Vector3(middle.x, zeroPos.y);
  1478. diff1 = (middle - lp).normalized * lineWidth;
  1479. diff2 = (np - middle).normalized * lineWidth;
  1480. start = dataIndex == 1 ? lp : lp + diff1;
  1481. end = nnp != np ? np - diff2 : np;
  1482. if (Vector3.Distance(lp, middle) > 2 * lineWidth)
  1483. {
  1484. ChartHelper.GetPointList(ref linePointList, start, middle - diff1, settings.lineSegmentDistance);
  1485. sp = linePointList[0];
  1486. for (int i = 1; i < linePointList.Count; i++)
  1487. {
  1488. ep = linePointList[i];
  1489. if (serie.animation.CheckDetailBreak(ep, isYAxis)) return false;
  1490. Internal_CheckClipAndDrawLine(vh, sp, ep, lineWidth, lineColor, serie.clip, grid);
  1491. sp = ep;
  1492. }
  1493. Internal_CheckClipAndDrawPolygon(vh, middle, lineWidth, lineColor, serie.clip, true, grid);
  1494. }
  1495. else
  1496. {
  1497. if (dataIndex == 1) Internal_CheckClipAndDrawPolygon(vh, lp, lineWidth, lineColor, serie.clip, true, grid);
  1498. Internal_CheckClipAndDrawLine(vh, lp + diff1, middle + diff1, lineWidth, lineColor, serie.clip, grid);
  1499. }
  1500. if (serie.areaStyle.show)
  1501. {
  1502. if (Vector3.Dot(middle - lp, middleZero - middle) >= 0)
  1503. {
  1504. DrawPolygonToZero(vh, middle - diff2, middle + diff2, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1505. }
  1506. else if (dataIndex == 1)
  1507. {
  1508. DrawPolygonToZero(vh, lp - diff2, lp + diff2, axis, zeroPos, areaColor, areaToColor, Vector3.zero);
  1509. }
  1510. }
  1511. ChartHelper.GetPointList(ref linePointList, middle + diff2, end, settings.lineSegmentDistance);
  1512. sp = linePointList[0];
  1513. for (int i = 1; i < linePointList.Count; i++)
  1514. {
  1515. ep = linePointList[i];
  1516. if (serie.animation.CheckDetailBreak(ep, isYAxis)) return false;
  1517. Internal_CheckClipAndDrawLine(vh, sp, ep, lineWidth, lineColor, serie.clip, grid);
  1518. if (serie.areaStyle.show)
  1519. {
  1520. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1521. }
  1522. sp = ep;
  1523. }
  1524. if (nnp != np)
  1525. {
  1526. if (serie.animation.CheckDetailBreak(np, isYAxis)) return false;
  1527. Internal_CheckClipAndDrawPolygon(vh, np, lineWidth, lineColor, serie.clip, true, grid);
  1528. bool flag = ((isYAxis && nnp.x > np.x && np.x > zeroPos.x) || (!isYAxis && nnp.y > np.y && np.y > zeroPos.y));
  1529. if (serie.areaStyle.show && flag)
  1530. {
  1531. DrawPolygonToZero(vh, np - diff2, np + diff2, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1532. }
  1533. }
  1534. break;
  1535. case LineType.StepMiddle:
  1536. middle1 = isYAxis ? new Vector2(lp.x, (lp.y + np.y) / 2) : new Vector2((lp.x + np.x) / 2, lp.y);
  1537. middle2 = isYAxis ? new Vector2(np.x, (lp.y + np.y) / 2) : new Vector2((lp.x + np.x) / 2, np.y);
  1538. middleZero = isYAxis ? new Vector3(zeroPos.x, middle1.y) : new Vector3(middle1.x, zeroPos.y);
  1539. diff1 = (middle1 - lp).normalized * lineWidth;
  1540. diff2 = (middle2 - middle1).normalized * lineWidth;
  1541. start = dataIndex == 1 ? lp : lp + diff1;
  1542. end = nnp != np ? np - diff2 : np;
  1543. //draw lp to middle1
  1544. if (Vector3.Distance(lp, middle1) > 2 * lineWidth)
  1545. {
  1546. ChartHelper.GetPointList(ref linePointList, start, middle1 - diff1, settings.lineSegmentDistance);
  1547. sp = linePointList[0];
  1548. for (int i = 1; i < linePointList.Count; i++)
  1549. {
  1550. ep = linePointList[i];
  1551. if (serie.animation.CheckDetailBreak(ep, isYAxis)) return false;
  1552. Internal_CheckClipAndDrawLine(vh, sp, ep, lineWidth, lineColor, serie.clip, grid);
  1553. if (serie.areaStyle.show)
  1554. {
  1555. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1556. }
  1557. sp = ep;
  1558. }
  1559. if (serie.animation.CheckDetailBreak(middle1, isYAxis)) return false;
  1560. Internal_CheckClipAndDrawPolygon(vh, middle1, lineWidth, lineColor, serie.clip, true, grid);
  1561. if (serie.areaStyle.show && Vector3.Dot(middleZero - middle1, middle2 - middle1) <= 0)
  1562. {
  1563. DrawPolygonToZero(vh, middle1 - diff1, middle1 + diff1, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1564. }
  1565. }
  1566. else
  1567. {
  1568. if (dataIndex == 1) Internal_CheckClipAndDrawPolygon(vh, lp, lineWidth, lineColor, serie.clip, true, grid);
  1569. Internal_CheckClipAndDrawLine(vh, lp + diff1, middle1 + diff1, lineWidth, lineColor, serie.clip, grid);
  1570. }
  1571. //draw middle1 to middle2
  1572. if (Vector3.Distance(middle1, middle2) > 2 * lineWidth)
  1573. {
  1574. ChartHelper.GetPointList(ref linePointList, middle1 + diff2, middle2 - diff2, settings.lineSegmentDistance);
  1575. sp = linePointList[0];
  1576. for (int i = 1; i < linePointList.Count; i++)
  1577. {
  1578. ep = linePointList[i];
  1579. Internal_CheckClipAndDrawLine(vh, sp, ep, lineWidth, lineColor, serie.clip, grid);
  1580. sp = ep;
  1581. }
  1582. Internal_CheckClipAndDrawPolygon(vh, middle2, lineWidth, lineColor, serie.clip, true, grid);
  1583. if (serie.areaStyle.show && Vector3.Dot(middleZero - middle2, middle2 - middle1) >= 0)
  1584. {
  1585. DrawPolygonToZero(vh, middle2 - diff1, middle2 + diff1, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1586. }
  1587. }
  1588. else
  1589. {
  1590. Internal_CheckClipAndDrawLine(vh, middle1 + diff2, middle2 + diff2, lineWidth, lineColor, serie.clip, grid);
  1591. }
  1592. //draw middle2 to np
  1593. if (Vector3.Distance(middle2, np) > 2 * lineWidth)
  1594. {
  1595. ChartHelper.GetPointList(ref linePointList, middle2 + diff1, np - diff1, settings.lineSegmentDistance);
  1596. sp = linePointList[0];
  1597. for (int i = 1; i < linePointList.Count; i++)
  1598. {
  1599. ep = linePointList[i];
  1600. if (serie.animation.CheckDetailBreak(ep, isYAxis)) return false;
  1601. Internal_CheckClipAndDrawLine(vh, sp, ep, lineWidth, lineColor, serie.clip, grid);
  1602. if (serie.areaStyle.show)
  1603. {
  1604. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1605. }
  1606. sp = ep;
  1607. }
  1608. if (serie.animation.CheckDetailBreak(np, isYAxis)) return false;
  1609. Internal_CheckClipAndDrawPolygon(vh, np, lineWidth, lineColor, serie.clip, true, grid);
  1610. if (serie.areaStyle.show)
  1611. {
  1612. DrawPolygonToZero(vh, np - diff1, np + diff1, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1613. }
  1614. }
  1615. else
  1616. {
  1617. Internal_CheckClipAndDrawLine(vh, middle1 + diff1, middle1 + diff1, lineWidth, lineColor, serie.clip, grid);
  1618. }
  1619. break;
  1620. case LineType.StepEnd:
  1621. middle = isYAxis ? new Vector3(lp.x, np.y) : new Vector3(np.x, lp.y);
  1622. middleZero = isYAxis ? new Vector3(zeroPos.x, middle.y) : new Vector3(middle.x, zeroPos.y);
  1623. diff1 = (middle - lp).normalized * lineWidth;
  1624. diff2 = (np - middle).normalized * lineWidth;
  1625. start = dataIndex == 1 ? lp : lp + diff1;
  1626. end = nnp != np ? np - diff2 : np;
  1627. if (Vector3.Distance(lp, middle) > 2 * lineWidth)
  1628. {
  1629. ChartHelper.GetPointList(ref linePointList, start, middle - diff1, settings.lineSegmentDistance);
  1630. sp = linePointList[0];
  1631. for (int i = 1; i < linePointList.Count; i++)
  1632. {
  1633. ep = linePointList[i];
  1634. if (serie.animation.CheckDetailBreak(ep, isYAxis)) return false;
  1635. Internal_CheckClipAndDrawLine(vh, sp, ep, lineWidth, lineColor, serie.clip, grid);
  1636. if (serie.areaStyle.show)
  1637. {
  1638. DrawPolygonToZero(vh, sp, ep, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1639. }
  1640. sp = ep;
  1641. }
  1642. if (serie.animation.CheckDetailBreak(middle, isYAxis)) return false;
  1643. Internal_CheckClipAndDrawPolygon(vh, middle, lineWidth, lineColor, serie.clip, true, grid);
  1644. if (serie.areaStyle.show && Vector3.Dot(np - middle, middleZero - middle) <= 0)
  1645. {
  1646. DrawPolygonToZero(vh, middle - diff1, middle + diff1, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1647. }
  1648. }
  1649. else
  1650. {
  1651. if (dataIndex == 1) Internal_CheckClipAndDrawPolygon(vh, lp, lineWidth, lineColor, serie.clip, true, grid);
  1652. Internal_CheckClipAndDrawLine(vh, lp + diff1, middle + diff1, lineWidth, lineColor, serie.clip, grid);
  1653. }
  1654. if (Vector3.Distance(middle, np) > 2 * lineWidth)
  1655. {
  1656. ChartHelper.GetPointList(ref linePointList, middle + diff2, end, settings.lineSegmentDistance);
  1657. sp = linePointList[0];
  1658. for (int i = 1; i < linePointList.Count; i++)
  1659. {
  1660. ep = linePointList[i];
  1661. Internal_CheckClipAndDrawLine(vh, sp, ep, lineWidth, lineColor, serie.clip, grid);
  1662. sp = ep;
  1663. }
  1664. if (nnp != np) Internal_CheckClipAndDrawPolygon(vh, np, lineWidth, lineColor, serie.clip, true, grid);
  1665. }
  1666. else
  1667. {
  1668. Internal_CheckClipAndDrawLine(vh, middle + diff2, np + diff2, lineWidth, lineColor, serie.clip, grid);
  1669. }
  1670. bool flag2 = ((isYAxis && middle.x > np.x && np.x > zeroPos.x) || (!isYAxis && middle.y > np.y && np.y > zeroPos.y));
  1671. if (serie.areaStyle.show && flag2)
  1672. {
  1673. DrawPolygonToZero(vh, np - diff1, np + diff1, axis, zeroPos, areaColor, areaToColor, areaDiff);
  1674. }
  1675. break;
  1676. }
  1677. return true;
  1678. }
  1679. }
  1680. }