public void Update() { mSliderUpdated = false; mSliders.RemoveAll(x => { CategoryData data; if (mData.TryGetValue(x.category, out data) == false) { return(true); } if (data.IsBezierCurve) { return(false); } List <DoubleVector3> points = data.Data; if (x.from >= points.Count || x.index >= points.Count) { return(true); } DoubleVector3 from = points[x.from]; DoubleVector3 to = x.To; double time = Time.time; time -= x.startTime; if (x.totalTime <= 0.0001f) { time = 1f; } else { time /= x.totalTime; Math.Max(0.0, Math.Min(time, 1.0)); } DoubleVector3 v = DoubleVector3.Lerp(from, to, time); x.current = v; points[x.index] = v; mSliderUpdated = true; if (time >= 1f) { ModifyMinMax(data, v); return(true); } return(false); }); if (mSliderUpdated) { RaiseRealtimeDataChanged(); } }
protected string StringFromAxisFormat(DoubleVector3 val, AxisBase axis, int fractionDigits, bool isX) { val.z = 0; double itemVal = isX ? val.x : val.y; var dic = VectorValueToStringMap; KeyValuePair <string, string> res; // Debug.Log("try get " + val + " count is " + dic.Count); if (dic.TryGetValue(val, out res)) { if (isX && res.Key != null) { return(res.Key); } if (isX == false && res.Value != null) { return(res.Value); } } if (axis == null) { return(ChartAdancedSettings.Instance.FormatFractionDigits(fractionDigits, itemVal, CustomNumberFormat)); } string toSet = ""; if (axis.Format == AxisFormat.Number) { toSet = ChartAdancedSettings.Instance.FormatFractionDigits(fractionDigits, itemVal, CustomNumberFormat); } else { DateTime date = ChartDateUtility.ValueToDate(itemVal); if (axis.Format == AxisFormat.DateTime) { toSet = ChartDateUtility.DateToDateTimeString(date, CustomDateTimeFormat); } else { if (axis.Format == AxisFormat.Date) { toSet = ChartDateUtility.DateToDateString(date); } else { toSet = ChartDateUtility.DateToTimeString(date); } } } return(toSet); }
/// <summary> /// adds a point to the category. The points are sorted by their x value automatically /// </summary> /// <param name="category"></param> /// <param name="point"></param> public void AddPointToCategory(string category, double x,double y, double pointSize = -1f) { if (!IsExtended && pointSize >= 0f) { Debug.LogError("Point sizes are not supported in the lite version of Graph and Chart"); pointSize = -1f; } if (mData.ContainsKey(category) == false) { Debug.LogWarning("Invalid category name. Make sure the category is present in the graph"); return; } CategoryData data = (CategoryData)mData[category]; if(data.IsBezierCurve == true) { Debug.LogWarning("Category is Bezier curve. use AddCurveToCategory instead "); return; } DoubleVector3 point = new DoubleVector3(x, y,pointSize); List<DoubleVector3> points = data.Data; if (data.MaxRadius.HasValue == false || data.MaxRadius.Value < pointSize) data.MaxRadius = pointSize; if (data.MaxX.HasValue == false || data.MaxX.Value < point.x) data.MaxX = point.x; if (data.MinX.HasValue == false || data.MinX.Value > point.x) data.MinX = point.x; if (data.MaxY.HasValue == false || data.MaxY.Value < point.y) data.MaxY = point.y; if (data.MinY.HasValue == false || data.MinY.Value > point.y) data.MinY = point.y; if (points.Count > 0) { if (data.AllowNonFunctions || points[points.Count - 1].x <= point.x) { points.Add(point); RaiseDataChanged(); return; } } // points.Add(point); int search = points.BinarySearch(point, mComparer); if (search < 0) search = ~search; points.Insert(search, point); RaiseDataChanged(); }
public void Normalize() { double num = DoubleVector3.Magnitude(this); if (num > 1E-05f) { this /= num; } else { this = DoubleVector3.zero; } }
public static DoubleVector3 ClampMagnitude(DoubleVector3 vector, double maxLength) { DoubleVector3 result; if (vector.sqrMagnitude > maxLength * maxLength) { result = vector.normalized * maxLength; } else { result = vector; } return(result); }
public void AddPointToCategoryRealtime(string category, double x, double y, double slideTime = 0f, double pointSize = -1f) { if (mData.ContainsKey(category) == false) { Debug.LogWarning("Invalid category name. Make sure the category is present in the graph"); return; } CategoryData data = (CategoryData)mData[category]; if (data.IsBezierCurve == true) { Debug.LogWarning("Category is Bezier curve. use AddCurveToCategory instead "); return; } DoubleVector3 point = new DoubleVector3(x, y, pointSize); List <DoubleVector3> points = data.Data; if (points.Count > 0) { if (points[points.Count - 1].x > point.x) { Debug.LogWarning("realtime points can only be added at the end of the graph"); return; } } if (slideTime <= 0f || points.Count == 0) { points.Add(point); ModifyMinMax(data, point); } else { Slider s = new Slider(this); s.category = category; s.from = points.Count - 1; s.index = points.Count; s.StartTime = Time.time; s.Duration = slideTime; s.To = point; mSliders.Add(s); s.current = points[points.Count - 1]; points.Add(s.current); } RaiseRealtimeDataChanged(); }
public static DoubleVector3 Normalize(DoubleVector3 value) { double num = DoubleVector3.Magnitude(value); DoubleVector3 result; if (num > 1E-05f) { result = value / num; } else { result = DoubleVector3.zero; } return(result); }
public override bool Equals(object other) { bool result; if (!(other is DoubleVector3)) { result = false; } else { DoubleVector3 vector = (DoubleVector3)other; result = (this.x.Equals(vector.x) && this.y.Equals(vector.y) && this.z.Equals(vector.z)); } return(result); }
/// <summary> /// gets the last point for the specified category. returns false if the category is empty , otherwise returns true and assigns the point to the "point" parameter /// </summary> /// <param name="category"></param> /// <param name="point"></param> /// <returns></returns> public bool GetLastPoint(string category, out DoubleVector3 point) { CategoryData data = (CategoryData)mData[category]; List <DoubleVector3> points = data.getPoints(); point = DoubleVector3.zero; if (points.Count == 0) { return(false); } int index = points.Count - 1; point = points[index]; return(true); }
public static void AddPointToCategoryWithLabelRealtime(GraphChartBase chart, string category, double x, double y, double slideTime = 0, double pointSize = -1, string xLabel = null, string yLabel = null) { bool invalidate = false; DoubleVector3 item = new DoubleVector3(x, y, 0.0); invalidate = chart.VectorValueToStringMap.Remove(item); chart.VectorValueToStringMap[item] = new KeyValuePair <string, string>(xLabel, yLabel); if (invalidate) { chart.ClearCache(); } chart.DataSource.AddPointToCategoryRealtime(category, x, y, slideTime, pointSize); }
public override bool Update() { BaseScrollableCategoryData baseData; CategoryData data; if (mParent.mData.TryGetValue(category, out baseData) == false) { return(true); } data = (CategoryData)baseData; if (data.IsBezierCurve) { return(false); } List <DoubleVector3> points = data.Data; if (from >= points.Count || index >= points.Count) { return(true); } DoubleVector3 fromPoint = points[from]; DoubleVector3 to = To; double time = Time.time; time -= StartTime; if (Duration <= 0.0001f) { time = 1f; } else { time /= Duration; Math.Max(0.0, Math.Min(time, 1.0)); } DoubleVector3 v = DoubleVector3.Lerp(fromPoint, to, time); current = v; points[index] = v; if (time >= 1f) { mParent.ModifyMinMax(data, v); return(true); } return(false); }
public void SetCurveInitialPoint(string category, double x, double y, double pointSize = -1f) { if (mData.ContainsKey(category) == false) { Debug.LogWarning("Invalid category name. Make sure the category is present in the graph"); return; } CategoryData data = (CategoryData)mData[category]; if (data.IsBezierCurve == false) { Debug.LogWarning("Category is not Bezier curve. use AddPointToCategory instead "); return; } if (data.Data.Count > 0) { Debug.LogWarning("Initial point already set for this category, call is ignored. Call ClearCategory to create a new curve"); return; } data.Regenerate = true; if (data.MaxRadius.HasValue == false || data.MaxRadius.Value < pointSize) { data.MaxRadius = pointSize; } if (data.MaxX.HasValue == false || data.MaxX.Value < x) { data.MaxX = x; } if (data.MinX.HasValue == false || data.MinX.Value > x) { data.MinX = x; } if (data.MaxY.HasValue == false || data.MaxY.Value < y) { data.MaxY = y; } if (data.MinY.HasValue == false || data.MinY.Value > y) { data.MinY = y; } DoubleVector3 sizedPoint = new DoubleVector3(x, y, pointSize); data.Data.Add(sizedPoint); RaiseDataChanged(); }
protected void TransformCandles(IList <CandleChartData.CandleValue> candles, List <CandleChartData.CandleValue> output, Rect viewRect, DoubleVector3 min, DoubleVector3 max) { DoubleVector3 range = max - min; if (range.x <= 0.0001f || range.y < 0.0001f) { return; } output.Clear(); for (int i = 0; i < candles.Count; i++) { CandleChartData.CandleValue candle = candles[i]; candle = InterpolateCandleInRect(NormalizeCandle(candle, min, range), viewRect); output.Add(candle); } }
public static DoubleVector3 MoveTowards(DoubleVector3 current, DoubleVector3 target, double maxDistanceDelta) { DoubleVector3 a = target - current; double magnitude = a.magnitude; DoubleVector3 result; if (magnitude <= maxDistanceDelta || magnitude == 0f) { result = target; } else { result = current + a / magnitude * maxDistanceDelta; } return(result); }
/// <summary> /// returns true if the axis unity rect is visible on the chart, even if it is only partially visible. false otherwise /// </summary> /// <param name="rect"></param> /// <returns></returns> public bool IsRectVisible(DoubleRect rect) { DoubleVector3 min = rect.min; DoubleVector3 max = rect.max; min = PointToNormalized(min.x, min.y); max = PointToNormalized(max.x, max.y); if (min.x > 1f || min.y > 1f) { return(false); } if (max.x < 0f || max.y < 0f) { return(false); } return(true); }
protected void TransformPoints(IList <DoubleVector3> points, Rect viewRect, DoubleVector3 min, DoubleVector3 max) { DoubleVector3 range = max - min; if (range.x <= 0.0001f || range.y < 0.0001f) { return; } double radiusMultiplier = Math.Min(viewRect.width / range.x, viewRect.height / range.y); for (int i = 0; i < points.Count; i++) { DoubleVector3 point = points[i]; DoubleVector4 res = interpolateInRect(viewRect, new DoubleVector3((point.x - min.x) / range.x, (point.y - min.y) / range.y)); res.z = point.z * radiusMultiplier; points[i] = res.ToDoubleVector3(); } }
private void Dots_Click(string category, int idx, Vector2 pos) { DoubleVector3 point = Data.GetPoint(category, idx); Dictionary <int, BillboardText> catgoryTexts; BillboardText b; if (mTexts.TryGetValue(category, out catgoryTexts)) { if (catgoryTexts.TryGetValue(idx, out b)) { SelectActiveText(b); } } string xString = StringFromAxisFormat(point.x, mHorizontalAxis, true); string yString = StringFromAxisFormat(point.y, mVerticalAxis, false); OnItemSelected(new GraphEventArgs(idx, pos, point.ToDoubleVector2(), (float)point.z, category, xString, yString)); }
public void SaveGraphDataToFile(string path, GraphChartBase graph) { IInternalGraphData data = (IInternalGraphData)graph; using (StreamWriter file = new StreamWriter(path)) { foreach (var cat in data.Categories) { file.WriteLine(cat.Name); file.WriteLine(cat.Data.Count); for (int i = 0; i < cat.Data.Count; i++) { DoubleVector3 item = cat.Data[i]; file.WriteLine(item.x); file.WriteLine(item.y); } } } }
protected void TransformPoints(IList <DoubleVector4> points, List <Vector4> output, Rect viewRect, DoubleVector3 min, DoubleVector3 max) { output.Clear(); DoubleVector3 range = max - min; if (range.x <= 0.0001f || range.y < 0.0001f) { return; } double radiusMultiplier = Math.Min(viewRect.width / range.x, viewRect.height / range.y); for (int i = 0; i < points.Count; i++) { DoubleVector4 point = points[i]; DoubleVector4 res = ChartCommon.interpolateInRect(viewRect, new DoubleVector3((point.x - min.x) / range.x, (point.y - min.y) / range.y)); res.z = 0.0; res.w = point.w * radiusMultiplier; output.Add(res.ToVector4()); } }
/// <summary> /// tranforms an axis unit rect into a recttransform. The rect transform must have a parent assigned to it. Also the chart and the rectTransform must share a common ancestor canvas /// </summary> /// <param name="assignTo">The rect tranform to which the result is assigned to</param> /// <param name="rect"></param> /// <param name="catgeory"></param> /// <returns></returns> public bool RectToCanvas(RectTransform assignTo, DoubleRect rect, string catgeory = null) { DoubleVector3 min = rect.min; DoubleVector3 max = rect.max; Vector3 worldMin, worldMax; if (PointToWorldSpace(out worldMin, min.x, min.y, catgeory) == false) { return(false); } if (PointToWorldSpace(out worldMax, max.x, max.y, catgeory) == false) { return(false); } Transform parent = assignTo.parent; if (parent == null) { return(false); } worldMin = parent.transform.InverseTransformPoint(worldMin); worldMax = parent.transform.InverseTransformPoint(worldMax); float minX = Math.Min(worldMin.x, worldMax.x); float minY = Math.Min(worldMin.y, worldMax.y); float sizeX = Math.Max(worldMin.x, worldMax.x) - minX; float sizeY = Math.Max(worldMin.y, worldMax.y) - minY; assignTo.anchorMin = new Vector2(0.5f, 0.5f); assignTo.anchorMax = new Vector2(0.5f, 0.5f); assignTo.pivot = new Vector2(0f, 0f); assignTo.anchoredPosition = new Vector2(minX, minY); assignTo.sizeDelta = new Vector2(sizeX, sizeY); return(true); }
protected void ModifyMinMax(BaseScrollableCategoryData data, DoubleVector3 point) { if (data.MaxRadius.HasValue == false || data.MaxRadius.Value < point.z) { data.MaxRadius = point.z; } if (data.MaxX.HasValue == false || data.MaxX.Value < point.x) { data.MaxX = point.x; } if (data.MinX.HasValue == false || data.MinX.Value > point.x) { data.MinX = point.x; } if (data.MaxY.HasValue == false || data.MaxY.Value < point.y) { data.MaxY = point.y; } if (data.MinY.HasValue == false || data.MinY.Value > point.y) { data.MinY = point.y; } }
public void MakeCurveCategorySmooth(string category) { if (mData.ContainsKey(category) == false) { Debug.LogWarning("Invalid category name. Make sure the category is present in the graph"); return; } CategoryData data = (CategoryData)mData[category]; if (data.IsBezierCurve == false) { Debug.LogWarning("Category is not Bezier curve. use AddPointToCategory instead "); return; } List <DoubleVector3> points = data.Data; data.Regenerate = true; mTmpDriv.Clear(); for (int i = 0; i < points.Count; i += 3) { DoubleVector3 prev = points[Mathf.Max(i - 3, 0)]; DoubleVector3 next = points[Mathf.Min(i + 3, points.Count - 1)]; DoubleVector3 diff = next - prev; mTmpDriv.Add(diff * 0.25f); } for (int i = 3; i < points.Count; i += 3) { int driv = i / 3; DoubleVector3 ct1 = points[i - 3] + (DoubleVector3)mTmpDriv[driv - 1]; DoubleVector3 ct2 = points[i] - (DoubleVector3)mTmpDriv[driv]; points[i - 2] = ct1; points[i - 1] = ct2; } RaiseDataChanged(); }
public static bool operator ==(DoubleVector3 lhs, DoubleVector3 rhs) { return(DoubleVector3.SqrMagnitude(lhs - rhs) < 9.99999944E-11f); }
private void DrawDivisions(double scrollOffset, AnyChart parent, Transform parentTransform, ChartDivisionInfo info, IChartMesh mesh, int group, ChartOrientation orientation, double gap, bool oppositeSide, double mainGap) { //scrollOffset = -scrollOffset; double parentSize = (orientation == ChartOrientation.Vertical) ? ((IInternalUse)parent).InternalTotalHeight : ((IInternalUse)parent).InternalTotalWidth; DoubleVector3 startPosition, lengthDirection, advanceDirection; GetDirectionVectors(parent, info, orientation, 0f, oppositeSide, out startPosition, out lengthDirection, out advanceDirection); double markDepth = ChartCommon.GetAutoDepth(parent, orientation, info); double length = ChartCommon.GetAutoLength(parent, orientation, info); double backLength = (orientation == ChartOrientation.Vertical) ? ((IInternalUse)parent).InternalTotalWidth : ((IInternalUse)parent).InternalTotalHeight; if (info.MarkBackLength.Automatic == false) { backLength = info.MarkBackLength.Value; } double totaluv = Math.Abs(length); if (backLength != 0 && markDepth > 0) { totaluv += Math.Abs(backLength) + Math.Abs(markDepth); } DoubleVector3 halfThickness = advanceDirection * (info.MarkThickness * 0.5f); // if (scrollOffset != 0f) // last--; bool hasValues = ((IInternalUse)parent).InternalHasValues(this); double maxValue = ((IInternalUse)parent).InternalMaxValue(this); double minValue = ((IInternalUse)parent).InternalMinValue(this); double range = maxValue - minValue; float AutoAxisDepth = Depth.Value; // float scrollFactor = (scrollOffset / (float)(maxValue - minValue)); //scrollOffset = scrollFactor * parentSize; if (Depth.Automatic) { AutoAxisDepth = (float)((((IInternalUse)parent).InternalTotalDepth) - markDepth); } double startValue = (scrollOffset + minValue); double endValue = (scrollOffset + maxValue) + double.Epsilon; double direction = 1.0; Func <double, double> ValueToPosition = x => ((x - startValue) / range) * parentSize; if (startValue > endValue) { direction = -1.0; //ValueToPosition = x => (1.0- ((x - startValue) / range)) * parentSize; } gap = Math.Abs(gap); double fraction = gap - (scrollOffset - Math.Floor((scrollOffset / gap) - double.Epsilon) * gap); double mainfraction = -1f; double currentMain = 0f; if (mainGap > 0f) { mainfraction = mainGap - (scrollOffset - Math.Floor((scrollOffset / mainGap) - double.Epsilon) * mainGap); currentMain = (scrollOffset + minValue + mainfraction); } int i = 0; mTmpToRemove.Clear(); double startRange = startValue + fraction; foreach (double key in mFormats.Keys) { if (key * direction > endValue * direction || key * direction < startRange * direction) { mTmpToRemove.Add(key); } } for (int k = 0; k < mTmpToRemove.Count; k++) { mFormats.Remove(mTmpToRemove[k]); } for (double current = startRange; direction *current <= direction *endValue; current += gap * direction) { ++i; if (i > 3000) { break; } if (mainGap > 0.0) { if (Math.Abs(current - currentMain) < 0.00001) { currentMain += mainGap; continue; } if (current > currentMain) { currentMain += mainGap; } } double offset = ValueToPosition(current); if (offset < 0 || offset > parentSize) { continue; } DoubleVector3 start = startPosition + advanceDirection * offset; DoubleVector3 size = halfThickness + length * lengthDirection; start -= halfThickness; //size += halfThickness; float uvoffset = 0f; Rect r = ChartCommon.FixRect(new Rect((float)start.x, (float)start.y, (float)size.x, (float)size.y)); SetMeshUv(mesh, (float)(-length / totaluv), uvoffset); uvoffset += Math.Abs(mesh.Length); mesh.AddXYRect(r, group, AutoAxisDepth); if (hasValues) { double val = Math.Round(current * 1000.0) / 1000.0; string toSet = ""; double keyVal = val;// (int)Math.Round(val); var dic = (orientation == ChartOrientation.Horizontal) ? parent.HorizontalValueToStringMap : parent.VerticalValueToStringMap; if (!(Math.Abs(val - keyVal) < 0.001 && dic.TryGetValue(keyVal, out toSet))) { if (mFormats.TryGetValue(val, out toSet) == false) { if (format == AxisFormat.Number) { toSet = ChartAdancedSettings.Instance.FormatFractionDigits(info.FractionDigits, val); } else { DateTime date = ChartDateUtility.ValueToDate(val); if (format == AxisFormat.DateTime) { toSet = ChartDateUtility.DateToDateTimeString(date, parent.CustomDateTimeFormat); } else { if (format == AxisFormat.Date) { toSet = ChartDateUtility.DateToDateString(date); } else { toSet = ChartDateUtility.DateToTimeString(date); } } } toSet = info.TextPrefix + toSet + info.TextSuffix; mFormats[val] = toSet; } } else { toSet = info.TextPrefix + toSet + info.TextSuffix; } DoubleVector3 textPos = new DoubleVector3(start.x, start.y); textPos += lengthDirection * info.TextSeperation; TextData userData = new TextData(); userData.interp = (float)(offset / parentSize); userData.info = info; userData.fractionDigits = info.FractionDigits; mesh.AddText(parent, info.TextPrefab, parentTransform, info.FontSize, info.FontSharpness, toSet, (float)textPos.x, (float)textPos.y, AutoAxisDepth + info.TextDepth, 0f, userData); } if (markDepth > 0) { if (orientation == ChartOrientation.Horizontal) { SetMeshUv(mesh, (float)(markDepth / totaluv), uvoffset); r = ChartCommon.FixRect(new Rect((float)start.x, AutoAxisDepth, (float)size.x, (float)markDepth)); mesh.AddXZRect(r, group, (float)start.y); } else { SetMeshUv(mesh, (float)(-markDepth / totaluv), uvoffset); r = ChartCommon.FixRect(new Rect((float)start.y, AutoAxisDepth, (float)size.y, (float)markDepth)); mesh.AddYZRect(r, group, (float)start.x); } uvoffset += Math.Abs(mesh.Length); if (backLength != 0) { SetMeshUv(mesh, (float)(backLength / totaluv), uvoffset); uvoffset += Math.Abs(mesh.Length); DoubleVector3 backSize = halfThickness + backLength * lengthDirection; Rect backR = ChartCommon.FixRect(new Rect((float)start.x, (float)start.y, (float)backSize.x, (float)backSize.y)); mesh.AddXYRect(backR, group, (float)(AutoAxisDepth + markDepth)); } } } // Debug.Log("start"); // Debug.Log(mFormats.Count); // Debug.Log(cached); }
public void AddInnerCurve(DoubleVector3 p1, DoubleVector3 c1, DoubleVector3 c2, DoubleVector3 p2) { for (int i = 0; i < SegmentsPerCurve; i++) { double blend = ((double)i) / (double)SegmentsPerCurve; double invBlend = 1f - blend; DoubleVector3 p = (invBlend * invBlend * invBlend * p1) + (3f * invBlend * invBlend * blend * c1) + (3f * blend * blend * invBlend * c2) + (blend * blend * blend * p2); mTmpCurveData.Add(new DoubleVector3(p.x, p.y, 0f)); } }
public override void InternalGenerateChart() { if (gameObject.activeInHierarchy == false) { return; } base.InternalGenerateChart(); if (FitToContainer) { RectTransform trans = GetComponent <RectTransform>(); widthRatio = trans.rect.width; heightRatio = trans.rect.height; } ClearChart(); if (Data == null) { return; } GenerateAxis(true); double minX = ((IInternalGraphData)Data).GetMinValue(0, false); double minY = ((IInternalGraphData)Data).GetMinValue(1, false); double maxX = ((IInternalGraphData)Data).GetMaxValue(0, false); double maxY = ((IInternalGraphData)Data).GetMaxValue(1, false); double xScroll = GetScrollOffset(0); double yScroll = GetScrollOffset(1); double xSize = maxX - minX; double ySize = maxY - minY; double xOut = minX + xScroll + xSize; double yOut = minY + yScroll + ySize; DoubleVector3 min = new DoubleVector3(xScroll + minX, yScroll + minY); DoubleVector3 max = new DoubleVector3(xOut, yOut); Rect viewRect = new Rect(0f, 0f, widthRatio, heightRatio); int index = 0; int total = ((IInternalGraphData)Data).TotalCategories + 1; bool edit = false; ClearBillboard(); mActiveTexts.Clear(); GameObject mask = CreateRectMask(viewRect); foreach (GraphData.CategoryData data in ((IInternalGraphData)Data).Categories) { mClipped.Clear(); DoubleVector3[] points = data.getPoints().ToArray(); Rect uv; int refrenceIndex = ClipPoints(points, mClipped, out uv); TransformPoints(mClipped, mTransformed, viewRect, min, max); if (points.Length == 0 && ChartCommon.IsInEditMode) { edit = true; int tmpIndex = total - 1 - index; float y1 = (((float)tmpIndex) / (float)total); float y2 = (((float)tmpIndex + 1) / (float)total); DoubleVector3 pos1 = ChartCommon.interpolateInRect(viewRect, new DoubleVector3(0f, y1, -1f)).ToDoubleVector3(); DoubleVector3 pos2 = ChartCommon.interpolateInRect(viewRect, new DoubleVector3(0.5f, y2, -1f)).ToDoubleVector3(); DoubleVector3 pos3 = ChartCommon.interpolateInRect(viewRect, new DoubleVector3(1f, y1, -1f)).ToDoubleVector3(); points = new DoubleVector3[] { pos1, pos2, pos3 }; mTransformed.AddRange(points.Select(x => (Vector4)x.ToVector3())); index++; } List <CanvasLines.LineSegement> list = new List <CanvasLines.LineSegement>(); list.Add(new CanvasLines.LineSegement(mTransformed)); CategoryObject categoryObj = new CategoryObject(); if (data.FillMaterial != null) { CanvasLines fill = CreateDataObject(data, mask); fill.material = data.FillMaterial; fill.SetRefrenceIndex(refrenceIndex); fill.SetLines(list); fill.SetViewRect(viewRect, uv); fill.MakeFillRender(viewRect, data.StetchFill); categoryObj.mFill = fill; } if (data.LineMaterial != null) { CanvasLines lines = CreateDataObject(data, mask); float tiling = 1f; if (data.LineTiling.EnableTiling == true && data.LineTiling.TileFactor > 0f) { float length = 0f; for (int i = 1; i < mTransformed.Count; i++) { length += (mTransformed[i - 1] - mTransformed[i]).magnitude; } tiling = length / data.LineTiling.TileFactor; } if (tiling <= 0.0001f) { tiling = 1f; } lines.SetViewRect(viewRect, uv); lines.Thickness = (float)data.LineThickness; lines.Tiling = tiling; lines.SetRefrenceIndex(refrenceIndex); lines.material = data.LineMaterial; lines.SetHoverPrefab(data.LineHoverPrefab); lines.SetLines(list); categoryObj.mLines = lines; } //if (data.PointMaterial != null) //{ CanvasLines dots = CreateDataObject(data, mask); categoryObj.mDots = dots; dots.material = data.PointMaterial; dots.SetLines(list); Rect pickRect = viewRect; float halfSize = (float)data.PointSize * 0.5f; pickRect.xMin -= halfSize; pickRect.yMin -= halfSize; pickRect.xMax += halfSize; pickRect.yMax += halfSize; dots.SetViewRect(pickRect, uv); dots.SetRefrenceIndex(refrenceIndex); dots.SetHoverPrefab(data.PointHoverPrefab); if (data.PointMaterial != null) { dots.MakePointRender((float)data.PointSize); } else { dots.MakePointRender(0f); } if (mItemLabels != null && mItemLabels.isActiveAndEnabled) { CanvasChartMesh m = new CanvasChartMesh(true); m.RecycleText = true; categoryObj.mItemLabels = m; Rect textRect = viewRect; textRect.xMin -= 1f; textRect.yMin -= 1f; textRect.xMax += 1f; textRect.yMax += 1f; for (int i = 0; i < mTransformed.Count; i++) { if (mTransformed[i].w == 0f) { continue; } DoubleVector2 pointValue = new DoubleVector2(mTransformed[i]); if (textRect.Contains(pointValue.ToVector2()) == false) { continue; } if (edit == false) { pointValue = Data.GetPoint(data.Name, i + refrenceIndex).ToDoubleVector2(); } string xFormat = StringFromAxisFormat(pointValue.x, mHorizontalAxis, mItemLabels.FractionDigits, true); string yFormat = StringFromAxisFormat(pointValue.y, mVerticalAxis, mItemLabels.FractionDigits, false); Vector3 labelPos = ((Vector3)mTransformed[i]) + new Vector3(mItemLabels.Location.Breadth, mItemLabels.Seperation, mItemLabels.Location.Depth); if (mItemLabels.Alignment == ChartLabelAlignment.Base) { labelPos.y -= mTransformed[i].y; } FormatItem(mRealtimeStringBuilder, xFormat, yFormat); string formatted = mRealtimeStringBuilder.ToString(); string toSet = mItemLabels.TextFormat.Format(formatted, data.Name, ""); BillboardText billboard = m.AddText(this, mItemLabels.TextPrefab, transform, mItemLabels.FontSize, mItemLabels.FontSharpness, toSet, labelPos.x, labelPos.y, labelPos.z, 0f, null); // BillboardText billboard = ChartCommon.CreateBillboardText(null,mItemLabels.TextPrefab, transform, toSet, labelPos.x, labelPos.y, labelPos.z, 0f, null, hideHierarchy, mItemLabels.FontSize, mItemLabels.FontSharpness); TextController.AddText(billboard); AddBillboardText(data.Name, i + refrenceIndex, billboard); } } string catName = data.Name; dots.Hover += (idx, t, d, pos) => { Dots_Hover(catName, idx, pos); }; dots.Click += (idx, t, d, pos) => { Dots_Click(catName, idx, pos); }; dots.Leave += () => { Dots_Leave(catName); }; mCategoryObjects[catName] = categoryObj; } }
public override void GenerateRealtime() { if (SupressRealtimeGeneration) { return; } base.GenerateRealtime(); double minX = ((IInternalGraphData)Data).GetMinValue(0, false); double minY = ((IInternalGraphData)Data).GetMinValue(1, false); double maxX = ((IInternalGraphData)Data).GetMaxValue(0, false); double maxY = ((IInternalGraphData)Data).GetMaxValue(1, false); double xScroll = GetScrollOffset(0); double yScroll = GetScrollOffset(1); double xSize = maxX - minX; double ySize = maxY - minY; double xOut = minX + xScroll + xSize; double yOut = minY + yScroll + ySize; DoubleVector3 min = new DoubleVector3(xScroll + minX, yScroll + minY); DoubleVector3 max = new DoubleVector3(xOut, yOut); Rect viewRect = new Rect(0f, 0f, widthRatio, heightRatio); Transform parentT = transform; if (mFixPosition != null) { parentT = mFixPosition.transform; } ClearBillboardCategories(); foreach (GraphData.CategoryData data in ((IInternalGraphData)Data).Categories) { CategoryObject obj = null; if (mCategoryObjects.TryGetValue(data.Name, out obj) == false) { continue; } mClipped.Clear(); mTmpData.Clear(); mTmpData.AddRange(data.getPoints()); Rect uv;// = new Rect(0f, 0f, 1f, 1f); int refrenceIndex = ClipPoints(mTmpData, mClipped, out uv); //mClipped.AddRange(mTmpData); TransformPoints(mClipped, mTransformed, viewRect, min, max); mTmpToRemove.Clear(); int range = refrenceIndex + mClipped.Count; foreach (int key in obj.mCahced.Keys) { if (key < refrenceIndex || key > range) { mTmpToRemove.Add(key); } } for (int i = 0; i < mTmpToRemove.Count; i++) { obj.mCahced.Remove(mTmpToRemove[i]); } obj.mCahced.Remove(mTmpData.Count - 1); // never store the last point cache , it might be intepolating by the realtime feature if (mTmpData.Count == 0) { continue; } if (mItemLabels != null && mItemLabels.isActiveAndEnabled && obj.mItemLabels != null) { Rect textRect = viewRect; textRect.xMin -= 1f; textRect.yMin -= 1f; textRect.xMax += 1f; textRect.yMax += 1f; CanvasChartMesh m = obj.mItemLabels; m.Clear(); for (int i = 0; i < mTransformed.Count; i++) { if (mTransformed[i].w == 0.0) { continue; } Vector3 labelPos = ((Vector3)mTransformed[i]) + new Vector3(mItemLabels.Location.Breadth, mItemLabels.Seperation, mItemLabels.Location.Depth); if (mItemLabels.Alignment == ChartLabelAlignment.Base) { labelPos.y -= (float)mTransformed[i].y; } if (textRect.Contains((Vector2)(mTransformed[i])) == false) { continue; } string toSet = null; int pointIndex = i + refrenceIndex; if (obj.mCahced.TryGetValue(pointIndex, out toSet) == false) { DoubleVector3 pointValue = mTmpData[i + refrenceIndex]; string xFormat = StringFromAxisFormat(pointValue.x, mHorizontalAxis, mItemLabels.FractionDigits, true); string yFormat = StringFromAxisFormat(pointValue.y, mVerticalAxis, mItemLabels.FractionDigits, false); FormatItem(mRealtimeStringBuilder, xFormat, yFormat); string formatted = mRealtimeStringBuilder.ToString(); mItemLabels.TextFormat.Format(mRealtimeStringBuilder, formatted, data.Name, ""); toSet = mRealtimeStringBuilder.ToString(); obj.mCahced[pointIndex] = toSet; } BillboardText billboard = m.AddText(this, mItemLabels.TextPrefab, parentT, mItemLabels.FontSize, mItemLabels.FontSharpness, toSet, labelPos.x, labelPos.y, labelPos.z, 0f, null); AddBillboardText(data.Name, i + refrenceIndex, billboard); } m.DestoryRecycled(); if (m.TextObjects != null) { foreach (BillboardText text in m.TextObjects) { ((IInternalUse)this).InternalTextController.AddText(text); } } } if (obj.mDots != null) { Rect pickRect = viewRect; float halfSize = (float)(data.PointSize * 0.5f); pickRect.xMin -= halfSize; pickRect.yMin -= halfSize; pickRect.xMax += halfSize; pickRect.yMax += halfSize; obj.mDots.SetViewRect(pickRect, uv); obj.mDots.ModifyLines(mTransformed); obj.mDots.SetRefrenceIndex(refrenceIndex); } if (obj.mLines != null) { float tiling = 1f; if (data.LineTiling.EnableTiling == true && data.LineTiling.TileFactor > 0f) { float length = 0f; for (int i = 1; i < mTransformed.Count; i++) { length += (mTransformed[i - 1] - mTransformed[i]).magnitude; } tiling = length / data.LineTiling.TileFactor; } if (tiling <= 0.0001f) { tiling = 1f; } obj.mLines.Tiling = tiling; obj.mLines.SetViewRect(viewRect, uv); obj.mLines.ModifyLines(mTransformed); obj.mLines.SetRefrenceIndex(refrenceIndex); } if (obj.mFill != null) { obj.mFill.SetViewRect(viewRect, uv); obj.mFill.ModifyLines(mTransformed); obj.mFill.SetRefrenceIndex(refrenceIndex); } } }
public override void InternalGenerateChart() { if (gameObject.activeInHierarchy == false) { return; } base.InternalGenerateChart(); ClearChart(); if (Data == null) { return; } double minX = (float)((IInternalGraphData)Data).GetMinValue(0, false); double minY = (float)((IInternalGraphData)Data).GetMinValue(1, false); double maxX = (float)((IInternalGraphData)Data).GetMaxValue(0, false); double maxY = (float)((IInternalGraphData)Data).GetMaxValue(1, false); DoubleVector3 min = new DoubleVector3(minX, minY); DoubleVector3 max = new DoubleVector3(maxX, maxY); Rect viewRect = new Rect(0f, 0f, widthRatio, heightRatio); int index = 0; int total = ((IInternalGraphData)Data).TotalCategories + 1; double positiveDepth = 0f; double maxThickness = 0f; bool edit = false; m3DTexts.Clear(); mActiveTexts.Clear(); foreach (GraphData.CategoryData data in ((IInternalGraphData)Data).Categories) { maxThickness = Math.Max(data.LineThickness, maxThickness); DoubleVector3[] points = data.getPoints().ToArray(); TransformPoints(points, viewRect, min, max); if (points.Length == 0 && ChartCommon.IsInEditMode) { edit = true; int tmpIndex = total - 1 - index; float y1 = (((float)tmpIndex) / (float)total); float y2 = (((float)tmpIndex + 1) / (float)total); DoubleVector3 pos1 = ChartCommon.interpolateInRect(viewRect, new DoubleVector3(0f, y1, -1f)).ToDoubleVector3(); DoubleVector3 pos2 = ChartCommon.interpolateInRect(viewRect, new DoubleVector3(0.5f, y2, -1f)).ToDoubleVector3(); DoubleVector3 pos3 = ChartCommon.interpolateInRect(viewRect, new DoubleVector3(1f, y1, -1f)).ToDoubleVector3(); points = new DoubleVector3[] { pos1, pos2, pos3 }; index++; } /*if (data.FillMaterial != null) * { * CanvasLines fill = CreateDataObject(data); * fill.material = data.FillMaterial; * fill.SetLines(list); * fill.MakeFillRender(viewRect, data.StetchFill); * }*/ if (data.Depth > 0) { positiveDepth = Math.Max(positiveDepth, data.Depth); } // if (data.DotPrefab != null) //{ for (int i = 0; i < points.Length; i++) { DoubleVector3 pointValue = points[i]; if (edit == false) { pointValue = Data.GetPoint(data.Name, i); } string xFormat = StringFromAxisFormat(pointValue.x, mHorizontalAxis); string yFormat = StringFromAxisFormat(pointValue.y, mVerticalAxis); GraphEventArgs args = new GraphEventArgs(i, (points[i] + new DoubleVector3(0.0, 0.0, data.Depth)).ToVector3(), pointValue.ToDoubleVector2(), (float)pointValue.z, data.Name, xFormat, yFormat); GameObject point = CreatePointObject(data); ChartItemEvents[] events = point.GetComponentsInChildren <ChartItemEvents>(); for (int j = 0; j < events.Length; ++j) { if (events[j] == null) { continue; } InternalItemEvents comp = (InternalItemEvents)events[j]; comp.Parent = this; comp.UserData = args; } double pointSize = points[i].z * data.PointSize; if (pointSize < 0f) { pointSize = data.PointSize; } point.transform.localScale = new DoubleVector3(pointSize, pointSize, pointSize).ToVector3(); if (data.PointMaterial != null) { Renderer rend = point.GetComponent <Renderer>(); if (rend != null) { rend.material = data.PointMaterial; } ChartMaterialController controller = point.GetComponent <ChartMaterialController>(); if (controller != null && controller.Materials != null) { Color hover = controller.Materials.Hover; Color selected = controller.Materials.Selected; controller.Materials = new ChartDynamicMaterial(data.PointMaterial, hover, selected); } } DoubleVector3 position = points[i]; position.z = data.Depth; point.transform.localPosition = position.ToVector3(); if (mItemLabels != null && mItemLabels.isActiveAndEnabled) { Vector3 labelPos = (points[i] + new DoubleVector3(mItemLabels.Location.Breadth, mItemLabels.Seperation, mItemLabels.Location.Depth + data.Depth)).ToVector3(); if (mItemLabels.Alignment == ChartLabelAlignment.Base) { labelPos.y -= (float)points[i].y; } FormatItem(mRealtimeStringBuilder, xFormat, yFormat); string formatted = mRealtimeStringBuilder.ToString(); string toSet = mItemLabels.TextFormat.Format(formatted, data.Name, ""); BillboardText billboard = ChartCommon.CreateBillboardText(null, mItemLabels.TextPrefab, transform, toSet, labelPos.x, labelPos.y, labelPos.z, 0f, null, hideHierarchy, mItemLabels.FontSize, mItemLabels.FontSharpness); TextController.AddText(billboard); AddBillboardText(data.Name, billboard); } } //} for (int i = 0; i < points.Length; i++) { points[i].z = 0f; } Vector3[] floatPoints = points.Select(x => x.ToVector3()).ToArray(); if (data.LinePrefab != null) { PathGenerator lines = CreateLineObject(data); // float tiling = 1f; if (data.LineTiling.EnableTiling == true && data.LineTiling.TileFactor > 0f) { float length = 0f; for (int i = 1; i < points.Length; i++) { length += (float)(points[i - 1] - points[i]).magnitude; } // tiling = length / data.LineTiling.TileFactor; } lines.Generator(floatPoints, (float)data.LineThickness, false); Vector3 tmp = lines.transform.localPosition; tmp.z = (float)data.Depth; lines.transform.localPosition = tmp; if (data.LineMaterial != null) { Renderer rend = lines.GetComponent <Renderer>(); if (rend != null) { rend.material = data.LineMaterial; } ChartMaterialController controller = lines.GetComponent <ChartMaterialController>(); if (controller != null && controller.Materials != null) { Color hover = controller.Materials.Hover; Color selected = controller.Materials.Selected; controller.Materials = new ChartDynamicMaterial(data.LineMaterial, hover, selected); } } } totalDepth = (float)(positiveDepth + maxThickness * 2f); if (data.FillPrefab != null) { FillPathGenerator fill = CreateFillObject(data); Vector3 tmp = fill.transform.localPosition; tmp.z = (float)data.Depth; fill.transform.localPosition = tmp; if (data.LinePrefab == null || !(data.LinePrefab is SmoothPathGenerator)) { fill.SetLineSmoothing(false, 0, 0f); } else { SmoothPathGenerator smooth = ((SmoothPathGenerator)data.LinePrefab); fill.SetLineSmoothing(true, smooth.JointSmoothing, smooth.JointSize); } fill.SetGraphBounds(viewRect.yMin, viewRect.yMax); fill.SetStrechFill(data.StetchFill); fill.Generator(floatPoints, (float)data.LineThickness * 1.01f, false); if (data.FillMaterial != null) { Renderer rend = fill.GetComponent <Renderer>(); if (rend != null) { rend.material = data.FillMaterial; } ChartMaterialController controller = fill.GetComponent <ChartMaterialController>(); if (controller != null && controller.Materials != null) { Color hover = controller.Materials.Hover; Color selected = controller.Materials.Selected; controller.Materials = new ChartDynamicMaterial(data.FillMaterial, hover, selected); } } } } GenerateAxis(true); }
internal static double normalizeInRangeY(double value, DoubleVector3 min, DoubleVector3 size) { return(normalizeInRange(value, min.y, size.y)); }
// /// <summary> // /// used internally to draw the division of the axis into a chart mesh // /// </summary> // /// <param name="parent"></param> // /// <param name="parentTransform"></param> // /// <param name="info"></param> // /// <param name="mesh"></param> // /// <param name="group"></param> // /// <param name="orientation"></param> // /// <param name="totalDivisions"></param> // /// <param name="oppositeSide"></param> // /// <param name="skip"></param> // private void DrawDivisions(float scrollOffset,AnyChart parent, Transform parentTransform, ChartDivisionInfo info, IChartMesh mesh, int group, ChartOrientation orientation, float totalDivisions, bool oppositeSide, int skip) // { // //scrollOffset = -scrollOffset; // float parentSize = (orientation == ChartOrientation.Vertical) ? ((IInternalUse)parent).InternalTotalHeight : ((IInternalUse)parent).InternalTotalWidth; // Vector2 startPosition, lengthDirection, advanceDirection; // GetDirectionVectors(parent, info, orientation, 0f, oppositeSide, out startPosition, out lengthDirection, out advanceDirection); // float markDepth = ChartCommon.GetAutoDepth(parent, orientation, info); // float length = ChartCommon.GetAutoLength(parent, orientation, info); // float backLength = (orientation == ChartOrientation.Vertical) ? ((IInternalUse)parent).InternalTotalWidth : ((IInternalUse)parent).InternalTotalHeight; // if (info.MarkBackLength.Automatic == false) // backLength = info.MarkBackLength.Value; // float totaluv = Math.Abs(length); // if (backLength != 0 && markDepth > 0) // totaluv += Math.Abs(backLength) + Math.Abs(markDepth); // Vector2 halfThickness = advanceDirection * (info.MarkThickness * 0.5f); // // if (scrollOffset != 0f) // // last--; // bool hasValues = ((IInternalUse)parent).InternalHasValues(this); // double maxValue = ((IInternalUse)parent).InternalMaxValue(this); // double minValue = ((IInternalUse)parent).InternalMinValue(this); // ChartMainDivisionInfo main = info as ChartMainDivisionInfo; // float divisionComplement = 0f; // float divisionOffsetComplement = 0f; // if (main != null) // { // if(main.Messure == ChartDivisionInfo.DivisionMessure.DataUnits) // { // if (main.UnitsPerDivision <= 0.0001f) // return; // float range = (float)(maxValue - minValue); // totalDivisions = (range / main.UnitsPerDivision) + 1; // divisionComplement = (float)(1f - (main.UnitsPerDivision - Math.Truncate(main.UnitsPerDivision))) / range; // divisionOffsetComplement = (divisionComplement) * parentSize; // } // } // float first, last; // GetStartEnd(parent, orientation, totalDivisions, out first, out last); // float AutoAxisDepth = Depth.Value; // float scrollFactor = (scrollOffset / (float)(maxValue - minValue)); // scrollOffset = scrollFactor * parentSize; // if (Depth.Automatic) // { // AutoAxisDepth = (((IInternalUse)parent).InternalTotalDepth) - markDepth; // } // float floorLast = Mathf.Floor(last); // for (float i = first; i < floorLast; i++) // { // if (skip != -1 && ((int)i) % skip == 0) // continue; // float factor = ((float)i) / (float)(totalDivisions - 1); // float offset = -scrollOffset + factor * parentSize; // if (scrollOffset != 0f) // { // float prevOffs = offset; // offset = offset - Mathf.Floor((offset / parentSize)) * parentSize; //// Debug.Log("prev " + prevOffs); //// Debug.Log("offs " + offset); // if (offset < prevOffs) // { // offset -= divisionOffsetComplement; // } // } // if (offset < 0f) // continue; // Vector2 start = startPosition + advanceDirection * offset; // Vector2 size = halfThickness + length * lengthDirection; // start -= halfThickness; // //size += halfThickness; // float uvoffset = 0f; // Rect r = ChartCommon.FixRect(new Rect(start.x, start.y, size.x, size.y)); // SetMeshUv(mesh, -length / totaluv, uvoffset); // uvoffset += Math.Abs(mesh.Length); // mesh.AddXYRect(r, group, AutoAxisDepth); // if (hasValues) // { // float valFactor = -scrollFactor + factor; // if (scrollOffset != 0f) // { // float prevFact = valFactor; // valFactor -= Mathf.Floor(valFactor); // if(valFactor < prevFact) // { // valFactor -= divisionComplement; // } // } // //valFactor += scrollFactor; // double offsetPos = (maxValue - minValue) * valFactor; // double scroll = minValue + ((maxValue - minValue) * scrollFactor); // double val = scroll + offsetPos; // string toSet = ""; // if (format == AxisFormat.Number) // toSet = ChartAdancedSettings.Instance.FormatFractionDigits(info.FractionDigits, (float)val); // else // { // DateTime date = ChartDateUtility.ValueToDate(val); // if (format == AxisFormat.DateTime) // toSet = ChartDateUtility.DateToDateTimeString(date); // else // { // if (format == AxisFormat.Date) // toSet = ChartDateUtility.DateToDateString(date); // else // toSet = ChartDateUtility.DateToTimeString(date); // } // } // toSet = info.TextPrefix + toSet + info.TextSuffix; // Vector2 textPos = new Vector2(start.x, start.y); // textPos += lengthDirection * info.TextSeperation; // TextData userData = new TextData(); // userData.interp = factor; // userData.info = info; // userData.fractionDigits = info.FractionDigits; // mesh.AddText(parent, info.TextPrefab, parentTransform, info.FontSize, info.FontSharpness, toSet, textPos.x, textPos.y, AutoAxisDepth + info.TextDepth,0f, userData); // } // if (markDepth > 0) // { // if (orientation == ChartOrientation.Horizontal) // { // SetMeshUv(mesh, markDepth / totaluv, uvoffset); // r = ChartCommon.FixRect(new Rect(start.x, AutoAxisDepth, size.x, markDepth)); // mesh.AddXZRect(r, group, start.y); // } // else // { // SetMeshUv(mesh, -markDepth / totaluv, uvoffset); // r = ChartCommon.FixRect(new Rect(start.y, AutoAxisDepth, size.y, markDepth)); // mesh.AddYZRect(r, group, start.x); // } // uvoffset += Math.Abs(mesh.Length); // if (backLength != 0) // { // SetMeshUv(mesh, backLength / totaluv, uvoffset); // uvoffset += Math.Abs(mesh.Length); // Vector2 backSize = halfThickness + backLength * lengthDirection; // Rect backR = ChartCommon.FixRect(new Rect(start.x, start.y, backSize.x, backSize.y)); // mesh.AddXYRect(backR, group, AutoAxisDepth + markDepth); // } // } // } // } /// <summary> /// used internally to determine drawing direction of the each chart division /// </summary> /// <param name="parent"></param> /// <param name="info"></param> /// <param name="orientation"></param> /// <param name="oppositeSide"></param> /// <param name="startPosition"></param> /// <param name="lengthDirection"></param> /// <param name="advanceDirection"></param> private void GetDirectionVectors(AnyChart parent, ChartDivisionInfo info, ChartOrientation orientation, float scrollOffset, bool oppositeSide, out DoubleVector3 startPosition, out DoubleVector3 lengthDirection, out DoubleVector3 advanceDirection) { if (orientation == ChartOrientation.Horizontal) { advanceDirection = new DoubleVector3(1f, 0f); if (oppositeSide) { startPosition = new DoubleVector3(scrollOffset, ((IInternalUse)parent).InternalTotalHeight); lengthDirection = new DoubleVector3(0f, -1f); return; } startPosition = new DoubleVector3(0f, 0f); lengthDirection = new DoubleVector3(0f, 1f); return; } advanceDirection = new DoubleVector3(0f, 1f); if (oppositeSide) { startPosition = new DoubleVector3(0f, 0f); lengthDirection = new DoubleVector3(1f, 0f); return; } startPosition = new DoubleVector3(((IInternalUse)parent).InternalTotalWidth, scrollOffset); lengthDirection = new DoubleVector3(-1f, 0f); }