/// <summary>
        /// Returns a geoJson map into a heat map.
        /// </summary>
        /// <param name="geoJson">The geoJson.</param>
        /// <param name="values">The values.</param>
        /// <param name="heatMap">The heat map.</param>
        /// <param name="heatStops">The heat stops.</param>
        /// <param name="stroke">The stroke.</param>
        /// <param name="fill">The fill.</param>
        /// <param name="thickness">The thickness.</param>
        /// <param name="projector">The projector.</param>
        /// <returns></returns>
        public static IEnumerable<PathShape> AsHeatMapShapes(
            this GeoJsonFile geoJson,
            Dictionary<string, double> values,
            LvcColor[] heatMap, List<Tuple<double, LvcColor>> heatStops,
            LvcColor stroke,
            LvcColor fill,
            float thickness,
            MapProjector projector)
        {
            var paths = new List<PathShape>();

            var weightBounds = new Bounds();
            foreach (var value in values)
            {
                weightBounds.AppendValue(value.Value);
            }

            var d = new double[0][][][];

            foreach (var feature in geoJson.Features ?? new GeoJsonFeature[0])
            {
                var name = feature.Properties is not null ? feature.Properties["shortName"] : "";
                LvcColor? baseColor = values.TryGetValue(name, out var weight)
                    ? HeatFunctions.InterpolateColor((float)weight, weightBounds, heatMap, heatStops)
                    : null;

                foreach (var geometry in feature.Geometry?.Coordinates ?? d)
                {
                    foreach (var segment in geometry)
                    {
                        var path = new PathShape
                        {
                            StrokeColor = stroke,
                            FillColor = baseColor ?? fill,
                            StrokeThickness = thickness,
                            IsClosed = true
                        };
                        var isFirst = true;
                        foreach (var point in segment)
                        {
                            var p = projector.ToMap(point);

                            if (isFirst)
                            {
                                isFirst = false;
                                path.AddCommand(new MoveToPathCommand { X = p[0], Y = p[1] });
                                continue;
                            }

                            path.AddCommand(new LineSegment { X = p[0], Y = p[1] });
                        }
                        paths.Add(path);
                    }
                }
            }

            return paths;
        }
Exemple #2
0
    /// <summary>
    /// Initializes a new instance of the <see cref="CartesianChart"/> class.
    /// </summary>
    /// <exception cref="Exception">Default colors are not valid</exception>
    public CartesianChart()
    {
        InitializeComponent();

        // workaround to detect mouse events.
        // Avalonia do not seem to detect pointer events if background is not set.
        ((IChartView)this).BackColor = LvcColor.FromArgb(0, 0, 0, 0);

        if (!LiveCharts.IsConfigured)
        {
            LiveCharts.Configure(LiveChartsSkiaSharp.DefaultPlatformBuilder);
        }

        var stylesBuilder = LiveCharts.CurrentSettings.GetTheme <SkiaSharpDrawingContext>();
        var initializer   = stylesBuilder.GetVisualsInitializer();

        if (stylesBuilder.CurrentColors is null || stylesBuilder.CurrentColors.Length == 0)
        {
            throw new Exception("Default colors are not valid");
        }
        initializer.ApplyStyleToChart(this);

        InitializeCore();

        AttachedToVisualTree += CartesianChart_AttachedToVisualTree;

        _seriesObserver   = new CollectionDeepObserver <ISeries>(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true);
        _xObserver        = new CollectionDeepObserver <ICartesianAxis>(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true);
        _yObserver        = new CollectionDeepObserver <ICartesianAxis>(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true);
        _sectionsObserver = new CollectionDeepObserver <Section <SkiaSharpDrawingContext> >(
            OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true);

        XAxes = new List <ICartesianAxis>()
        {
            LiveCharts.CurrentSettings.GetProvider <SkiaSharpDrawingContext>().GetDefaultCartesianAxis()
        };
        YAxes = new List <ICartesianAxis>()
        {
            LiveCharts.CurrentSettings.GetProvider <SkiaSharpDrawingContext>().GetDefaultCartesianAxis()
        };
        Series = new ObservableCollection <ISeries>();

        PointerPressed += CartesianChart_PointerPressed;
        PointerMoved   += CartesianChart_PointerMoved;
        // .. special case in avalonia for pointer released... he handle our own pointer capture.
        PointerWheelChanged += CartesianChart_PointerWheelChanged;
        PointerLeave        += CartesianChart_PointerLeave;

        DetachedFromVisualTree += CartesianChart_DetachedFromVisualTree;
    }
