예제 #1
0
        internal double FromPreviousAxisState(double value, AxisTags direction, Chart chart)
        {
            //y = m * (x - x1) + y1

            if (LastAxisMax == null)
            {
                return(0);
            }

            var p1 = new Point();
            var p2 = new Point();

            if (direction == AxisTags.Y)
            {
                p1.X = LastAxisMax ?? 0;
                p1.Y = LastPlotArea.Y;

                p2.X = LastAxisMin ?? 0;
                p2.Y = LastPlotArea.Y + LastPlotArea.Height;
            }
            else
            {
                p1.X = LastAxisMax ?? 0;
                p1.Y = LastPlotArea.Width + LastPlotArea.X;

                p2.X = LastAxisMin ?? 0;
                p2.Y = LastPlotArea.X;
            }

            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);
        }
예제 #2
0
        public double FromPreviousAxisState(double value, AxisTags source, ChartCore chart)
        {
            if (LastAxisMax == null)
            {
                return(0);
            }

            var p1 = new CorePoint();
            var p2 = new CorePoint();

            if (source == AxisTags.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);
        }
예제 #3
0
        public static double FromDrawMargin(double value, AxisTags axis, Chart chart)
        {
            var o = axis == AxisTags.X ? chart.PlotArea.X : chart.PlotArea.Y;
            var of = axis == AxisTags.X ? chart.XOffset : chart.YOffset;

            return FromPlotArea(value, axis, chart) - o + of;
        }
