internal double FromPreviousState(double value, AxisOrientation source, ChartCore chart) { if (LastAxisMax == null) { return(0); } var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientation.Y) { p1.X = LastAxisMax ?? 0; p1.Y = LastPlotArea.Top; p2.X = LastAxisMin ?? 0; p2.Y = LastPlotArea.Top + LastPlotArea.Height; } else { p1.X = LastAxisMax ?? 0; p1.Y = LastPlotArea.Width + LastPlotArea.Left; p2.X = LastAxisMin ?? 0; p2.Y = LastPlotArea.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); var d = m * (value - p1.X) + p2.Y; return(d); }
/// <summary> /// Drags the specified delta. /// </summary> /// <param name="delta">The delta.</param> public void Drag(CorePoint delta) { if ((View.Pan == PanningOptions.Unset && View.Zoom == ZoomingOptions.None) || View.Pan == PanningOptions.None) { return; } var px = View.Pan == PanningOptions.Unset && (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy); px = px || View.Pan == PanningOptions.X || View.Pan == PanningOptions.Xy; if (px) { foreach (var xi in AxisX) { xi.View.SetRange((double.IsNaN(xi.MinValue) ? xi.BotLimit : xi.MinValue) + delta.X, (double.IsNaN(xi.MaxValue) ? xi.TopLimit : xi.MaxValue) + delta.X); } } var py = View.Pan == PanningOptions.Unset && (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy); py = py || View.Pan == PanningOptions.Y || View.Pan == PanningOptions.Xy; if (py) { foreach (var ax in AxisY) { ax.View.SetRange((double.IsNaN(ax.MinValue) ? ax.BotLimit : ax.MinValue) + delta.Y, (double.IsNaN(ax.MaxValue) ? ax.TopLimit : ax.MaxValue) + delta.Y); } } }
/// <summary> /// Converts from chart values to chart control size. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation to scale value at</param> /// <param name="chart">chart model to scale value at</param> /// <param name="axis">axis model instance</param> /// <returns></returns> public static double ToPlotArea(double value, AxisOrientation source, ChartCore chart, AxisCore axis) { var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientation.Y) { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Top; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Top + chart.DrawMargin.Height; } else { p1.X = axis.TopLimit; p1.Y = chart.DrawMargin.Width + chart.DrawMargin.Left; p2.X = axis.BotLimit; p2.Y = chart.DrawMargin.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); return(m * (value - p1.X) + p1.Y); }
/// <summary> /// Ends the segment. /// </summary> /// <param name="atIndex">At index.</param> /// <param name="location">The location.</param> public virtual void EndSegment(int atIndex, CorePoint location) { var splitter = Splitters[ActiveSplitters - 1]; var animSpeed = Model.Chart.View.AnimationsSpeed; var noAnim = Model.Chart.View.DisableAnimations; var areaLimit = ChartFunctions.ToDrawMargin(double.IsNaN(AreaLimit) ? Model.Chart.AxisY[ScalesYAt].FirstSeparator : AreaLimit, AxisOrientation.Y, Model.Chart, ScalesYAt); var uw = Model.Chart.AxisX[ScalesXAt].EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.X, Model.Chart, ScalesXAt) / 2 : 0; location.X -= uw; if (splitter.IsNew) { splitter.Right.Point = new Point(location.X, Model.Chart.DrawMargin.Height); } Figure.Segments.Remove(splitter.Right); if (noAnim) { splitter.Right.Point = new Point(location.X, areaLimit); } else { splitter.Right.BeginPointAnimation(nameof(LineSegment.Point), new Point(location.X, areaLimit), animSpeed); } Figure.Segments.Insert(atIndex, splitter.Right); splitter.IsNew = false; }
public override void EndSegment(int atIndex, CorePoint location) { var splitter = Splitters[ActiveSplitters - 1]; var animSpeed = Model.Chart.View.AnimationsSpeed; var noAnim = Model.Chart.View.DisableAnimations; if (splitter.IsNew) { splitter.Right.Point = new Point(0, location.Y); } Figure.Segments.Remove(splitter.Right); if (noAnim) { splitter.Right.Point = new Point(0, location.Y); } else { splitter.Right.BeginAnimation(LineSegment.PointProperty, new PointAnimation(new Point(0, location.Y), animSpeed)); } Figure.Segments.Insert(atIndex, splitter.Right); splitter.IsNew = false; }
public void Drag(CorePoint delta) { if (View.Zoom == ZoomingOptions.None) { return; } if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { foreach (var xi in AxisX) { xi.View.SetRange((xi.MinValue ?? xi.BotLimit) + delta.X, (xi.MaxValue ?? xi.TopLimit) + delta.X); } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { foreach (var yi in AxisY) { yi.View.SetRange((yi.MinValue ?? yi.BotLimit) + delta.Y, (yi.MaxValue ?? yi.TopLimit) + delta.Y); } } }
public void Drag(CorePoint delta) { if (PivotZoomingAxis == AxisOrientation.None) { return; } if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { foreach (var xi in AxisX) { xi.View.MaxValue = (xi.MaxValue ?? xi.TopLimit) + delta.X; xi.View.MinValue = (xi.MinValue ?? xi.BotLimit) + delta.X; } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { foreach (var yi in AxisY) { yi.View.MaxValue = (yi.MaxValue ?? yi.TopLimit) + delta.Y; yi.View.MinValue = (yi.MinValue ?? yi.BotLimit) + delta.Y; } } Updater.Run(false, true); }
/// <summary> /// Converts from chart control size to chart values. /// </summary> /// <param name="value">value to scale</param> /// <param name="source">axis orientation to scale value at</param> /// <param name="chart">chart model to scale value at</param> /// <param name="axis">axis index in collection of chart.axis</param> /// <returns></returns> public static double FromPlotArea(double value, AxisOrientation source, ChartCore chart, int axis = 0) { var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientation.Y) { p1.X = chart.AxisY[axis].TopLimit; p1.Y = chart.DrawMargin.Top; p2.X = chart.AxisY[axis].BotLimit; p2.Y = chart.DrawMargin.Top + chart.DrawMargin.Height; } else { p1.X = chart.AxisX[axis].TopLimit; p1.Y = chart.DrawMargin.Width + chart.DrawMargin.Left; p2.X = chart.AxisX[axis].BotLimit; p2.Y = chart.DrawMargin.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); return (value + m * p1.X - p1.Y) / m; }
public void ZoomIn(CorePoint pivot) { if (AxisX == null || AxisY == null) { return; } View.HideTooltip(); pivot = new CorePoint( ChartFunctions.FromPlotArea(pivot.X, AxisOrientation.X, this), ChartFunctions.FromPlotArea(pivot.Y, AxisOrientation.Y, this)); var speed = View.ZoomingSpeed < 0.1 ? 0.1 : (View.ZoomingSpeed > 0.95 ? 0.95 : View.ZoomingSpeed); if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { foreach (var xi in AxisX) { var max = xi.MaxValue ?? xi.TopLimit; var min = xi.MinValue ?? xi.BotLimit; var l = max - min; var rMin = (pivot.X - min) / l; var rMax = 1 - rMin; var target = l * speed; if (target < xi.View.MinRange) { return; } var mint = pivot.X - target * rMin; var maxt = pivot.X + target * rMax; xi.View.SetRange(mint, maxt); } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { foreach (var yi in AxisY) { var max = yi.MaxValue ?? yi.TopLimit; var min = yi.MinValue ?? yi.BotLimit; var l = max - min; var rMin = (pivot.Y - min) / l; var rMax = 1 - rMin; var target = l * speed; if (target < yi.View.MinRange) { return; } var mint = pivot.X - target * rMin; var maxt = pivot.X + target * rMax; yi.View.SetRange(mint, maxt); } } }
private static void Chart_PreviewTouchMove(object sender, TouchEventArgs e) { var chart = sender as Chart; if (chart == null) { return; } var currentTouchDevices = GetCurrentTouchDevices(chart); if (currentTouchDevices == null) { return; } if (currentTouchDevices.Count < zoomTouchCountLimit) { return; } var touchDeviceId = e.TouchDevice.Id; if (currentTouchDevices.ContainsKey(touchDeviceId) == false) { return; } currentTouchDevices[touchDeviceId] = e.GetTouchPoint(chart).Position; var firstPoint = currentTouchDevices.ElementAt(0).Value; var secondPoint = currentTouchDevices.ElementAt(1).Value; var zoomStartingDistance = GetZoomStartingDistance(chart); var newDistance = CalculateDistance(firstPoint, secondPoint); var diffDistance = zoomStartingDistance - newDistance; Debug.WriteLine($"DiffDistance {diffDistance}"); if (Math.Abs(diffDistance) < zoomDistanceTreshold) { return; } SetZoomStartingDistance(chart, newDistance); var corePoint = new CorePoint((firstPoint.X + secondPoint.X) / 2, (firstPoint.Y + secondPoint.Y) / 2); if (diffDistance < 0) { chart.Model.ZoomIn(corePoint); } else { chart.Model.ZoomOut(corePoint); } }
/// <summary> /// Zooms the out. /// </summary> /// <param name="pivot">The pivot.</param> public void ZoomOut(CorePoint pivot) { View.HideTooltip(); var speed = View.ZoomingSpeed < 0.1 ? 0.1 : (View.ZoomingSpeed > 0.95 ? 0.95 : View.ZoomingSpeed); if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { for (var index = 0; index < AxisX.Count; index++) { var xi = AxisX[index]; var px = ChartFunctions.FromPlotArea(pivot.X, AxisOrientation.X, this, index); var max = double.IsNaN(xi.View.MaxValue) ? xi.TopLimit : xi.View.MaxValue; var min = double.IsNaN(xi.View.MinValue) ? xi.BotLimit : xi.View.MinValue; var l = max - min; var rMin = (px - min) / l; var rMax = 1 - rMin; var target = l * (1 / speed); if (target > xi.View.MaxRange) { return; } var mint = px - target * rMin; var maxt = px + target * rMax; xi.View.SetRange(mint, maxt); } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { for (var index = 0; index < AxisY.Count; index++) { var ax = AxisY[index]; var py = ChartFunctions.FromPlotArea(pivot.Y, AxisOrientation.Y, this, index); var max = double.IsNaN(ax.View.MaxValue) ? ax.TopLimit : ax.View.MaxValue; var min = double.IsNaN(ax.View.MinValue) ? ax.BotLimit : ax.View.MinValue; var l = max - min; var rMin = (py - min) / l; var rMax = 1 - rMin; var target = l * (1 / speed); if (target > ax.View.MaxRange) { return; } var mint = py - target * rMin; var maxt = py + target * rMax; ax.View.SetRange(mint, maxt); } } }
private void Debounced(MouseWheelEventArgs e) { var m = _pcmodel.ChartGroupViewModel; var p = e.GetPosition(this); var corePoint = new CorePoint(p.X, p.Y); e.Handled = true; m.OverviewZoom.ZoomProxy?.Invoke(corePoint, e.Delta > 0); }
public void ZoomIn(CorePoint pivot) { if (AxisX == null || AxisY == null) { return; } View.HideTooltop(); pivot = new CorePoint( ChartFunctions.FromPlotArea(pivot.X, AxisOrientation.X, this), ChartFunctions.FromPlotArea(pivot.Y, AxisOrientation.Y, this)); if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { foreach (var xi in AxisX) { var max = xi.MaxValue ?? xi.TopLimit; var min = xi.MinValue ?? xi.BotLimit; var l = max - min; var rMin = (pivot.X - min) / l; var rMax = 1 - rMin; if ((max - rMax * xi.S) - (min + rMin * xi.S) < xi.S * .01) { return; } xi.View.MinValue = min + rMin * xi.S; xi.View.MaxValue = max - rMax * xi.S; } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { foreach (var yi in AxisY) { var max = yi.MaxValue ?? yi.TopLimit; var min = yi.MinValue ?? yi.BotLimit; var l = max - min; var rMin = (pivot.Y - min) / l; var rMax = 1 - rMin; if ((max - rMax * yi.S) - (min + rMin * yi.S) < yi.S * .01) { return; } yi.View.MinValue = min + rMin * yi.S; yi.View.MaxValue = max - rMax * yi.S; } } Updater.Run(); }
private static byte InterpolateColorComponent(byte fromComponent, byte toComponent, double fromOffset, double toOffset, double value) { var p1 = new CorePoint(fromOffset, fromComponent); var p2 = new CorePoint(toOffset, toComponent); var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); return((byte)(m * (value - p1.X) + p1.Y)); }
public void ZoomOut(CorePoint pivot) { View.HideTooltip(); pivot = new CorePoint( ChartFunctions.FromPlotArea(pivot.X, AxisOrientation.X, this), ChartFunctions.FromPlotArea(pivot.Y, AxisOrientation.Y, this)); var speed = View.ZoomingSpeed < 0.1 ? 0.1 : (View.ZoomingSpeed > 0.95 ? 0.95 : View.ZoomingSpeed); if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { foreach (var xi in AxisX) { var max = double.IsNaN(xi.MaxValue) ? xi.TopLimit : xi.MaxValue; var min = double.IsNaN(xi.MinValue) ? xi.BotLimit : xi.MinValue; var l = max - min; var rMin = (pivot.X - min) / l; var rMax = 1 - rMin; var target = l * (1 / speed); if (target > xi.View.MaxRange) { return; } var mint = pivot.X - target * rMin; var maxt = pivot.X + target * rMax; xi.View.SetRange(mint, maxt); } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { foreach (var yi in AxisY) { var max = double.IsNaN(yi.MaxValue) ? yi.TopLimit : yi.MaxValue; var min = double.IsNaN(yi.MinValue) ? yi.BotLimit : yi.MinValue; var l = max - min; var rMin = (pivot.Y - min) / l; var rMax = 1 - rMin; var target = l * (1 / speed); if (target > yi.View.MaxRange) { return; } var mint = pivot.X - target * rMin; var maxt = pivot.X + target * rMax; yi.View.SetRange(mint, maxt); } } }
private void UnanimatedPlace(IChartView chart, AxisTags direction, int axisIndex, Axis axis) { var i = ChartFunctions.ToPlotArea(Model.Value, direction, chart.Model, axisIndex); var uw = new CorePoint( axis.Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisTags.X, chart.Model, axis.Model) / 2 : 0, axis.Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisTags.Y, chart.Model, axis.Model) / 2 : 0); if (direction == AxisTags.Y) { Line.X1 = chart.Model.DrawMargin.Left; Line.X2 = chart.Model.DrawMargin.Left + chart.Model.DrawMargin.Width; Line.Y1 = i; Line.Y2 = i; var topM = axis.IsMerged ? (i + TextBlock.ActualHeight > chart.Model.DrawMargin.Top + chart.Model.DrawMargin.Height ? +TextBlock.ActualHeight : 0) : TextBlock.ActualHeight * .5; var leftM = axis.IsMerged ? TextBlock.ActualWidth + 10 : -2; Canvas.SetTop(TextBlock, i + uw.Y - topM); Canvas.SetLeft(TextBlock, axis.Position == AxisPosition.LeftBottom ? axis.LabelsReference - TextBlock.ActualWidth + leftM : axis.LabelsReference - leftM); } else { Line.X1 = i; Line.X2 = i; Line.Y1 = chart.Model.DrawMargin.Top; Line.Y2 = chart.Model.DrawMargin.Top + chart.Model.DrawMargin.Height; var left = axis.IsMerged ? (i + TextBlock.ActualWidth > chart.Model.DrawMargin.Left + chart.Model.DrawMargin.Width ? TextBlock.ActualWidth + 2 : -2) : TextBlock.ActualWidth * .5; var top = axis.IsMerged ? TextBlock.ActualHeight : 0; Canvas.SetLeft(TextBlock, i + uw.X - left); Canvas.SetTop(TextBlock, axis.Position == AxisPosition.LeftBottom ? axis.LabelsReference - top : axis.LabelsReference); } }
public void ZoomOut(CorePoint pivot) { View.HideTooltop(); if (IsZooming) { return; } RequestedZoomAt = DateTime.Now; var dataPivot = new CorePoint( ChartFunctions.FromDrawMargin(pivot.X, AxisOrientation.X, this), ChartFunctions.FromDrawMargin(pivot.Y, AxisOrientation.Y, this)); if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { foreach (var xi in AxisX) { var max = xi.MaxValue ?? xi.TopLimit; var min = xi.MinValue ?? xi.BotLimit; var l = max - min; var rMin = (dataPivot.X - min) / l; var rMax = 1 - rMin; xi.View.MinValue = min - rMin * xi.S; xi.View.MaxValue = max + rMax * xi.S; } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { foreach (var yi in AxisY) { var max = yi.MaxValue ?? yi.TopLimit; var min = yi.MinValue ?? yi.BotLimit; var l = max - min; var rMin = (dataPivot.Y - min) / l; var rMax = 1 - rMin; yi.View.MinValue = min - rMin * yi.S; yi.View.MaxValue = max + rMax * yi.S; } } Updater.Run(false, true); }
public CoreRectangle PlaceLegend(CoreRectangle drawMargin) { var legendSize = View.LoadLegend(); const int padding = 10; switch (View.LegendLocation) { case LegendLocation.None: View.HideLegend(); break; case LegendLocation.Top: var top = new CorePoint(ChartControlSize.Width * .5 - legendSize.Width * .5, 0); var y = drawMargin.Top; drawMargin.Top = y + top.Y + legendSize.Height + padding; drawMargin.Height -= legendSize.Height - padding; View.ShowLegend(top); break; case LegendLocation.Bottom: var bot = new CorePoint(ChartControlSize.Width * .5 - legendSize.Width * .5, ChartControlSize.Height - legendSize.Height); drawMargin.Height -= legendSize.Height; View.ShowLegend(new CorePoint(bot.X, ChartControlSize.Height - legendSize.Height)); break; case LegendLocation.Left: drawMargin.Left = drawMargin.Left + legendSize.Width; View.ShowLegend(new CorePoint(0, ChartControlSize.Height * .5 - legendSize.Height * .5)); break; case LegendLocation.Right: drawMargin.Width -= legendSize.Width + padding; View.ShowLegend(new CorePoint(ChartControlSize.Width - legendSize.Width, ChartControlSize.Height * .5 - legendSize.Height * .5)); break; default: throw new ArgumentOutOfRangeException(); } return(drawMargin); }
/// <summary> /// Converts a chart values pair to pixels /// </summary> /// <param name="chart">Target chart</param> /// <param name="chartPoint">point in screen</param> /// <param name="axisX">axis x index</param> /// <param name="axisY">axis y index</param> /// <returns></returns> public static Point ConvertToPixels(this Chart chart, Point chartPoint, int axisX = 0, int axisY = 0) { if (chart.Model == null || chart.AxisX.Any(x => x.Model == null)) { return(new Point()); } var uw = new CorePoint( chart.AxisX[axisX].Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.X, chart.Model, axisX) / 2 : 0, chart.AxisY[axisY].Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.Y, chart.Model, axisY) / 2 : 0); return(new Point( ChartFunctions.ToPlotArea(chartPoint.X, AxisOrientation.X, chart.Model, axisX) + uw.X, ChartFunctions.ToPlotArea(chartPoint.Y, AxisOrientation.Y, chart.Model, axisY) + uw.Y)); }
/// <summary> /// Converts a point at screen to chart values scale /// </summary> /// <param name="chart">Target chart</param> /// <param name="screenPoint">point in screen</param> /// <param name="axisX">axis x index</param> /// <param name="axisY">axis y index</param> /// <returns></returns> public static Point ConvertToChartValues(this Chart chart, Point screenPoint, int axisX = 0, int axisY = 0) { if (chart.Model == null || chart.AxisX == null || chart.AxisX.Any(x => x.Model == null)) { return(new Point()); } var uw = new CorePoint( chart.AxisX[axisX].Model.EvaluatesUnitWidth ? ChartFunctionsNew.GetUnitWidth(AxisOrientationNew.X, chart.Model, axisX) / 2 : 0, chart.AxisY[axisY].Model.EvaluatesUnitWidth ? ChartFunctionsNew.GetUnitWidth(AxisOrientationNew.Y, chart.Model, axisY) / 2 : 0); return(new Point( ChartFunctionsNew.FromPlotArea(screenPoint.X - uw.X, AxisOrientationNew.X, chart.Model, axisX), ChartFunctionsNew.FromPlotArea(screenPoint.Y - uw.Y, AxisOrientationNew.Y, chart.Model, axisY))); }
public void ShowLegend(CorePoint at) { if (ChartLegend == null) { return; } if (ChartLegend.Parent == null) { AddToView(ChartLegend); Canvas.SetLeft(ChartLegend, 0d); Canvas.SetTop(ChartLegend, 0d); } ChartLegend.Visibility = Visibility.Visible; Canvas.SetLeft(ChartLegend, at.X); Canvas.SetTop(ChartLegend, at.Y); }
/// <summary> /// Drags the specified delta. /// </summary> /// <param name="delta">The delta.</param> public void Drag(CorePoint delta) { if (View.Pan == PanningOptions.Unset && View.Zoom == ZoomingOptions.None || View.Pan == PanningOptions.None) { return; } var px = View.Pan == PanningOptions.Unset && (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy); px = px || View.Pan == PanningOptions.X || View.Pan == PanningOptions.Xy; if (px) { for (var index = 0; index < AxisX.Count; index++) { var xi = AxisX[index]; var dx = ChartFunctions.FromPlotArea(delta.X, AxisOrientation.X, this, index) - ChartFunctions.FromPlotArea(0, AxisOrientation.X, this, index); xi.View.SetRange((double.IsNaN(xi.View.MinValue) ? xi.BotLimit : xi.View.MinValue) + dx, (double.IsNaN(xi.View.MaxValue) ? xi.TopLimit : xi.View.MaxValue) + dx); } } var py = View.Pan == PanningOptions.Unset && (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy); py = py || View.Pan == PanningOptions.Y || View.Pan == PanningOptions.Xy; if (py) { for (var index = 0; index < AxisY.Count; index++) { var ax = AxisY[index]; var dy = ChartFunctions.FromPlotArea(delta.Y, AxisOrientation.Y, this, index) - ChartFunctions.FromPlotArea(0, AxisOrientation.Y, this, index); ax.View.SetRange((double.IsNaN(ax.View.MinValue) ? ax.BotLimit : ax.View.MinValue) + dy, (double.IsNaN(ax.View.MaxValue) ? ax.TopLimit : ax.View.MaxValue) + dy); } } }
/// <summary> /// Updates this instance. /// </summary> public override void Update() { var bubbleSeries = (IScatterSeriesView)View; var p1 = new CorePoint(); var p2 = new CorePoint(); p1.X = Chart.WLimit.Max; p1.Y = bubbleSeries.MaxPointShapeDiameter; p2.X = Chart.WLimit.Min; p2.Y = bubbleSeries.MinPointShapeDiameter; var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); var uw = new CorePoint( CurrentXAxis.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.X, Chart, View.ScalesXAt) / 2 : 0, CurrentYAxis.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.Y, Chart, View.ScalesYAt) / 2 : 0); foreach (var chartPoint in View.ActualValues.GetPoints(View)) { chartPoint.ChartLocation = ChartFunctions.ToDrawMargin( chartPoint, View.ScalesXAt, View.ScalesYAt, Chart) + uw; chartPoint.SeriesView = View; chartPoint.View = View.GetPointView(chartPoint, View.DataLabels ? View.GetLabelPointFormatter()(chartPoint) : null); var bubbleView = (IScatterPointView)chartPoint.View; bubbleView.Diameter = m * (chartPoint.Weight - p1.X) + p1.Y; chartPoint.View.DrawOrMove(null, chartPoint, 0, Chart); } }
public void ZoomOut(CorePoint pivot) { View.HideTooltop(); var dataPivot = new CorePoint( ChartFunctions.FromPlotArea(pivot.X, AxisOrientation.X, this), ChartFunctions.FromPlotArea(pivot.Y, AxisOrientation.Y, this)); if (View.Zoom == ZoomingOptions.X || View.Zoom == ZoomingOptions.Xy) { foreach (var xi in AxisX) { var max = xi.MaxValue ?? xi.TopLimit; var min = xi.MinValue ?? xi.BotLimit; var l = max - min; var rMin = (dataPivot.X - min) / l; var rMax = 1 - rMin; xi.View.MinValue = min - rMin * xi.S; xi.View.MaxValue = max + rMax * xi.S; } } if (View.Zoom == ZoomingOptions.Y || View.Zoom == ZoomingOptions.Xy) { foreach (var yi in AxisY) { var max = yi.MaxValue ?? yi.TopLimit; var min = yi.MinValue ?? yi.BotLimit; var l = max - min; var rMin = (dataPivot.Y - min) / l; var rMax = 1 - rMin; yi.View.MinValue = min - rMin * yi.S; yi.View.MaxValue = max + rMax * yi.S; } } Updater.Run(); }
private void OnPointerWheelChanged(object sender, PointerRoutedEventArgs e) { if (Zoom == ZoomingOptions.None) { return; } var p = e.GetCurrentPoint(this); var corePoint = new CorePoint(p.Position.X, p.Position.Y); e.Handled = true; if (p.Properties.MouseWheelDelta > 0) { Model.ZoomIn(corePoint); } else { Model.ZoomOut(corePoint); } }
private void MouseWheelOnRoll(object sender, MouseWheelEventArgs e) { if (Zoom == ZoomingOptions.None) { return; } var p = e.GetPosition(this); var corePoint = new CorePoint(p.X, p.Y); e.Handled = true; if (e.Delta > 0) { Model.ZoomIn(corePoint); } else { Model.ZoomOut(corePoint); } }
/// <summary> /// Ends the segment. /// </summary> /// <param name="atIndex">At index.</param> /// <param name="location">The location.</param> public override void EndSegment(int atIndex, CorePoint location) { var splitter = Splitters[ActiveSplitters - 1]; var animSpeed = Model.Chart.View.AnimationsSpeed; var noAnim = Model.Chart.View.DisableAnimations; if (splitter.IsNew) { splitter.Right.Point = new Point(0, location.Y); } var areaLimit = 0d; if (!double.IsNaN(AreaLimit)) { areaLimit = ChartFunctions.ToDrawMargin(AreaLimit, AxisOrientation.X, Model.Chart, ScalesXAt); } var uw = Model.Chart.AxisY[ScalesYAt].EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.Y, Model.Chart, ScalesYAt) / 2 : 0; location.Y += uw; Figure.Segments.Remove(splitter.Right); if (noAnim) { splitter.Right.Point = new Point(areaLimit, location.Y); } else { splitter.Right.BeginAnimation(LineSegment.PointProperty, new PointAnimation(new Point(areaLimit, location.Y), animSpeed)); } Figure.Segments.Insert(atIndex, splitter.Right); splitter.IsNew = false; }
private Tuple<VertexPositionColorNormal[], int[]> getCylinderCap(CorePoint point, int steps, bool reverse, bool backwards) { VertexPositionColorNormal[] vertices = new VertexPositionColorNormal[steps * steps]; int[] indices = new int[2 * steps + 2]; for (int i = 0; i < steps; i++) { for (int j = 0; j < steps; j++) { float t = (float) j/(steps - 1); Vector3 newp = point.pos - point.radius* point.orient*(backwards ? 1 : -1)*t; float newr = point.radius*(float)Math.Sqrt(1-(1-t)*(1-t)); Vector3 newn = newr*point.up + newp - point.pos; newn.Normalize(); Matrix rotationMatrix = Matrix.CreateFromAxisAngle(point.orient, (float)((reverse ? -1 : 1) * j * Math.PI * 2 / steps)); vertices[i * steps + j].Position = Vector3.Transform(point.up, rotationMatrix) * newr + newp; vertices[i * steps + j].Normal = Vector3.TransformNormal(newn, rotationMatrix); vertices[i * steps + j].Color = point.color; } } for (int j = 0; j < steps; j++) { indices[2 * j] = j; indices[2 * j + 1] = steps + j; } indices[2 * steps] = 0; indices[2 * steps + 1] = steps; return new Tuple<VertexPositionColorNormal[], int[]>(vertices, indices); }
public void AddOrMove() { if (UIElement.Parent == null) { Chart.AddToDrawMargin(UIElement); Panel.SetZIndex(UIElement, 1000); } var coordinate = new CorePoint(ChartFunctions.ToDrawMargin(X, AxisTags.X, Chart.Model, AxisX), ChartFunctions.ToDrawMargin(Y, AxisTags.Y, Chart.Model, AxisY)); var wpfChart = (CartesianChart) Chart; var uw = new CorePoint( wpfChart.AxisX[AxisX].Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisTags.X, Chart.Model, AxisX)/2 : 0, wpfChart.AxisY[AxisY].Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisTags.Y, Chart.Model, AxisY)/2 : 0); coordinate += uw; UIElement.UpdateLayout(); switch (VerticalAlignment) { case VerticalAlignment.Top: coordinate = new CorePoint(coordinate.X, coordinate.Y - UIElement.ActualHeight); break; case VerticalAlignment.Center: coordinate = new CorePoint(coordinate.X, coordinate.Y - UIElement.ActualHeight / 2); break; case VerticalAlignment.Bottom: coordinate = new CorePoint(coordinate.X, coordinate.Y); break; case VerticalAlignment.Stretch: break; default: throw new ArgumentOutOfRangeException(); } switch (HorizontalAlignment) { case HorizontalAlignment.Left: coordinate = new CorePoint(coordinate.X - UIElement.ActualWidth, coordinate.Y); break; case HorizontalAlignment.Center: coordinate = new CorePoint(coordinate.X - UIElement.ActualWidth / 2, coordinate.Y); break; case HorizontalAlignment.Right: coordinate = new CorePoint(coordinate.X, coordinate.Y); break; case HorizontalAlignment.Stretch: break; default: throw new ArgumentOutOfRangeException(); } if (Chart.DisableAnimations) { Canvas.SetLeft(UIElement, coordinate.X); Canvas.SetTop(UIElement, coordinate.Y); } else { if (double.IsNaN(Canvas.GetLeft(UIElement))) { Canvas.SetLeft(UIElement, coordinate.X); Canvas.SetTop(UIElement, coordinate.Y); } UIElement.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(coordinate.X, wpfChart.AnimationsSpeed)); UIElement.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(coordinate.Y, wpfChart.AnimationsSpeed)); } }
public override void Update() { var heatSeries = (IHeatSeriesView)View; var uw = new CorePoint( 0 * ChartFunctions.GetUnitWidth(AxisOrientation.X, Chart, View.ScalesXAt) / 2, -ChartFunctions.GetUnitWidth(AxisOrientation.Y, Chart, View.ScalesYAt)); // ReSharper disable once CompareOfFloatsByEqualityOperator var wd = CurrentXAxis.TopLimit - CurrentXAxis.BotLimit == 0 ? double.MaxValue : CurrentXAxis.TopLimit - CurrentXAxis.BotLimit; // ReSharper disable once CompareOfFloatsByEqualityOperator var hd = CurrentYAxis.TopLimit - CurrentYAxis.BotLimit == 0 ? double.MaxValue : CurrentYAxis.TopLimit - CurrentYAxis.BotLimit; var w = Chart.DrawMargin.Width / wd; var h = Chart.DrawMargin.Height / hd; //lets force the gradients to always have an 'interpol-able' model if (!heatSeries.Stops.Any()) { throw new LiveChartsException("There is no a valid gradient to create a heat series."); } var correctedGradients = heatSeries.Stops.Select(x => new CoreGradientStop { Color = x.Color, Offset = x.Offset < 0 ? 0 : (x.Offset > 1 ? 1 : x.Offset) }).ToList(); var min = correctedGradients[0]; min.Offset = 0; correctedGradients.Insert(0, min); var max = correctedGradients[correctedGradients.Count - 1]; max.Offset = 1; correctedGradients.Add(max); foreach (var chartPoint in View.ActualValues.GetPoints(View)) { chartPoint.ChartLocation = ChartFunctions.ToDrawMargin( chartPoint, View.ScalesXAt, View.ScalesYAt, Chart) + uw; chartPoint.SeriesView = View; chartPoint.View = View.GetPointView(chartPoint.View, chartPoint, View.DataLabels ? View.GetLabelPointFormatter()(chartPoint) : null); var heatView = (IHeatPointView)chartPoint.View; heatView.ColorComponents = ColorInterpolation(correctedGradients, chartPoint.Weight / Chart.Value3CoreLimit.Max); heatView.Width = w; heatView.Height = h; chartPoint.View.DrawOrMove(null, chartPoint, 0, Chart); } }
public void ShowLegend(CorePoint at) { if (ChartLegend == null) return; if (ChartLegend.Parent == null) { AddToView(ChartLegend); Canvas.SetLeft(ChartLegend, 0d); Canvas.SetTop(ChartLegend, 0d); } ChartLegend.Visibility = Visibility.Visible; Canvas.SetLeft(ChartLegend, at.X); Canvas.SetTop(ChartLegend, at.Y); }
/// <summary> /// Starts the segment. /// </summary> /// <param name="atIndex">At index.</param> /// <param name="location">The location.</param> public override void StartSegment(int atIndex, CorePoint location) { if (Splitters.Count <= ActiveSplitters) { Splitters.Add(new LineSegmentSplitter { IsNew = true }); } var splitter = Splitters[ActiveSplitters]; splitter.SplitterCollectorIndex = SplittersCollector; ActiveSplitters++; var animSpeed = Model.Chart.View.AnimationsSpeed; var noAnim = Model.Chart.View.DisableAnimations; var areaLimit = ChartFunctions.ToDrawMargin(double.IsNaN(AreaLimit) ? Model.Chart.AxisX[ScalesXAt].FirstSeparator : AreaLimit, AxisOrientation.X, Model.Chart, ScalesXAt); if (Values != null && atIndex == 0) { if (Model.Chart.View.DisableAnimations || IsNew) { Figure.StartPoint = new Point(areaLimit, location.Y); } else { Figure.BeginAnimation(PathFigure.StartPointProperty, new PointAnimation(new Point(areaLimit, location.Y), animSpeed)); } IsNew = false; } if (atIndex != 0) { Figure.Segments.Remove(splitter.Bottom); if (splitter.IsNew) { splitter.Bottom.Point = new Point(Model.Chart.DrawMargin.Width, location.Y); splitter.Left.Point = new Point(Model.Chart.DrawMargin.Width, location.Y); } if (noAnim) { splitter.Bottom.Point = new Point(Model.Chart.DrawMargin.Width, location.Y); } else { splitter.Bottom.BeginAnimation(LineSegment.PointProperty, new PointAnimation(new Point(Model.Chart.DrawMargin.Width, location.Y), animSpeed)); } Figure.Segments.Insert(atIndex, splitter.Bottom); Figure.Segments.Remove(splitter.Left); if (noAnim) { splitter.Left.Point = location.AsPoint(); } else { splitter.Left.BeginAnimation(LineSegment.PointProperty, new PointAnimation(location.AsPoint(), animSpeed)); } Figure.Segments.Insert(atIndex + 1, splitter.Left); return; } if (splitter.IsNew) { splitter.Bottom.Point = new Point(location.X, Model.Chart.DrawMargin.Height); splitter.Left.Point = new Point(location.X, Model.Chart.DrawMargin.Height); } Figure.Segments.Remove(splitter.Left); if (Model.Chart.View.DisableAnimations) { splitter.Left.Point = location.AsPoint(); } else { splitter.Left.BeginAnimation(LineSegment.PointProperty, new PointAnimation(location.AsPoint(), animSpeed)); } Figure.Segments.Insert(atIndex, splitter.Left); }
/// <summary> /// Adds the or move. /// </summary> /// <param name="chart">The chart.</param> /// <exception cref="System.ArgumentOutOfRangeException"> /// </exception> public void AddOrMove(ChartCore chart) { if (chart == null || UIElement == null) { return; } if (!chart.AreComponentsLoaded) { return; } if (UIElement.Parent == null) { chart.View.AddToDrawMargin(UIElement); Panel.SetZIndex(UIElement, 1000); } var coordinate = new CorePoint(ChartFunctions.ToDrawMargin(X, AxisOrientation.X, chart, AxisX), ChartFunctions.ToDrawMargin(Y, AxisOrientation.Y, chart.View.Model, AxisY)); var wpfChart = (CartesianChart)chart.View; var uw = new CorePoint( wpfChart.AxisX[AxisX].Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.X, chart, AxisX) / 2 : 0, wpfChart.AxisY[AxisY].Model.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.Y, chart, AxisY) / 2 : 0); coordinate += uw; UIElement.UpdateLayout(); switch (VerticalAlignment) { case VerticalAlignment.Top: coordinate = new CorePoint(coordinate.X, coordinate.Y - UIElement.ActualHeight); break; case VerticalAlignment.Center: coordinate = new CorePoint(coordinate.X, coordinate.Y - UIElement.ActualHeight / 2); break; case VerticalAlignment.Bottom: coordinate = new CorePoint(coordinate.X, coordinate.Y); break; case VerticalAlignment.Stretch: break; default: throw new ArgumentOutOfRangeException(); } switch (HorizontalAlignment) { case HorizontalAlignment.Left: coordinate = new CorePoint(coordinate.X - UIElement.ActualWidth, coordinate.Y); break; case HorizontalAlignment.Center: coordinate = new CorePoint(coordinate.X - UIElement.ActualWidth / 2, coordinate.Y); break; case HorizontalAlignment.Right: coordinate = new CorePoint(coordinate.X, coordinate.Y); break; case HorizontalAlignment.Stretch: break; default: throw new ArgumentOutOfRangeException(); } if (chart.View.DisableAnimations) { Canvas.SetLeft(UIElement, coordinate.X); Canvas.SetTop(UIElement, coordinate.Y); } else { if (double.IsNaN(Canvas.GetLeft(UIElement))) { Canvas.SetLeft(UIElement, coordinate.X); Canvas.SetTop(UIElement, coordinate.Y); } UIElement.BeginAnimation(Canvas.LeftProperty, new DoubleAnimation(coordinate.X, wpfChart.AnimationsSpeed)); UIElement.BeginAnimation(Canvas.TopProperty, new DoubleAnimation(coordinate.Y, wpfChart.AnimationsSpeed)); } _owner = chart; }
public override void Update() { var points = View.ActualValues.GetPoints(View).ToArray(); var segmentPosition = 0; var lineView = (ILineSeriesView)View; var smoothness = lineView.LineSmoothness; smoothness = smoothness > 1 ? 1 : (smoothness < 0 ? 0 : smoothness); foreach (var segment in points.SplitEachNaN()) { var p0 = segment.Count > 0 ? ChartFunctions.ToDrawMargin(segment[0], View.ScalesXAt, View.ScalesYAt, Chart) : new CorePoint(0, 0); var p1 = segment.Count > 0 ? ChartFunctions.ToDrawMargin(segment[0], View.ScalesXAt, View.ScalesYAt, Chart) : p0; var p2 = segment.Count > 1 ? ChartFunctions.ToDrawMargin(segment[1], View.ScalesXAt, View.ScalesYAt, Chart) : p1; var p3 = segment.Count > 2 ? ChartFunctions.ToDrawMargin(segment[2], View.ScalesXAt, View.ScalesYAt, Chart) : p2; var uw = new CorePoint( CurrentXAxis.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.X, Chart, View.ScalesXAt) / 2 : 0, CurrentYAxis.EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(AxisOrientation.Y, Chart, View.ScalesYAt) / 2 : 0); if (SeriesOrientation == SeriesOrientation.Horizontal) { p0 += uw; p1 += uw; p2 += uw; p3 += uw; } else { p0 = new CorePoint(p0.X + uw.X, p0.Y - uw.Y); p1 = new CorePoint(p1.X + uw.X, p1.Y - uw.Y); p2 = new CorePoint(p2.X + uw.X, p2.Y - uw.Y); p3 = new CorePoint(p3.X + uw.X, p3.Y - uw.Y); } lineView.StartSegment(segmentPosition, p1); segmentPosition += segmentPosition == 0 ? 1 : 2; ChartPoint previousDrawn = null; var isOpen = false; for (var index = 0; index < segment.Count; index++) { var chartPoint = segment[index]; chartPoint.ChartLocation = p1; chartPoint.SeriesView = View; var xc1 = (p0.X + p1.X) / 2.0; var yc1 = (p0.Y + p1.Y) / 2.0; var xc2 = (p1.X + p2.X) / 2.0; var yc2 = (p1.Y + p2.Y) / 2.0; var xc3 = (p2.X + p3.X) / 2.0; var yc3 = (p2.Y + p3.Y) / 2.0; var len1 = Math.Sqrt((p1.X - p0.X) * (p1.X - p0.X) + (p1.Y - p0.Y) * (p1.Y - p0.Y)); var len2 = Math.Sqrt((p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y)); var len3 = Math.Sqrt((p3.X - p2.X) * (p3.X - p2.X) + (p3.Y - p2.Y) * (p3.Y - p2.Y)); var k1 = len1 / (len1 + len2); var k2 = len2 / (len2 + len3); if (double.IsNaN(k1)) { k1 = 0d; } if (double.IsNaN(k2)) { k2 = 0d; } var xm1 = xc1 + (xc2 - xc1) * k1; var ym1 = yc1 + (yc2 - yc1) * k1; var xm2 = xc2 + (xc3 - xc2) * k2; var ym2 = yc2 + (yc3 - yc2) * k2; var c1X = xm1 + (xc2 - xm1) * smoothness + p1.X - xm1; var c1Y = ym1 + (yc2 - ym1) * smoothness + p1.Y - ym1; var c2X = xm2 + (xc2 - xm2) * smoothness + p2.X - xm2; var c2Y = ym2 + (yc2 - ym2) * smoothness + p2.Y - ym2; chartPoint.View = View.GetPointView(chartPoint, View.DataLabels ? View.GetLabelPointFormatter()(chartPoint) : null); var bezierView = chartPoint.View as IBezierPointView; if (bezierView == null) { continue; } bezierView.Data = index == segment.Count - 1 ? new BezierData(new CorePoint(p1.X, p1.Y)) : new BezierData { Point1 = index == 0 ? new CorePoint(p1.X, p1.Y) : new CorePoint(c1X, c1Y), Point2 = new CorePoint(c2X, c2Y), Point3 = new CorePoint(p2.X, p2.Y) }; chartPoint.View.DrawOrMove(previousDrawn, chartPoint, segmentPosition, Chart); segmentPosition++; previousDrawn = chartPoint.View.IsNew ? previousDrawn : chartPoint; p0 = new CorePoint(p1); p1 = new CorePoint(p2); p2 = new CorePoint(p3); p3 = segment.Count > index + 3 ? ChartFunctions.ToDrawMargin(segment[index + 3], View.ScalesXAt, View.ScalesYAt, Chart) : p2; if (SeriesOrientation == SeriesOrientation.Horizontal) { p3 += uw; } else { p3 = new CorePoint(p3.X + uw.X, p3.Y - uw.Y); } isOpen = true; } if (isOpen) { lineView.EndSegment(segmentPosition, p1); } segmentPosition++; } }
internal double FromPreviousState(double value, AxisOrientation source, ChartCore chart) { if (LastAxisMax == null) return 0; var p1 = new CorePoint(); var p2 = new CorePoint(); if (source == AxisOrientation.Y) { p1.X = LastAxisMax ?? 0; p1.Y = LastPlotArea.Top; p2.X = LastAxisMin ?? 0; p2.Y = LastPlotArea.Top + LastPlotArea.Height; } else { p1.X = LastAxisMax ?? 0; p1.Y = LastPlotArea.Width + LastPlotArea.Left; p2.X = LastAxisMin ?? 0; p2.Y = LastPlotArea.Left; } var deltaX = p2.X - p1.X; // ReSharper disable once CompareOfFloatsByEqualityOperator var m = (p2.Y - p1.Y) / (deltaX == 0 ? double.MinValue : deltaX); var d = m * (value - p1.X) + p1.Y; return d; }
/// <summary> /// Initializes a new instance of CorePoint /// </summary> /// <param name="point">source pont</param> public CorePoint(CorePoint point) : this() { X = point.X; Y = point.Y; }
/// <summary> /// Initializes a new instance of the <see cref="BezierData"/> class. /// </summary> /// <param name="point">The point.</param> public BezierData(CorePoint point) { Point1 = point; Point2 = point; Point3 = point; }
private List<FingerTrace> GetTraces(CurrentNoteRendering r) { List<FingerTrace> traces = new List<FingerTrace>(); foreach (var trace in r.missed) { FingerTrace ft = new FingerTrace(); foreach (var p in trace.points) { CorePoint cp = new CorePoint(new Vector3(p.x, fallingSpeed * chart.bpm * (float)(p.time), 0), Vector3.UnitY, Vector3.UnitZ, p.force, new Color(0.5f, 0.5f, 0.5f, 0.7f)); ft.points.Add(cp); } traces.Add(ft); } foreach (var trace in r.inProgress) { FingerTrace ft = new FingerTrace(); foreach (var p in trace.points) { CorePoint cp = new CorePoint(new Vector3(p.x, fallingSpeed * chart.bpm * (float)(p.time), 0), Vector3.UnitY, Vector3.UnitZ, p.force, Color.Yellow); ft.points.Add(cp); } traces.Add(ft); } foreach (var trace in r.future) { FingerTrace ft = new FingerTrace(); foreach (var p in trace.points) { CorePoint cp = new CorePoint(new Vector3(p.x, fallingSpeed * chart.bpm * (float)(p.time), 0), Vector3.UnitY, Vector3.UnitZ, p.force, Color.LightBlue); ft.points.Add(cp); } traces.Add(ft); } return traces; }
private Tuple<VertexPositionColorNormal[], int[]> getCylinder(CorePoint[] points, int steps, bool reverse) { VertexPositionColorNormal[] vertices = new VertexPositionColorNormal[points.Length * steps]; int[] indices = new int[2*steps+2]; for (int i = 0; i < points.Length; i++) { CorePoint p = points[i]; for (int j = 0; j < steps; j++) { Matrix fromAxisAngle = Matrix.CreateFromAxisAngle(p.orient, (float) ((reverse?-1:1)*j * Math.PI * 2 / steps)); vertices[i*steps + j].Position = Vector3.Transform(p.up, fromAxisAngle)*p.radius + p.pos; vertices[i*steps + j].Normal = Vector3.TransformNormal(p.up, fromAxisAngle); vertices[i*steps + j].Color = p.color; } } for (int j = 0; j < steps; j++) { indices[2*j] = j; indices[2 * j + 1] = steps + j; } indices[2 * steps] = 0; indices[2 * steps + 1] = steps; return new Tuple<VertexPositionColorNormal[], int[]>(vertices, indices); }