Exemple #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PolarChart"/> class.
        /// </summary>
        /// <exception cref="Exception">Default colors are not valid</exception>
        public PolarChart()
        {
            InitializeComponent();

            // workaround to detect mouse events.
            // Avalonia do not seem to detect pointer events if background is not set.
            ((IChartView)this).BackColor = LvcColor.FromArgb(0, 0, 0, 0);

            if (!LiveCharts.IsConfigured)
            {
                LiveCharts.Configure(LiveChartsSkiaSharp.DefaultPlatformBuilder);
            }

            var stylesBuilder = LiveCharts.CurrentSettings.GetTheme <SkiaSharpDrawingContext>();
            var initializer   = stylesBuilder.GetVisualsInitializer();

            if (stylesBuilder.CurrentColors is null || stylesBuilder.CurrentColors.Length == 0)
            {
                throw new Exception("Default colors are not valid");
            }
            initializer.ApplyStyleToChart(this);

            InitializeCore();

            AttachedToVisualTree += OnAttachedToVisualTree;

            _seriesObserver = new CollectionDeepObserver <ISeries>(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true);
            _angleObserver  = new CollectionDeepObserver <IPolarAxis>(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true);
            _radiusObserver = new CollectionDeepObserver <IPolarAxis>(OnDeepCollectionChanged, OnDeepCollectionPropertyChanged, true);

            AngleAxes = new List <IPolarAxis>()
            {
                LiveCharts.CurrentSettings.PolarAxisProvider()
            };
            RadiusAxes = new List <IPolarAxis>()
            {
                LiveCharts.CurrentSettings.PolarAxisProvider()
            };
            Series = new ObservableCollection <ISeries>();

            PointerWheelChanged += PolarChart_PointerWheelChanged;
            PointerPressed      += PolarChart_PointerPressed;
            PointerMoved        += PolarChart_PointerMoved;

            PointerLeave           += PolarChart_PointerLeave;
            DetachedFromVisualTree += PolarChart_DetachedFromVisualTree;
        }
Exemple #4
0
    /// <summary>
    /// Interpolates the color.
    /// </summary>
    /// <param name="weight">The weight.</param>
    /// <param name="weightBounds">The weight bounds.</param>
    /// <param name="heatMap">The heat map.</param>
    /// <param name="heatStops">The heat stops.</param>
    /// <returns></returns>
    public static LvcColor InterpolateColor(float weight, Bounds weightBounds, LvcColor[] heatMap, List <Tuple <double, LvcColor> > heatStops)
    {
        var range = weightBounds.Max - weightBounds.Min;

        if (range == 0)
        {
            range = double.Epsilon;
        }
        var p = (weight - weightBounds.Min) / range;

        if (p < 0)
        {
            p = 0;
        }
        if (p > 1)
        {
            p = 1;
        }

        var previous = heatStops[0];

        for (var i = 1; i < heatStops.Count; i++)
        {
            var next = heatStops[i];

            if (next.Item1 < p)
            {
                previous = heatStops[i];
                continue;
            }

            var px = (p - previous.Item1) / (next.Item1 - previous.Item1);

            return(LvcColor.FromArgb(
                       (byte)(previous.Item2.A + px * (next.Item2.A - previous.Item2.A)),
                       (byte)(previous.Item2.R + px * (next.Item2.R - previous.Item2.R)),
                       (byte)(previous.Item2.G + px * (next.Item2.G - previous.Item2.G)),
                       (byte)(previous.Item2.B + px * (next.Item2.B - previous.Item2.B))));
        }

        return(heatMap[heatMap.Length - 1]);
    }
Exemple #5
0
    /// <summary>
    /// Initialices a new instance of the <see cref="HeatLandSeries"/> class.
    /// </summary>
    public HeatLandSeries()
    {
        HeatMap = new[]
        {
            LvcColor.FromArgb(255, 179, 229, 252),  // cold (min value)
            LvcColor.FromArgb(255, 2, 136, 209)     // hot (max value)
        };

        if (!LiveCharts.IsConfigured)
        {
            LiveCharts.Configure(LiveChartsSkiaSharp.DefaultPlatformBuilder);
        }
        IntitializeSeries(LiveCharts.CurrentSettings.GetProvider <SkiaSharpDrawingContext>().GetSolidColorPaint());

        // ToDo: Themeit!

        //var stylesBuilder = LiveCharts.CurrentSettings.GetTheme<TDrawingContext>();
        //var initializer = stylesBuilder.GetVisualsInitializer();
        //if (stylesBuilder.CurrentColors is null || stylesBuilder.CurrentColors.Length == 0)
        //    throw new Exception("Default colors are not valid");

        //initializer.ApplyStyleToSeries(this);
    }
 /// <summary>
 /// Gets a new paint of the given color.
 /// </summary>
 /// <returns></returns>
 public abstract IPaint <TDrawingContext> GetSolidColorPaint(LvcColor color = new());