예제 #4
0
        public void Place(Chart chart, AxisTags direction, int axisIndex, Axis axis)
        {
            _anSpeed = axis.AnimationsSpeed ?? chart.AnimationsSpeed;

            switch (State)
            {
            case SeparationState.Remove:
                MoveFromCurrentAx(chart, direction, axisIndex, axis);
                Remove(chart, axis);
                break;

            case SeparationState.Keep:
                UnanimatedPlace(chart, direction, axisIndex, axis);
                MoveFromPreviousAx(chart, direction, axisIndex, axis);
                if (IsNew)
                {
                    FadeIn(chart, axis);
                }
                break;

            case SeparationState.InitialAdd:
                UnanimatedPlace(chart, direction, axisIndex, axis);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #5
0
        internal CoreSize PrepareChart(AxisTags source, ChartCore chart)
        {
            if (!(Math.Abs(MaxLimit - MinLimit) > S * .01) || !ShowLabels)
            {
                return(new CoreSize());
            }

            CalculateSeparator(chart, source);

            var f = GetFormatter();

            var biggest   = new CoreSize(0, 0);
            var tolerance = S / 10;

            for (var i = MinLimit; i <= MaxLimit - (EvaluatesUnitWidth ? 1 : 0); i += S)
            {
                SeparatorElementCore asc;

                var key = Math.Round(i / tolerance) * tolerance;
                if (!Cache.TryGetValue(key, out asc))
                {
                    asc = new SeparatorElementCore {
                        IsNew = true
                    };
                    Cache[key] = asc;
                }
                else
                {
                    asc.IsNew = false;
                }

                View.RenderSeparator(asc, Chart);

                asc.Key      = key;
                asc.Value    = i;
                asc.IsActive = true;

                var labelsSize = asc.View.UpdateLabel(f(i), this);

                biggest.Width = labelsSize.Width > biggest.Width
                    ? labelsSize.Width
                    : biggest.Width;
                biggest.Height = labelsSize.Height > biggest.Height
                    ? labelsSize.Height
                    : biggest.Height;

                if (LastAxisMax == null)
                {
                    asc.State = SeparationState.InitialAdd;
                    continue;
                }

                asc.State = SeparationState.Keep;
            }

#if DEBUG
            Debug.WriteLine("Axis.Separations: " + Cache.Count);
#endif
            return(biggest);
        }
예제 #6
0
        public static double FromDrawMargin(double value, AxisTags axis, Chart chart)
        {
            var o  = axis == AxisTags.X ? chart.PlotArea.X : chart.PlotArea.Y;
            var of = axis == AxisTags.X ? chart.XOffset : chart.YOffset;

            return(FromPlotArea(value, axis, chart) - o + of);
        }
예제 #7
0
        public void Move(ChartCore chart, AxisCore axis, AxisTags direction, int axisIndex, double toLabel, double toLine, double tab)
        {
            if (direction == AxisTags.Y)
            {
                Line.BeginAnimation(Line.X1Property,
                                    new DoubleAnimation(chart.DrawMargin.Left, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.X2Property,
                                    new DoubleAnimation(chart.DrawMargin.Left + chart.DrawMargin.Width, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y1Property,
                                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y2Property,
                                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));

                TextBlock.BeginAnimation(Canvas.TopProperty,
                                         new DoubleAnimation(toLabel, chart.View.AnimationsSpeed));
                TextBlock.BeginAnimation(Canvas.LeftProperty,
                                         new DoubleAnimation(tab, chart.View.AnimationsSpeed));
            }
            else
            {
                Line.BeginAnimation(Line.X1Property,
                                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.X2Property,
                                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y1Property,
                                    new DoubleAnimation(chart.DrawMargin.Top, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y2Property,
                                    new DoubleAnimation(chart.DrawMargin.Top + chart.DrawMargin.Height, chart.View.AnimationsSpeed));

                TextBlock.BeginAnimation(Canvas.LeftProperty,
                                         new DoubleAnimation(toLabel, chart.View.AnimationsSpeed));
                TextBlock.BeginAnimation(Canvas.TopProperty,
                                         new DoubleAnimation(tab, chart.View.AnimationsSpeed));
            }
        }
예제 #8
0
        public AxisSectionCore AsCoreElement(AxisCore axis, AxisTags source)
        {
            var model = new AxisSectionCore(this, axis.Chart);

            model.View.Model = model;
            return(model);
        }
예제 #9
0
        public static double ToPlotArea(double value, AxisTags source, ChartCore chart, AxisCore axis)
        {
            var p1 = new CorePoint();
            var p2 = new CorePoint();

            if (source == AxisTags.Y)
            {
                p1.X = axis.MaxLimit;
                p1.Y = chart.DrawMargin.Top;

                p2.X = axis.MinLimit;
                p2.Y = chart.DrawMargin.Top + chart.DrawMargin.Height;
            }
            else
            {
                p1.X = axis.MaxLimit;
                p1.Y = chart.DrawMargin.Width + chart.DrawMargin.Left;

                p2.X = axis.MinLimit;
                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);
        }
예제 #10
0
        public static double ToDrawMargin(double value, AxisTags source, ChartCore chart, AxisCore axis)
        {
            var o = source == AxisTags.X
                ? chart.DrawMargin.Left
                : chart.DrawMargin.Top;

            return(ToPlotArea(value, source, chart, axis) - o);
        }
예제 #11
0
        public static double FromDrawMargin(double value, AxisTags source, Chart chart, int axis = 0)
        {
            //var o = axis == AxisTags.X
            //    ? Canvas.GetLeft(chart.DrawMargin)
            //    : Canvas.GetTop(chart.DrawMargin);
            //var of = axis == AxisTags.X ? chart.XOffset : chart.YOffset;

            return(FromPlotArea(value, source, chart, axis));//FromPlotArea(value, axis, chart) - o + of;
        }
예제 #12
0
        public static double FromDrawMargin(double value, AxisTags axis, Chart chart)
        {
            var o = axis == AxisTags.X
                ? Canvas.GetLeft(chart.DrawMargin)
                : Canvas.GetTop(chart.DrawMargin);
            var of = axis == AxisTags.X ? chart.XOffset : chart.YOffset;

            return(FromPlotArea(value, axis, chart) - o + of);
        }
예제 #13
0
        public static double FromDrawMargin(double value, AxisTags source, ChartCore chart, int axis = 0)
        {
            var o = source == AxisTags.X
                ? chart.DrawMargin.Left
                : chart.DrawMargin.Top;

            //var of = axis == AxisTags.X ? chart.XOffset : chart.YOffset;

            return(FromPlotArea(value, source, chart, axis)); //- o; //FromPlotArea(value, axis, chart) - o + of;
        }
예제 #14
0
        /// <summary>
        /// Axis Y: is Horizontal axis, Axis X: Vertical, confusing but this is how it is!
        /// </summary>
        /// <param name="range"></param>
        /// <param name="axis"></param>
        /// <returns></returns>
        protected double CalculateSeparator(double range, AxisTags axis)
        {
            //based on:
            //http://stackoverflow.com/questions/361681/algorithm-for-nice-grid-line-intervals-on-a-graph

            var m = axis == AxisTags.Y ? Min.Y : Min.X;

            if (Math.Abs(range) < m * .01)
            {
                range = m;
            }

            var ft = axis == AxisTags.Y
                                ? new FormattedText(
                "A label",
                CultureInfo.CurrentUICulture,
                FlowDirection.LeftToRight,
                new Typeface(PrimaryAxis.FontFamily, PrimaryAxis.FontStyle, PrimaryAxis.FontWeight,
                             PrimaryAxis.FontStretch), PrimaryAxis.FontSize, Brushes.Black)
                                : new FormattedText(
                "A label",
                CultureInfo.CurrentUICulture,
                FlowDirection.LeftToRight,
                new Typeface(SecondaryAxis.FontFamily, SecondaryAxis.FontStyle, SecondaryAxis.FontWeight,
                             SecondaryAxis.FontStretch), SecondaryAxis.FontSize, Brushes.Black);

            var separations = axis == AxisTags.Y
                                ? Math.Round(PlotArea.Height / ((ft.Height) * PrimaryAxis.CleanFactor), 0)
                                : Math.Round(PlotArea.Width / ((ft.Width) * SecondaryAxis.CleanFactor), 0);

            separations = separations < 2 ? 2 : separations;

            var    minimum   = range / separations;
            var    magnitude = Math.Pow(10, Math.Floor(Math.Log(minimum) / Math.Log(10)));
            var    residual  = minimum / magnitude;
            double tick;

            if (residual > 5)
            {
                tick = 10 * magnitude;
            }
            else if (residual > 2)
            {
                tick = 5 * magnitude;
            }
            else if (residual > 1)
            {
                tick = 2 * magnitude;
            }
            else
            {
                tick = magnitude;
            }
            return(tick);
        }
예제 #15
0
        internal void CalculateSeparator(Chart chart, AxisTags source)
        {
            if (Separator.Step != null)
            {
                S = Separator.Step ?? 1;
                return;
            }

            var range = MaxLimit - MinLimit;

            range = range <= 0 ? 1 : range;

            var ft = new FormattedText(
                "A label",
                CultureInfo.CurrentCulture,
                FlowDirection.LeftToRight,
                new Typeface(FontFamily, FontStyle, FontWeight,
                             FontStretch), FontSize, Brushes.Black);

            var separations = source == AxisTags.Y
                ? Math.Round(chart.DrawMargin.Height / ((ft.Height) * CleanFactor), 0)
                : Math.Round(chart.DrawMargin.Width / ((ft.Width) * CleanFactor), 0);

            separations = separations < 2 ? 2 : separations;

            var    minimum   = range / separations;
            var    magnitude = Math.Pow(10, Math.Floor(Math.Log(minimum) / Math.Log(10)));
            var    residual  = minimum / magnitude;
            double tick;

            if (residual > 5)
            {
                tick = 10 * magnitude;
            }
            else if (residual > 2)
            {
                tick = 5 * magnitude;
            }
            else if (residual > 1)
            {
                tick = 2 * magnitude;
            }
            else
            {
                tick = magnitude;
            }

            S = tick;

            if (Labels != null)
            {
                S = S < 1 ? 1 : S;
            }
        }
예제 #16
0
 public static double FromPlotArea(double value, AxisTags axis, Chart chart)
 {
     var p1 = axis == AxisTags.X
         ? new Point(chart.Max.X, chart.PlotArea.Width + chart.PlotArea.X)
         : new Point(chart.Max.Y, chart.PlotArea.Y);
     var p2 = axis == AxisTags.X
         ? new Point(chart.Min.X, chart.PlotArea.X)
         : new Point(chart.Min.Y, chart.PlotArea.Y + chart.PlotArea.Height);
     var m = (p2.Y - p1.Y) / (p2.X - p1.X);
     return (value + m*p1.X - p1.Y)/m;
 }
예제 #17
0
 /// <summary>
 /// Scales a graph value to screen according to an axis. 
 /// </summary>
 /// <param name="value"></param>
 /// <param name="axis"></param>
 /// <param name="chart"></param>
 /// <returns></returns>
 public static double ToPlotArea(double value, AxisTags axis, Chart chart)
 {
     //y = m (x - x1) + y1
     var p1 = axis == AxisTags.X
         ? new Point(chart.Max.X, chart.PlotArea.Width + chart.PlotArea.X)
         : new Point(chart.Max.Y, chart.PlotArea.Y);
     var p2 = axis == AxisTags.X
         ? new Point(chart.Min.X, chart.PlotArea.X)
         : new Point(chart.Min.Y, chart.PlotArea.Y + chart.PlotArea.Height);
     var m = (p2.Y - p1.Y) / (p2.X - p1.X);
     return m * (value - p1.X) + p1.Y;
 }
예제 #18
0
        public static double FromPlotArea(double value, AxisTags axis, Chart chart)
        {
            var p1 = axis == AxisTags.X
                ? new Point(chart.Max.X, chart.PlotArea.Width + chart.PlotArea.X)
                : new Point(chart.Max.Y, chart.PlotArea.Y);
            var p2 = axis == AxisTags.X
                ? new Point(chart.Min.X, chart.PlotArea.X)
                : new Point(chart.Min.Y, chart.PlotArea.Y + chart.PlotArea.Height);
            var m = (p2.Y - p1.Y) / (p2.X - p1.X);

            return((value + m * p1.X - p1.Y) / m);
        }
예제 #19
0
        public static double ToDrawMargin(double value, AxisTags source, Chart chart, int axis = 0)
        {
            var o = source == AxisTags.X
                ? Canvas.GetLeft(chart.DrawMargin)
                : Canvas.GetTop(chart.DrawMargin);

            var of = source == AxisTags.X
                ? chart.XOffset
                : chart.YOffset;

            return(ToPlotArea(value, source, chart, axis) - o + of);
        }
예제 #20
0
        private void MoveFromPreviousAx(Chart chart, AxisTags direction, int axisIndex, Axis axis)
        {
            if (axis.DisableAnimations || chart.DisableAnimations)
            {
                return;
            }

            var i = chart.ToPlotArea(Value, direction, axisIndex);

            if (direction == AxisTags.Y)
            {
                var y = IsNew ? axis.FromPreviousAxisState(Value, direction, chart) : Line.Y1;

                Line.BeginAnimation(Line.X1Property,
                                    new DoubleAnimation(Line.X1, Canvas.GetLeft(chart.DrawMargin), _anSpeed));
                Line.BeginAnimation(Line.X2Property,
                                    new DoubleAnimation(Line.X2, Canvas.GetLeft(chart.DrawMargin) + chart.DrawMargin.Width, _anSpeed));
                Line.BeginAnimation(Line.Y1Property,
                                    new DoubleAnimation(y, i, _anSpeed));
                Line.BeginAnimation(Line.Y2Property,
                                    new DoubleAnimation(y, i, _anSpeed));

                var hh = axis.IsMerged
                    ? (i + TextBlock.ActualHeight > Canvas.GetTop(chart.DrawMargin) + chart.DrawMargin.Height
                        ? +TextBlock.ActualHeight
                        : 0)
                    : TextBlock.ActualHeight * .5;
                TextBlock.BeginAnimation(Canvas.TopProperty,
                                         new DoubleAnimation(y - hh + axis.UnitWidth * .5, i - hh + axis.UnitWidth * .5, _anSpeed));
            }
            else
            {
                var x = IsNew ? axis.FromPreviousAxisState(Value, direction, chart) : Line.X1;

                Line.BeginAnimation(Line.X1Property,
                                    new DoubleAnimation(x, i, _anSpeed));
                Line.BeginAnimation(Line.X2Property,
                                    new DoubleAnimation(x, i, _anSpeed));
                Line.BeginAnimation(Line.Y1Property,
                                    new DoubleAnimation(Line.Y1, Canvas.GetTop(chart.DrawMargin), _anSpeed));
                Line.BeginAnimation(Line.Y2Property,
                                    new DoubleAnimation(Line.Y2, Canvas.GetTop(chart.DrawMargin) + chart.DrawMargin.Height, _anSpeed));

                var hw = axis.IsMerged
                    ? (i + TextBlock.ActualWidth > Canvas.GetLeft(chart.DrawMargin) + chart.DrawMargin.Width
                        ? TextBlock.ActualWidth + 2
                        : -2)
                    : TextBlock.ActualWidth * .5;
                TextBlock.BeginAnimation(Canvas.LeftProperty,
                                         new DoubleAnimation(x - hw + axis.UnitWidth * .5, i - hw + axis.UnitWidth * .5, _anSpeed));
            }
        }
예제 #21
0
        /// <summary>
        /// Scales a graph value to screen according to an axis.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="axis"></param>
        /// <param name="chart"></param>
        /// <returns></returns>
        public static double ToPlotArea(double value, AxisTags axis, Chart chart)
        {
            //y = m (x - x1) + y1
            var p1 = axis == AxisTags.X
                ? new Point(chart.Max.X, chart.PlotArea.Width + chart.PlotArea.X)
                : new Point(chart.Max.Y, chart.PlotArea.Y);
            var p2 = axis == AxisTags.X
                ? new Point(chart.Min.X, chart.PlotArea.X)
                : new Point(chart.Min.Y, chart.PlotArea.Y + chart.PlotArea.Height);
            var m = (p2.Y - p1.Y) / (p2.X - p1.X);

            return(m * (value - p1.X) + p1.Y);
        }
예제 #22
0
        public static double GetUnitWidth(AxisTags source, ChartCore chart, int axis = 0)
        {
            double min;

            if (source == AxisTags.Y)
            {
                min = chart.AxisY[axis].MinLimit;
                return(ToDrawMargin(min, AxisTags.Y, chart, axis) - ToDrawMargin(min + 1, AxisTags.Y, chart, axis));
            }

            min = chart.AxisX[axis].MinLimit;
            return(ToDrawMargin(min + 1, AxisTags.X, chart, axis) - ToDrawMargin(min, AxisTags.X, chart, axis));
        }
예제 #23
0
        public static double GetUnitWidth(AxisTags source, ChartCore chart, AxisCore axis)
        {
            double min;

            if (source == AxisTags.Y)
            {
                min = axis.MinLimit;
                return(ToDrawMargin(min, AxisTags.Y, chart, axis) - ToDrawMargin(min + 1, AxisTags.Y, chart, axis));
            }

            min = axis.MinLimit;
            return(ToDrawMargin(min + 1, AxisTags.X, chart, axis) - ToDrawMargin(min, AxisTags.X, chart, axis));
        }
예제 #24
0
        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);
            }
        }
예제 #25
0
        internal void CalculateSeparator(ChartCore chart, AxisTags source)
        {
            var range = MaxLimit - MinLimit;

            range = range <= 0 ? 1 : range;

            //ToDO: Improve this according to current labels!
            var separations = source == AxisTags.Y
                ? Math.Round(chart.DrawMargin.Height / ((12) * CleanFactor), 0) // at least 3 font 12 labels per separator.
                : Math.Round(chart.DrawMargin.Width / (50 * CleanFactor), 0);   // at least 150 pixels per separator.

            separations = separations < 2 ? 2 : separations;

            var minimum = range / separations;

            Magnitude = Math.Pow(10, Math.Floor(Math.Log(minimum) / Math.Log(10)));

            if (Separator.Step != null)
            {
                S = Separator.Step ?? 1;
                return;
            }

            var    residual = minimum / Magnitude;
            double tick;

            if (residual > 5)
            {
                tick = 10 * Magnitude;
            }
            else if (residual > 2)
            {
                tick = 5 * Magnitude;
            }
            else if (residual > 1)
            {
                tick = 2 * Magnitude;
            }
            else
            {
                tick = Magnitude;
            }

            S = tick;

            if (Labels != null)
            {
                S = S < 1 ? 1 : S;
            }
        }
예제 #26
0
        public LabelEvaluation UpdateLabel(string text, AxisCore axis, AxisTags source)
        {
            TextBlock.Text = text;
            TextBlock.UpdateLayout();

            var transform = new LabelEvaluation(axis.View.LabelsRotation,
                                                TextBlock.ActualWidth, TextBlock.ActualHeight, axis, source);

            TextBlock.RenderTransform = Math.Abs(transform.LabelAngle) > 1
                ? new RotateTransform(transform.LabelAngle)
                : null;

            LabelModel = transform;

            return(transform);
        }
예제 #27
0
        private void UnanimatedPlace(Chart chart, AxisTags direction, int axisIndex, Axis axis)
        {
            var i = chart.ToPlotArea(Value, direction, axisIndex);

            Line.X1 = direction == AxisTags.Y
                ? Canvas.GetLeft(chart.DrawMargin)
                : i;
            Line.X2 = direction == AxisTags.Y
                ? Canvas.GetLeft(chart.DrawMargin) + chart.DrawMargin.Width
                : i;

            Line.Y1 = direction == AxisTags.Y
                ? i
                : Canvas.GetTop(chart.DrawMargin);
            Line.Y2 = direction == AxisTags.Y
                ? i
                : Canvas.GetTop(chart.DrawMargin) + chart.DrawMargin.Height;

            if (direction == AxisTags.Y)
            {
                var topM = axis.IsMerged
                    ? (i + TextBlock.ActualHeight > Canvas.GetTop(chart.DrawMargin) + chart.DrawMargin.Height
                        ? +TextBlock.ActualHeight
                        : 0)
                    : TextBlock.ActualHeight * .5;
                var leftM = axis.IsMerged ? TextBlock.ActualWidth + 10 : -2;
                Canvas.SetTop(TextBlock, i - topM);
                Canvas.SetLeft(TextBlock, axis.Position == CoreComponents.AxisPosition.LeftBottom
                    ? axis.LabelsReference - TextBlock.ActualWidth + leftM
                    : axis.LabelsReference - leftM);
            }
            else
            {
                var left = axis.IsMerged
                    ? (i + TextBlock.ActualWidth > Canvas.GetLeft(chart.DrawMargin) + chart.DrawMargin.Width
                        ? TextBlock.ActualWidth + 2
                        : -2)
                    : TextBlock.ActualWidth * .5;
                var top = axis.IsMerged ? TextBlock.ActualHeight : 0;
                Canvas.SetLeft(TextBlock, i - left);
                Canvas.SetTop(TextBlock,
                              axis.Position == CoreComponents.AxisPosition.LeftBottom
                        ? axis.LabelsReference - top
                        : axis.LabelsReference);
            }
        }
예제 #28
0
        public ChartCursor(Chart chart, AxisTags tag)
        {
            _chart = chart;
            _tag   = tag;

            Shape = new Rectangle
            {
                StrokeThickness = 2,
                Stroke          = new SolidColorBrush(Color.FromRgb(55, 71, 79)),
                Fill            = new SolidColorBrush(Color.FromRgb(55, 71, 79))
                {
                    Opacity = .3
                }
            };

            Canvas.SetLeft(Shape, 0d);
            Canvas.SetTop(Shape, 0d);
        }
예제 #29
0
        internal void UpdateSeparations(AxisTags direction, Chart chart, int axisPosition)
        {
            foreach (var separation in Separations.Values.ToArray())
            {
                if (!separation.IsActive)
                {
                    separation.State = SeparationState.Remove;
                    Separations.Remove(separation.Key);
                }
                separation.Place(chart, direction, axisPosition, this);
                separation.IsActive = false;
            }

            LastAxisMax  = MaxLimit;
            LastAxisMin  = MinLimit;
            LastPlotArea = new Rect(Canvas.GetLeft(chart.DrawMargin), Canvas.GetTop(chart.DrawMargin),
                                    chart.DrawMargin.Width, chart.DrawMargin.Height);
        }
예제 #30
0
        internal void UpdateSeparators(AxisTags source, ChartCore chart, int axisPosition)
        {
            foreach (var element in Cache.Values.ToArray())
            {
                if (!element.IsActive)
                {
                    element.State = SeparationState.Remove;
                    Cache.Remove(element.Key);
                }
                element.View.UpdateLine(source, chart, axisPosition, this);
                element.IsActive = false;
            }

            LastAxisMax  = MaxLimit;
            LastAxisMin  = MinLimit;
            LastPlotArea = new CoreRectangle(chart.DrawMargin.Left, chart.DrawMargin.Top,
                                             chart.DrawMargin.Width, chart.DrawMargin.Height);
        }
예제 #31
0
        /// <summary>
        /// Scales a graph value to screen according to an axis.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="source"></param>
        /// <param name="chart"></param>
        /// <param name="axis"></param>
        /// <returns></returns>
        public static double ToPlotArea(double value, AxisTags source, Chart chart, int axis = 0)
        {
            //y = m * (x - x1) + y1

            var p1 = new Point();
            var p2 = new Point();

            if (source == AxisTags.Y)
            {
                if (axis >= chart.AxisY.Count)
                {
                    throw new Exception("There is not a valid Y axis at position " + axis);
                }

                var ax = chart.AxisY[axis];

                p1.X = ax.MaxLimit;
                p1.Y = Canvas.GetTop(chart.DrawMargin);

                p2.X = ax.MinLimit;
                p2.Y = Canvas.GetTop(chart.DrawMargin) + chart.DrawMargin.Height;
            }
            else
            {
                if (axis >= chart.AxisX.Count)
                {
                    throw new Exception("There is not a valid X axis at position " + axis);
                }

                var ax = chart.AxisX[axis];

                p1.X = ax.MaxLimit;
                p1.Y = chart.DrawMargin.Width + Canvas.GetLeft(chart.DrawMargin);

                p2.X = ax.MinLimit;
                p2.Y = Canvas.GetLeft(chart.DrawMargin);
            }

            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);
        }
