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