Exemple #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PathShape"/> class.
 /// </summary>
 public PathShape() : base()
 {
     _strokeProperty = RegisterMotionProperty(new ColorMotionProperty(nameof(StrokeColor), LvcColor.FromArgb(0, 255, 255, 255)));
     _stProperty     = RegisterMotionProperty(new FloatMotionProperty(nameof(StrokeThickness)));
     _fillProperty   = RegisterMotionProperty(new ColorMotionProperty(nameof(StrokeColor), LvcColor.FromArgb(0, 255, 255, 255)));
 }
Exemple #8
0
 /// <summary>
 /// Creates a new color based on the
 /// </summary>
 /// <param name="color">The color.</param>
 /// <param name="opacity">The opacity from 0 to 255.</param>
 /// <returns></returns>
 public static LvcColor WithOpacity(this LvcColor color, byte opacity)
 {
     return(LvcColor.FromArgb(opacity, color));
 }
Exemple #9
0
 /// <summary>
 /// Converts a <see cref="LvcColor"/> to a <see cref="SKColor"/> instance.
 /// </summary>
 /// <param name="color">The color.</param>
 /// <param name="alphaOverrides">The alpha overrides.</param>
 /// <returns></returns>
 public static SKColor AsSKColor(this LvcColor color, byte?alphaOverrides = null)
 {
     return(new SKColor(color.R, color.G, color.B, alphaOverrides ?? color.A));
 }