예제 #32
0
        private void MoveFromCurrentAx(Chart chart, AxisTags direction, int axisIndex, Axis axis)
        {
            var i = chart.ToPlotArea(Value, direction, axisIndex);

            if (direction == AxisTags.Y)
            {
                Line.BeginAnimation(Line.X1Property,
                                    new DoubleAnimation(Line.X1, Canvas.GetLeft(chart.DrawMargin), _anSpeed));
                Line.BeginAnimation(Line.X2Property,
                                    new DoubleAnimation(Line.X2, Canvas.GetLeft(chart.DrawMargin) + chart.DrawMargin.Width, _anSpeed));
                Line.BeginAnimation(Line.Y1Property,
                                    new DoubleAnimation(Line.Y1, i, _anSpeed));
                Line.BeginAnimation(Line.Y2Property,
                                    new DoubleAnimation(Line.Y2, i, _anSpeed));

                var hh = axis.IsMerged
                    ? (i + TextBlock.ActualHeight > Canvas.GetTop(chart.DrawMargin) + chart.DrawMargin.Height
                        ? +TextBlock.ActualHeight
                        : 0)
                    : TextBlock.ActualHeight * .5;
                TextBlock.BeginAnimation(Canvas.TopProperty,
                                         new DoubleAnimation(Line.Y1 - hh, i - hh, _anSpeed));
            }
            else
            {
                Line.BeginAnimation(Line.X1Property,
                                    new DoubleAnimation(Line.X1, i, _anSpeed));
                Line.BeginAnimation(Line.X2Property,
                                    new DoubleAnimation(Line.X2, i, _anSpeed));
                Line.BeginAnimation(Line.Y1Property,
                                    new DoubleAnimation(Line.Y1, Canvas.GetTop(chart.DrawMargin), _anSpeed));
                Line.BeginAnimation(Line.Y2Property,
                                    new DoubleAnimation(Line.Y2, Canvas.GetTop(chart.DrawMargin) + chart.DrawMargin.Height, _anSpeed));

                var hw = axis.IsMerged
                    ? (i + TextBlock.ActualWidth > Canvas.GetLeft(chart.DrawMargin) + chart.DrawMargin.Width
                        ? TextBlock.ActualWidth + 2
                        : -2)
                    : TextBlock.ActualWidth * .5;
                TextBlock.BeginAnimation(Canvas.LeftProperty,
                                         new DoubleAnimation(Line.X1 - hw, i - hw, _anSpeed));
            }
        }
예제 #33
0
        public void UpdateLine(AxisTags source, ChartCore chart, int axisIndex, AxisCore axis)
        {
            var wpfChart = chart.View as Chart;
            var wpfAxis  = axis.View as Axis;

            if (wpfChart == null || wpfAxis == null)
            {
                return;
            }

            switch (Model.State)
            {
            case SeparationState.Remove:
                if (!chart.View.DisableAnimations && !axis.DisableAnimations)
                {
                    MoveFromCurrentAx(wpfChart, source, axisIndex, wpfAxis);
                }
                Remove(wpfChart, wpfAxis);
                break;

            case SeparationState.Keep:
                UnanimatedPlace(wpfChart, source, axisIndex, wpfAxis);
                if (!chart.View.DisableAnimations && !axis.DisableAnimations)
                {
                    MoveFromPreviousAx(wpfChart, source, axisIndex, wpfAxis);
                }
                if (Model.IsNew)
                {
                    FadeIn(wpfChart, wpfAxis);
                }
                break;

            case SeparationState.InitialAdd:
                UnanimatedPlace(wpfChart, source, axisIndex, wpfAxis);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #34
0
 public double FromDrawMargin(double value, AxisTags axis)
 {
     return Methods.FromDrawMargin(value, axis, this);
 }
예제 #35
0
        internal CoreMargin PrepareChart(AxisTags source, ChartCore chart)
        {
            if (!(Math.Abs(MaxLimit - MinLimit) > S*.01) || !ShowLabels) return new CoreMargin();

            CalculateSeparator(chart, source);

            var f = GetFormatter();

            var currentMargin = new CoreMargin();
            var tolerance = S/10;

            InitializeGarbageCollector();

            for (var i = MinLimit; i <= MaxLimit - (EvaluatesUnitWidth ? 1 : 0); i += S)
            {
                SeparatorElementCore asc;

                var key = Math.Round(i/tolerance)*tolerance;
                if (!Cache.TryGetValue(key, out asc))
                {
                    asc = new SeparatorElementCore {IsNew = true};
                    Cache[key] = asc;
                }
                else
                {
                    asc.IsNew = false;
                }

                View.RenderSeparator(asc, Chart);

                asc.Key = key;
                asc.Value = i;
                asc.GarbageCollectorIndex = GarbageCollectorIndex;

                var labelsMargin = asc.View.UpdateLabel(f(i), this, source);

                currentMargin.Width = labelsMargin.TakenWidth > currentMargin.Width
                    ? labelsMargin.TakenWidth
                    : currentMargin.Width;
                currentMargin.Height = labelsMargin.TakenHeight > currentMargin.Height
                    ? labelsMargin.TakenHeight
                    : currentMargin.Height;

                currentMargin.Left = labelsMargin.Left > currentMargin.Left
                    ? labelsMargin.Left
                    : currentMargin.Left;
                currentMargin.Right = labelsMargin.Right > currentMargin.Right
                    ? labelsMargin.Right
                    : currentMargin.Right;

                currentMargin.Top = labelsMargin.Top > currentMargin.Top
                    ? labelsMargin.Top
                    : currentMargin.Top;
                currentMargin.Bottom = labelsMargin.Bottom > currentMargin.Bottom
                    ? labelsMargin.Bottom
                    : currentMargin.Bottom;

                if (LastAxisMax == null)
                {
                    asc.State = SeparationState.InitialAdd;
                    continue;
                }

                asc.State = SeparationState.Keep;
            }
            return currentMargin;
        }
예제 #36
0
 protected void ConfigureYAsIndexed()
 {
     AxisY.ShowLabels = AxisY.Labels != null;
     var m = (AxisY.Labels ?? new List<string> {""}).OrderByDescending(x => x.Length);
     var longestYLabel = new FormattedText(m.First(), CultureInfo.CurrentUICulture, FlowDirection.LeftToRight,
         new Typeface(AxisY.FontFamily, AxisY.FontStyle, AxisY.FontWeight, AxisY.FontStretch), AxisY.FontSize,
         Brushes.Black);
     AxisY.Separator.Step = (longestYLabel.Width*Max.Y)*1.25 > PlotArea.Width
         ? null
         : (int?) 1;
     if (AxisY.Separator.Step != null) S.Y = (int) AxisY.Separator.Step;
     if (Zooming) ZoomingAxis = AxisTags.Y;
 }
예제 #37
0
        internal double FromPreviousState(double value, AxisTags source, ChartCore chart)
        {
            if (LastAxisMax == null) return 0;

            var p1 = new CorePoint();
            var p2 = new CorePoint();

            if (source == AxisTags.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;
        }
예제 #38
0
		/// <summary>
		/// Scales a graph value to screen according to an axis. 
		/// </summary>
		/// <param name="value"></param>
		/// <param name="axis"></param>
		/// <returns></returns>
		public double ToPlotArea(double value, AxisTags axis)
		{
			return EnsureDouble(Methods.ToPlotArea(value, axis, this));
		}
예제 #39
0
        internal void UpdateSeparators(AxisTags source, ChartCore chart, int axisIndex)
        {
            foreach (var element in Cache.Values.ToArray())
            {
                if (element.GarbageCollectorIndex < GarbageCollectorIndex)
                {
                    element.State = SeparationState.Remove;
                    Cache.Remove(element.Key);
                }

                var toLine = ChartFunctions.ToPlotArea(element.Value, source, chart, axisIndex);

                var direction = source == AxisTags.X ? 1 : -1;

                toLine += EvaluatesUnitWidth ? direction*ChartFunctions.GetUnitWidth(source, chart, this)/2 : 0;
                var toLabel = toLine + element.View.LabelModel.GetOffsetBySource(source);

                if (IsMerged)
                {
                    const double padding = 4;

                    if (source == AxisTags.Y)
                    {
                        if (toLabel + element.View.LabelModel.ActualHeight >
                            chart.DrawMargin.Top + chart.DrawMargin.Height)
                            toLabel -= element.View.LabelModel.ActualHeight + padding;
                    }
                    else
                    {
                        if (toLabel + element.View.LabelModel.ActualWidth >
                            chart.DrawMargin.Left + chart.DrawMargin.Width)
                            toLabel -= element.View.LabelModel.ActualWidth + padding;
                    }
                }

                var labelTab = Tab;
                labelTab += element.View.LabelModel.GetOffsetBySource(source.Invert());

                switch (element.State)
                {
                    case SeparationState.Remove:
                        if (!chart.View.DisableAnimations && !View.DisableAnimations)
                        {
                            element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                            element.View.FadeOutAndRemove(chart);
                        }
                        else
                        {
                            element.View.Remove(chart);
                        }
                        break;
                    case SeparationState.Keep:
                        if (!chart.View.DisableAnimations && !View.DisableAnimations)
                        {
                            if (element.IsNew)
                            {
                                var toLinePrevious = FromPreviousState(element.Value, source, chart);
                                toLinePrevious += EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(source, chart, this) / 2 : 0;
                                var toLabelPrevious = toLinePrevious + element.View.LabelModel.GetOffsetBySource(source);
                                element.View.Place(chart, this, source, axisIndex, toLabelPrevious,
                                    toLinePrevious, labelTab);
                                element.View.FadeIn(this, chart);
                            }
                            element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                        }
                        else
                        {
                            element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                        }
                        break;
                    case SeparationState.InitialAdd:
                        element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }

            LastAxisMax = MaxLimit;
            LastAxisMin = MinLimit;
            LastPlotArea = new CoreRectangle(chart.DrawMargin.Left, chart.DrawMargin.Top,
                chart.DrawMargin.Width, chart.DrawMargin.Height);

            #if DEBUG
            Debug.WriteLine("Axis.Separations: " + Cache.Count);
            #endif
        }
예제 #40
0
        public void Move(ChartCore chart, AxisCore axis, AxisTags direction, int axisIndex, double toLabel, double toLine, double tab)
        {
            if (direction == AxisTags.Y)
            {
                Line.BeginAnimation(Line.X1Property,
                    new DoubleAnimation(chart.DrawMargin.Left, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.X2Property,
                    new DoubleAnimation(chart.DrawMargin.Left + chart.DrawMargin.Width, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y1Property,
                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y2Property,
                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));

                TextBlock.BeginAnimation(Canvas.TopProperty,
                    new DoubleAnimation(toLabel, chart.View.AnimationsSpeed));
                TextBlock.BeginAnimation(Canvas.LeftProperty,
                    new DoubleAnimation(tab, chart.View.AnimationsSpeed));
            }
            else
            {
                Line.BeginAnimation(Line.X1Property,
                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.X2Property,
                    new DoubleAnimation(toLine, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y1Property,
                    new DoubleAnimation(chart.DrawMargin.Top, chart.View.AnimationsSpeed));
                Line.BeginAnimation(Line.Y2Property,
                    new DoubleAnimation(chart.DrawMargin.Top + chart.DrawMargin.Height, chart.View.AnimationsSpeed));

                TextBlock.BeginAnimation(Canvas.LeftProperty,
                    new DoubleAnimation(toLabel, chart.View.AnimationsSpeed));
                TextBlock.BeginAnimation(Canvas.TopProperty,
                    new DoubleAnimation(tab, chart.View.AnimationsSpeed));
            }
        }
예제 #41
0
 public double GetOffsetBySource(AxisTags source)
 {
     return source == AxisTags.X
         ? XOffset
         : YOffset;
 }
예제 #42
0
        internal double CalculateSeparator(double range, AxisTags axis)
        {
            //based on:
            //http://stackoverflow.com/questions/361681/algorithm-for-nice-grid-line-intervals-on-a-graph

            range =  range <= 0 ? 1 : range;

            var ft = axis == AxisTags.Y
                ? new FormattedText(
                    "A label",
                    CultureInfo.CurrentUICulture,
                    FlowDirection.LeftToRight,
                    new Typeface(AxisY.FontFamily, AxisY.FontStyle, AxisY.FontWeight,
                        AxisY.FontStretch), AxisY.FontSize, Brushes.Black)
                : new FormattedText(
                    "A label",
                    CultureInfo.CurrentUICulture,
                    FlowDirection.LeftToRight,
                    new Typeface(AxisX.FontFamily, AxisX.FontStyle, AxisX.FontWeight,
                        AxisX.FontStretch), AxisX.FontSize, Brushes.Black);

            var separations = axis == AxisTags.Y
                ? Math.Round(PlotArea.Height / ((ft.Height) * AxisY.CleanFactor), 0)
                : Math.Round(PlotArea.Width / ((ft.Width) * AxisX.CleanFactor), 0);

            separations = separations < 2 ? 2 : separations;

            var minimum = range / separations;
            var magnitude = Math.Pow(10, Math.Floor(Math.Log(minimum) / Math.Log(10)));
            var residual = minimum / magnitude;
            double tick;
            if (residual > 5)
                tick = 10 * magnitude;
            else if (residual > 2)
                tick = 5 * magnitude;
            else if (residual > 1)
                tick = 2 * magnitude;
            else
                tick = magnitude;
            return tick;
        }
예제 #43
0
        internal void CalculateSeparator(ChartCore chart, AxisTags source)
        {
            var range = MaxLimit - MinLimit;
            range = range <= 0 ? 1 : range;

            //ToDO: Improve this according to current labels!
            var separations = source == AxisTags.Y
                ? Math.Round(chart.DrawMargin.Height/((12)*CleanFactor), 0) // at least 3 font 12 labels per separator.
                : Math.Round(chart.DrawMargin.Width/(50*CleanFactor), 0); // at least 150 pixels per separator.

            separations = separations < 2 ? 2 : separations;

            var minimum = range/separations;
            Magnitude = Math.Pow(10, Math.Floor(Math.Log(minimum)/Math.Log(10)));

            if (Separator.Step != null)
            {
                S = Separator.Step ?? 1;
                return;
            }

            var residual = minimum/Magnitude;
            double tick;
            if (residual > 5)
                tick = 10*Magnitude;
            else if (residual > 2)
                tick = 5*Magnitude;
            else if (residual > 1)
                tick = 2*Magnitude;
            else
                tick = Magnitude;

            S = tick;

            if (Labels != null) S = S < 1 ? 1 : S;
        }
예제 #44
0
        public LabelEvaluation UpdateLabel(string text, AxisCore axis, AxisTags source)
        {
            TextBlock.Text = text;
            TextBlock.UpdateLayout();

            var transform = new LabelEvaluation(axis.View.LabelsRotation,
                TextBlock.ActualWidth, TextBlock.ActualHeight, axis, source);

            TextBlock.RenderTransform = Math.Abs(transform.LabelAngle) > 1
                ? new RotateTransform(transform.LabelAngle)
                : null;

            LabelModel = transform;

            return transform;
        }
예제 #45
0
        public void Place(ChartCore chart, AxisCore axis, AxisTags direction, int axisIndex, 
            double toLabel, double toLine, double tab)
        {
            if (direction == AxisTags.Y)
            {
                Line.X1 = chart.DrawMargin.Left;
                Line.X2 = chart.DrawMargin.Left + chart.DrawMargin.Width;
                Line.Y1 = toLine;
                Line.Y2 = toLine;

                Canvas.SetLeft(TextBlock, tab);
                Canvas.SetTop(TextBlock, toLabel);
            }
            else
            {
                Line.X1 = toLine;
                Line.X2 = toLine;
                Line.Y1 = chart.DrawMargin.Top;
                Line.Y2 = chart.DrawMargin.Top + chart.DrawMargin.Height;

                Canvas.SetLeft(TextBlock, toLabel);
                Canvas.SetTop(TextBlock, tab);
            }
        }
예제 #46
0
 public double LenghtOf(double value, AxisTags axis)
 {
     var isX = axis == AxisTags.X;
     var m = isX ? Min.X : Min.Y;
     var o = isX ? PlotArea.X : PlotArea.Y;
     return Methods.ToPlotArea(m + value, axis, this) - o;
 }
예제 #47
0
 public double LenghtOf(double value, AxisTags axis)
 {
     return Methods.ToPlotArea(value, axis, this) - (axis == AxisTags.X ? PlotArea.X : PlotArea.Y);
 }
예제 #48
0
 /// <summary>
 /// Scales a graph value to screen according to an axis. 
 /// </summary>
 /// <param name="value"></param>
 /// <param name="axis"></param>
 /// <returns></returns>
 public double ToPlotArea(double value, AxisTags axis)
 {
     return Methods.ToPlotArea(value, axis, this);
 }
예제 #49
0
 /// <summary>
 /// Scales a graph value to screen according to an axis. 
 /// </summary>
 /// <param name="value"></param>
 /// <param name="axis"></param>
 /// <returns></returns>
 protected double ToPlotArea(double value, AxisTags axis)
 {
     return Methods.ToPlotArea(value, axis, Chart);
 }
예제 #50
0
 protected void ConfigureYAsIndexed()
 {
     if (AxisY.Labels == null && AxisY.LabelFormatter == null) AxisY.ShowLabels = false;
     var f = GetFormatter(AxisY);
     var d = AxisY.Labels == null
         ? Max.Y
         : AxisY.Labels.IndexOf(AxisY.Labels.OrderBy(x => x.Length).Reverse().First());
     var longestYLabel = new FormattedText(HasValidRange ? f(d) : "", CultureInfo.CurrentUICulture,
         FlowDirection.LeftToRight,
         new Typeface(AxisY.FontFamily, AxisY.FontStyle, AxisY.FontWeight, AxisY.FontStretch), AxisY.FontSize,
         Brushes.Black);
     AxisY.Separator.Step = (longestYLabel.Width*Max.Y)*1.25 > PlotArea.Width
         ? null
         : (int?) 1;
     if (AxisY.Separator.Step != null) S.Y = (int) AxisY.Separator.Step;
     if (Zoom != ZoomingOptions.None) ZoomingAxis = AxisTags.Y;
 }
예제 #51
0
        public LabelEvaluation(double angle, double w, double h, AxisCore axis, AxisTags source)
        {
            const double padding = 4;

            ActualWidth = w;
            ActualHeight = h;

            // for now there is no support for rotated and merged labels.
            // the labels will be rotated but there is no warranty that they are displayed correctly
            if (axis.View.IsMerged)
            {
                Top = 0;
                Bottom = 0;
                Left = 0;
                Right = 0;

                if (source == AxisTags.Y)
                {
                    XOffset = padding;
                    YOffset = padding;
                }
                else
                {
                    if (axis.Position == AxisPosition.LeftBottom)
                    {
                        //Bot
                        XOffset = padding;
                        YOffset = -h*2 - padding;
                    }
                    else
                    {
                        //Top
                        XOffset = padding;
                        YOffset = padding + h*2;
                    }
                }

                return;
            }

            //OK now lets evaluate the rotation angle...

            // the rotation angle starts from an horizontal line, yes like this text
            // - 0°, | 90°, - 180°, | 270°
            // notice normally rotating a label from 90 to 270° will show the label
            // in a wrong orientation
            // we need to fix that angle

            const double toRadians = Math.PI/180;

            // 1. width components
            // 2. height components

            WFromW = Math.Abs(Math.Cos(angle*toRadians)*w); // W generated from the width of the label
            WFromH = Math.Abs(Math.Sin(angle*toRadians)*h); // W generated from the height of the label

            HFromW = Math.Abs(Math.Sin(angle*toRadians)*w); // H generated from the width of the label
            HFromH = Math.Abs(Math.Cos(angle*toRadians)*h); // H generated from the height of the label

            LabelAngle = angle%360;
            if (LabelAngle < 0) LabelAngle += 360;
            if (LabelAngle > 90 && LabelAngle < 270)
                LabelAngle = (LabelAngle + 180)%360;

            //at this points angles should only exist in 1st and 4th quadrant
            //those are the only quadrants that generates readable labels
            //the other 2 quadrants display inverted labels

            var quadrant = ((int) (LabelAngle/90))%4 + 1;

            if (source == AxisTags.Y)
            {
                // Y Axis
                if (quadrant == 1)
                {
                    if (axis.Position == AxisPosition.LeftBottom)
                    {
                        // 1, L
                        Top = HFromW + (HFromH/2);      //space taken from separator to top
                        Bottom = TakenHeight - Top;          //space taken from separator to bottom
                        XOffset = -WFromW - padding;    //distance from separator to label origin in X
                        YOffset = -Top;                 //distance from separator to label origin in Y
                    }
                    else
                    {
                        // 1, R
                        Bottom = HFromW + (HFromH/2);
                        Top = TakenHeight - Bottom;
                        XOffset = padding + WFromH;
                        YOffset = -Top;
                    }
                }
                else
                {
                    if (axis.Position == AxisPosition.LeftBottom)
                    {
                        // 4, L
                        Bottom = HFromW + (HFromH/2);
                        Top = TakenHeight - Bottom;
                        XOffset = -TakenWidth - padding;
                        YOffset = HFromW - (HFromH/2);
                    }
                    else
                    {
                        // 4, R
                        Top = HFromW + (HFromH/2);
                        Bottom = TakenHeight - Top;
                        XOffset = padding;
                        YOffset = -Bottom;
                    }
                }
            }
            else
            {
                // X Axis

                //axis x has one exception, if labels rotation equals 0° then the label is centered
                if (Math.Abs(axis.View.LabelsRotation) < .01)
                {
                    Left = TakenWidth / 2;
                    Right = Left;
                    XOffset = -Left;
                    YOffset = axis.Position == AxisPosition.LeftBottom
                        ? padding
                        : -padding - TakenHeight;
                }
                else
                {
                    if (quadrant == 1)
                    {
                        if (axis.Position == AxisPosition.LeftBottom)
                        {
                            //1, B
                            Right = WFromW + (WFromH / 2);  //space taken from separator to right
                            Left = TakenWidth - Right;           //space taken from separator to left
                            XOffset = Left;                 //distance from separator to label origin in X
                            YOffset = padding;              //distance from separator to label origin in Y
                        }
                        else
                        {
                            //1, T
                            Left = WFromW + (WFromH/2);
                            Right = TakenWidth - Left;
                            XOffset = -WFromW;
                            YOffset = -padding - TakenHeight;
                        }
                    }
                    else
                    {
                        if (axis.Position == AxisPosition.LeftBottom)
                        {
                            //4, B
                            Left = WFromW + (WFromH/2);
                            Right = TakenWidth - Left;
                            XOffset = -Left;
                            YOffset = padding + HFromW;
                        }
                        else
                        {
                            //4, T
                            Right = WFromW + (WFromH/2);
                            Left = TakenWidth - Right;
                            XOffset = -Left;
                            YOffset = -HFromH;
                        }
                    }
                }
            }
        }