Exemple #10
0
        /// <summary>
        /// Adds the light theme.
        /// </summary>
        /// <param name="settings">The settings.</param>
        /// <param name="additionalStyles">The additional styles.</param>
        /// <returns></returns>
        public static LiveChartsSettings AddDarkTheme(
            this LiveChartsSettings settings, Action <Theme <SkiaSharpDrawingContext> >?additionalStyles = null)
        {
            return(settings
                   .HasTheme((Theme <SkiaSharpDrawingContext> theme) =>
            {
                _ = theme
                    .WithColors(ColorPalletes.MaterialDesign200)
                    .WithStyle(style =>
                               style
                               .HasRuleForCharts(chart =>
                {
                    //chart.BackColor = Color.FromArgb(255, 40, 40, 40);
                    chart.AnimationsSpeed = TimeSpan.FromMilliseconds(700);
                    chart.EasingFunction = EasingFunctions.ExponentialOut;

                    // The point states dictionary defines the fill and stroke to use for a point marked with the
                    // state key, LiveCharts uses this dictionary to highlight a chart point when the mouse is
                    // over a point, for example, the first .WithState() defines that every time a point is marked
                    // with the LiveCharts.BarSeriesHoverKey key, the library will draw a null stroke and
                    // new SKColor(255, 255, 255, 180) as the fill (defaultHoverColor).
                    var defaultHoverColor = LvcColor.FromArgb(40, 255, 255, 255).AsSKColor();
                    chart.PointStates =
                        new PointStatesDictionary <SkiaSharpDrawingContext>()
                        .WithState(
                            LiveCharts.BarSeriesHoverKey, null, new SolidColorPaint(defaultHoverColor), true)
                        .WithState(
                            LiveCharts.StepLineSeriesHoverKey, null, new SolidColorPaint(defaultHoverColor), true)
                        .WithState(
                            LiveCharts.LineSeriesHoverKey, null, new SolidColorPaint(defaultHoverColor), true)
                        .WithState(
                            LiveCharts.PieSeriesHoverKey, null, new SolidColorPaint(defaultHoverColor), true)
                        .WithState(
                            LiveCharts.ScatterSeriesHoverKey, null, new SolidColorPaint(defaultHoverColor), true)
                        .WithState(
                            LiveCharts.StackedBarSeriesHoverKey, null, new SolidColorPaint(defaultHoverColor), true)
                        .WithState(
                            LiveCharts.HeatSeriesHoverState, null, new SolidColorPaint(defaultHoverColor), true);
                })
                               .HasRuleForAxes(axis =>
                {
                    axis.TextSize = 18;
                    axis.ShowSeparatorLines = true;
                    axis.NamePaint = DefaultPaintTask;
                    axis.LabelsPaint = DefaultPaintTask;
                    axis.SeparatorsPaint = DefaultPaintTask;
                })
                               // ForAnySeries() will be called for all the series
                               .HasRuleForAnySeries(series =>
                {
                    if (series is not IStrokedAndFilled <SkiaSharpDrawingContext> strokedAndFilled)
                    {
                        return;
                    }
                    strokedAndFilled.Fill = DefaultPaintTask;
                    strokedAndFilled.Stroke = DefaultPaintTask;
                })
                               .HasRuleForLineSeries(lineSeries =>
                {
                    lineSeries.GeometrySize = 18;
                    lineSeries.GeometryFill = new SolidColorPaint(LvcColor.FromArgb(255, 40, 40, 40).AsSKColor());
                    lineSeries.GeometryStroke = DefaultPaintTask;
                })
                               .HasRuleForStepLineSeries(steplineSeries =>
                {
                    // at this point ForAnySeries() was already called
                    // we are configuring the missing properties
                    steplineSeries.GeometrySize = 18;
                    steplineSeries.GeometryFill = new SolidColorPaint(LvcColor.FromArgb(255, 40, 40, 40).AsSKColor());
                    steplineSeries.GeometryStroke = DefaultPaintTask;
                })
                               .HasRuleForStackedLineSeries(stackedLine =>
                {
                    // at this point both ForAnySeries() and ForLineSeries() were already called
                    // again we are correcting the previous settings
                    stackedLine.GeometrySize = 0;
                    stackedLine.GeometryFill = null;
                    stackedLine.GeometryStroke = null;
                    stackedLine.Stroke = null;
                    stackedLine.Fill = DefaultPaintTask;
                })
                               .HasRuleForBarSeries(barSeries =>
                {
                    // only ForAnySeries() has run, a bar series is not
                    // any of the previous types.
                    barSeries.Stroke = null;
                    barSeries.Rx = 4;
                    barSeries.Ry = 4;
                })
                               .HasRuleForStackedBarSeries(stackedBarSeries =>
                {
                    stackedBarSeries.Rx = 0;
                    stackedBarSeries.Ry = 0;
                })
                               .HasRuleForPieSeries(pieSeries =>
                {
                    pieSeries.Fill = DefaultPaintTask;
                    pieSeries.Stroke = null;
                    pieSeries.Pushout = 0;
                })
                               .HasRuleForStackedStepLineSeries(stackedStep =>
                {
                    stackedStep.GeometrySize = 0;
                    stackedStep.GeometryFill = null;
                    stackedStep.GeometryStroke = null;
                    stackedStep.Stroke = null;
                    stackedStep.Fill = DefaultPaintTask;
                })
                               .HasRuleForHeatSeries(heatSeries =>
                {
                    // ... rules here
                })
                               .HasRuleForFinancialSeries(financialSeries =>
                {
                    financialSeries.UpFill = DefaultPaintTask;
                    financialSeries.DownFill = DefaultPaintTask;
                    financialSeries.UpStroke = DefaultPaintTask;
                    financialSeries.DownStroke = DefaultPaintTask;
                }))
                    // finally add a resolver for the DefaultPaintTask
                    // the library already provides the AddDefaultResolvers() method
                    // this method only translates 'DefaultPaintTask' to a valid stroke/fill based on
                    // the series context
                    .AddDefaultDarkResolvers();

                additionalStyles?.Invoke(theme);
            }));
        }
Exemple #11
0
 private static LvcColor RGB(byte r, byte g, byte b)
 {
     return(LvcColor.FromArgb(255, r, g, b));
 }
Exemple #12
0
    /// <summary>
    /// Adds the light theme.
    /// </summary>
    /// <param name="settings">The settings.</param>
    /// <param name="additionalStyles">the additional styles.</param>
    /// <returns></returns>
    public static LiveChartsSettings AddLightTheme(
        this LiveChartsSettings settings, Action <Theme <SkiaSharpDrawingContext> >?additionalStyles = null)
    {
        return(settings
               .HasTheme((Theme <SkiaSharpDrawingContext> theme) =>
        {
            _ = theme
                .WithColors(ColorPalletes.MaterialDesign500)
                .WithStyle(style =>
                           style
                           .HasRuleForCharts(chart =>
            {
                chart.AnimationsSpeed = TimeSpan.FromMilliseconds(800);
                chart.EasingFunction = EasingFunctions.ExponentialOut;
            })
                           .HasRuleForAxes(axis =>
            {
                axis.TextSize = 16;
                axis.ShowSeparatorLines = true;
                axis.NamePaint = LiveChartsSkiaSharp.DefaultPaint;
                axis.LabelsPaint = LiveChartsSkiaSharp.DefaultPaint;
                axis.SeparatorsPaint = LiveChartsSkiaSharp.DefaultPaint;
            })
                           // ForAnySeries() will be called for all the series
                           .HasRuleForAnySeries(series =>
            {
                if (series is not IStrokedAndFilled <SkiaSharpDrawingContext> strokedAndFilled)
                {
                    return;
                }
                strokedAndFilled.Fill = LiveChartsSkiaSharp.DefaultPaint;
                strokedAndFilled.Stroke = LiveChartsSkiaSharp.DefaultPaint;
            })
                           .HasRuleForLineSeries(lineSeries =>
            {
                // at this point ForAnySeries() was already called
                // we are configuring the missing properties
                lineSeries.GeometrySize = 18;
                lineSeries.GeometryFill = new SolidColorPaint(LvcColor.FromArgb(255, 250, 250, 250).AsSKColor());
                lineSeries.GeometryStroke = LiveChartsSkiaSharp.DefaultPaint;
            })
                           .HasRuleForStepLineSeries(steplineSeries =>
            {
                // at this point ForAnySeries() was already called
                // we are configuring the missing properties
                steplineSeries.GeometrySize = 18;
                steplineSeries.GeometryFill = new SolidColorPaint(LvcColor.FromArgb(255, 250, 250, 250).AsSKColor());
                steplineSeries.GeometryStroke = LiveChartsSkiaSharp.DefaultPaint;
            })
                           .HasRuleForStackedLineSeries(stackedLine =>
            {
                // at this point both ForAnySeries() and ForLineSeries() were already called
                // again we are correcting the previous settings
                stackedLine.GeometrySize = 0;
                stackedLine.GeometryFill = null;
                stackedLine.GeometryStroke = null;
                stackedLine.Stroke = null;
                stackedLine.Fill = LiveChartsSkiaSharp.DefaultPaint;
            })
                           .HasRuleForBarSeries(barSeries =>
            {
                // only ForAnySeries() has run, a bar series is not
                // any of the previous types.
                barSeries.Stroke = null;
                barSeries.Rx = 4;
                barSeries.Ry = 4;
            })
                           .HasRuleForStackedBarSeries(stackedBarSeries =>
            {
                stackedBarSeries.Rx = 0;
                stackedBarSeries.Ry = 0;
            })
                           .HasRuleForPieSeries(pieSeries =>
            {
                pieSeries.Fill = LiveChartsSkiaSharp.DefaultPaint;
                pieSeries.Stroke = null;
                pieSeries.Pushout = 0;
            })
                           .HasRuleForStackedStepLineSeries(stackedStep =>
            {
                stackedStep.GeometrySize = 0;
                stackedStep.GeometryFill = null;
                stackedStep.GeometryStroke = null;
                stackedStep.Stroke = null;
                stackedStep.Fill = LiveChartsSkiaSharp.DefaultPaint;
            })
                           .HasRuleForHeatSeries(heatSeries =>
            {
                // ... rules here
            })
                           .HasRuleForFinancialSeries(financialSeries =>
            {
                financialSeries.UpFill = LiveChartsSkiaSharp.DefaultPaint;
                financialSeries.DownFill = LiveChartsSkiaSharp.DefaultPaint;
                financialSeries.UpStroke = LiveChartsSkiaSharp.DefaultPaint;
                financialSeries.DownStroke = LiveChartsSkiaSharp.DefaultPaint;
            })
                           .HasRuleForPolarLineSeries(polarLine =>
            {
                polarLine.GeometrySize = 18;
                polarLine.GeometryFill = new SolidColorPaint(LvcColor.FromArgb(255, 250, 250, 250).AsSKColor());
                polarLine.GeometryStroke = LiveChartsSkiaSharp.DefaultPaint;
            }))
                // finally add a resolver for the DefaultPaintTask
                // the library already provides the AddDefaultLightResolvers() and AddDefaultDarkResolvers methods
                // this method only translates 'DefaultPaintTask' to a valid stroke/fill based on
                // the series context
                .AddDefaultLightResolvers();

            additionalStyles?.Invoke(theme);
        }));
    }
 /// <inheritdoc cref="ChartProvider{TDrawingContext}.GetSolidColorPaint(LvcColor)"/>
 public override IPaint <SkiaSharpDrawingContext> GetSolidColorPaint(LvcColor color)
 {
     return(new SolidColorPaint(new SKColor(color.R, color.G, color.B, color.A)));
 }