This is the discussion forum for OxyPlot.
For bugs and new features, use the issue tracker located at GitHub.
Also try the chat room!

3D graph

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

hmahajan wrote at 2013-10-19 17:34:

Is it possible to create 3D graph like 3D piechart in oxyplot?

everytimer wrote at 2013-10-19 17:55:


hmahajan wrote at 2013-10-19 19:17:

Already using oxyplot to difficult to switch now.
What options are available in oxyplot for 3D

everytimer wrote at 2013-10-19 19:42:

It's not suitable for 3D, it will be easier for you to spend a couple days to learn to how to use a real 3D library.

PD. It's hard to eat a soup only with a fork.

objo wrote at 2013-10-19 20:30:

Sorry, this library does not support 3D. It is quite influenced by the works of Edward Tufte and Stephen Few, who strongly discourage pie charts and 3D effects.

Image

Synced Major Gridlines

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

KB24 wrote at 2014-05-28 17:31:

Hi and thanks for an awesome component.

I'm trying to accomplish the following:
  • One main y-axis on the left side.
  • Two secondary y-axes on the right side.
  • All three axes are at different scales and connected to different curves.
I would like to arrange the two right side axes to have the same number of major steps as the main left axis and I would like them to be zoom/panned in such a way that the major grid lines line up. The goal is to be able to follow the grid line from either side of the graph and have it match up against a major grid value on all axis.

Does anyone have any experience doing this and can give me a nudge in the right direction?

objo wrote at 2014-06-06 21:18:

I would like this too! I added https://oxyplot.codeplex.com/workitem/10217
I think it can be related to "synchronized axes" - https://oxyplot.codeplex.com/workitem/9945
but I have no idea on how to solve it!

KB24 wrote at 2014-06-21 15:03:

I kinda solved this problem, unfortuntely I did not have time to do it in a completely generic fashion.
You are welcome to use any of the follwing to make it generic and add it to Oxyplot though!

Background:
My graph contains 4 y-axis, 2 on each side.

Implementation:
I first had to decide how many major grid lines I was going to use for all the axes.
In my case, I constrained it to 20, because it works out well enough.
But one Idea I had that I never had time to implement was to let oxyplot create the axis natuarally by it self,
then find the one which naturally had the most grid marks and use that number of gridmarks as my gridmarkCount.

Then I had to make sure each axis started on a value and ended on a value, so first grid mark is always at the very bottom and last gridmark is always at the very top. This is simple enough if you set the minimum and maxium values to proper values.

Then I had to calculate a gridStep value that was evenly divisible by (maximum - minumum) / gridmarkCount.
This can be a bit tricky because the step values have to follow 1, 2, 5 , 10 etc, but its doable.

Finally, I needed a function to simply add x amount of gridSteps to the maximum of all other axis except the main, to make sure we ended up with gridmarkCount.

In my specific example it worked out like this:
  • MainAxis predetermined, not dynamic.
  • GridmarkCount = 20, not dynamic.
  • Minimum and Maximum always are 0 and 100 on my main axis, not dynamic.
  • Thus gridmarkStep becomes 5 on my main axis.
  • Calculate minimum and maximum for all other axis.
    If other axis turned out to have less than 20 gridmarks, I simply added x gridSteps to the maximum, thus changing the maximum until that axis gridmarkcount became 20.
  • Ensure each axis has an appropriate minimum and maximum to ensure first value is the absolute bottom and highest value is at the absolute top.
Hope this helps somehow!

Slxe wrote at 2014-07-02 20:40:

I've been syncing the axes using Zoom, although imo it's messy and I'm not really happy with it. As far as major grid lines I just leave the primary vertical and horizontal axes to handle them >_> again not a good overall solution. I mentioned in another post that it'd also be nice to have AxisChangeTypes include the type of zoom (by scale, factor or values) and the actual values sent, to make it easier to transform them into screen points and use them with the other axes.

Here's how I'm handling the axes, pretty sure I based it off an example:
(Quick note, this is done for multiple vertical and one horizontal axes)
private void Axis_OnAxisChanged(object sender, AxisChangedEventArgs args)
{
    if (_syncChange || ((Axis) sender).IsHorizontal())
        return;
    
    _syncChange = true;
    switch (args.ChangeType)
    {
        case AxisChangeTypes.Zoom:
        case AxisChangeTypes.Pan:
            _chartIsZoomed = true;
            foreach (var a in uiChartPlot.Model.Axes)
            {
                if (a.Key == ((Axis) sender).Key || a.IsHorizontal())
                    continue;

                double min =
                    a.InverseTransform(
                        ((Axis) sender).Transform(((Axis) sender).ActualMinimum));
                double max =
                    a.InverseTransform(
                        ((Axis) sender).Transform(((Axis) sender).ActualMaximum));

                a.Zoom(min, max);
            }
            break;

//      case AxisChangeTypes.Zoom:
//          break;

        case AxisChangeTypes.Reset:
            _chartIsZoomed = false;
            break;
    }

    uiChartPlot.InvalidatePlot(false);
    _syncChange = false;
}

WPF Low performance with Axis grid lines

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

Gimly wrote at 2013-09-19 18:27:

I have a rather complex graph (16 series composed of 10 data points each, 4 scatter, 12 lines). And I get very slow refresh performances when I'm adding the axis grid lines, without them, everything runs smooth and without any issues.

I did a minimal test, and it seems to be even struggling with only 1 serie... Am I doing something wrong?

Here's the code for the "minimal" version.
            var plotModel1 = new PlotModel();
            plotModel1.LegendPosition = LegendPosition.TopLeft;
            var linearAxis1 = new LinearAxis();
            linearAxis1.MajorGridlineStyle = LineStyle.Solid;
            linearAxis1.MinorGridlineStyle = LineStyle.Dot;
            linearAxis1.Position = AxisPosition.Bottom;
            plotModel1.Axes.Add(linearAxis1);
            var linearAxis2 = new LinearAxis();
            linearAxis2.MajorGridlineStyle = LineStyle.Solid;
            linearAxis2.MinorGridlineStyle = LineStyle.Dot;
            plotModel1.Axes.Add(linearAxis2);
            var lineSeries12 = new LineSeries();
            lineSeries12.Color = OxyColor.FromArgb(255, 164, 196, 0);
            lineSeries12.MarkerFill = OxyColor.FromArgb(255, 164, 196, 0);
            lineSeries12.MarkerSize = 5;
            lineSeries12.MarkerType = MarkerType.Circle;
            lineSeries12.Points.Add(new DataPoint(0, 1.24931413366607E-06));
            lineSeries12.Points.Add(new DataPoint(2.1067699074214E-05, 1.26694618923807E-06));
            lineSeries12.Points.Add(new DataPoint(5.02464626567535E-05, 1.29136658651057E-06));
            lineSeries12.Points.Add(new DataPoint(9.06380069247887E-05, 1.32517122510278E-06));
            lineSeries12.Points.Add(new DataPoint(0.00014072807797715, 1.36709279011516E-06));
            lineSeries12.Points.Add(new DataPoint(0.000198638830168781, 1.41555966811938E-06));
            lineSeries12.Points.Add(new DataPoint(0.000262199225377347, 1.46875486596933E-06));
            lineSeries12.Points.Add(new DataPoint(0.000329026423873679, 1.52468412874539E-06));
            lineSeries12.Points.Add(new DataPoint(0.000396615115502864, 1.58125070313242E-06));
            lineSeries12.Points.Add(new DataPoint(0.000462431442205522, 1.63633394339889E-06));
            lineSeries12.Points.Add(new DataPoint(0.000524007990782276, 1.68786881308793E-06));
            plotModel1.Series.Add(lineSeries12);
            return plotModel1;
(The ctrl-alt-c command is a reaaaaly clever idea by the way :))

Love the library, I'm in the process of reviewing several commercial plot libraries and OxyPlot is one of the simpler in terms of development. If I can get over that performance issue, it will make it perfect for my needs !

I just find it kind of sad that we cannot configure all the look of the plot in XAML, in the end it's where it should go. Maybe an amelioration for the future?

objo wrote at 2013-09-20 09:06:

See https://oxyplot.codeplex.com/wikipage?title=Performance&referringTitle=Documentation
Dotted lines are not performing well in WPF. There is nothing we can do about that, I think.

Gimly wrote at 2013-09-20 10:54:

Thanks for the link!

I just switched to solid lines and indeed it's faster.

Noob question : how to clone OxyPlot git repository.

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

vboilay wrote at 2014-05-01 10:37:

Hello,
Can someone drive me to a tutorial (or explain) how to clone OxyPlot git repository so that I can recompile the windows form dlls locally ?

Thank you.

OxyPlot.Axes.DateTimeAxis ArgumentOutOfRangeException and construtor vb.net

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

cedrelo wrote at 2013-12-05 08:52:

Hi,

First, really thanks for your job!!!

The method public static DateTime ToDateTime(double value) in OxyPlot.Axes.DateTimeAxis

produce an ArgumentOutOfRangeException when we zoom out at maximum

you could correct it wih this code
        /// <summary>
        /// Converts a numeric representation of the date (number of days after the time origin) to a DateTime structure.
        /// </summary>
        /// <param name="value">
        /// The number of days after the time origin.
        /// </param>
        /// <returns>
        /// A date/time structure.
        /// </returns>
        public static DateTime ToDateTime(double value)
        {
            var result = new DateTime();

            if (double.IsNaN(value))
            {
                return result;
            }

            if (CanAddDays(timeOrigin, value-1))
            {
               result= timeOrigin.AddDays(value - 1);
            }
            
            return result;
        }

        /// <summary>
        /// Determines whether this instance [can add days] the specified dt.
        /// </summary>
        /// <param name="dt">The dt.</param>
        /// <param name="days">The days.</param>
        /// <returns></returns>
        public static bool CanAddDays(DateTime dt, double days)
        {
            double maxDaysToAdd = (DateTime.MaxValue - dt).TotalDays;
            double minDaysToAdd = (DateTime.MinValue - dt).TotalDays;
            return days <= maxDaysToAdd && days >= minDaysToAdd;
        }
And one more thing : We have to comment the default constructor to use DateTimeAxis in vb.net


Thanks again

Cedre

objo wrote at 2013-12-09 21:15:

Thanks, I never tried to zoom out that far.
I have applied some fixes that seems to help (some code in the CreateDateTickValues should also be modified).

What is the problem with the default constructor, I didn't understand.

cedrelo wrote at 2013-12-10 10:03:

we have this error in vb.net

'.ctor' is ambiguous because multiple kinds of members with this name exist in class 'OxyPlot.DateTimeAxis'

so we have to comment the default constructor

objo wrote at 2013-12-10 11:29:

I see this has already been explained before... [discussion:394977]
Sorry, I didn't notice. I guess this applies to a lot of series constructors, too?
But I think the parameterless constructors should be chosen.
Changing this will also break a lot of code...
I added https://oxyplot.codeplex.com/workitem/10103

cedrelo wrote at 2013-12-10 12:26:

Thanks a lot

you do a really great job!!!


I also use helixtoolkit to display robot trajectory in a 3D environnement!!


Thanks again.

cedrelo wrote at 2013-12-10 12:34:

Even with parameterless constructors we can't instance the class

must have to comment like this in OxyPlot.Axes.DateTimeAxis
        //public DateTimeAxis()
        //{
        //    this.Position = AxisPosition.Bottom;
        //    this.IntervalType = DateTimeIntervalType.Auto;
        //    this.FirstDayOfWeek = DayOfWeek.Monday;
        //    this.CalendarWeekRule = CalendarWeekRule.FirstFourDayWeek;
        //}

objo wrote at 2013-12-11 11:32:

Can you show the VB.NET code that fails to compile when you don't comment out the constructor?

cedrelo wrote at 2013-12-11 12:36:

    _dateAxis = New DateTimeAxis()
        With _dateAxis
            .Position = AxisPosition.Bottom
            .IntervalType = DateTimeIntervalType.Seconds
            .MajorGridlineStyle = LineStyle.Solid
            .Key = "AxisDate"
            .IsPanEnabled = False
        End With
        PlotModel.Axes.Add(_dateAxis)

objo wrote at 2013-12-12 07:48:

Thanks, but I could not reproduce the problem! That VB code compiled without any errors here!

cedrelo wrote at 2013-12-12 07:54:

??

I use visual studio 2010 maybe it is the reason ?

really strange!

Thanks

objo wrote at 2013-12-12 20:34:

I added a WPF/VB.NET example created in VS 2013 to Source\Examples\WPF.

sdille wrote at 2013-12-27 19:13:

I don't seem to see an example that shows this works. Simply doing this in Visual Basic will cause compiler errors with the following error message:

code:
Dim xAxis As DateTimeAxis = New DateTimeAxis()

error:
'.ctor' is ambiguous because multiple kinds of members with this name exist in class 'OxyPlot.DateTimeAxis'


Any suggestions? I am unable the use any of the constructors for DateTimeAxis because of this issue

objo wrote at 2014-01-07 21:27:

Sorry, I have no experience with VB, but the VB example in Source\OxyPlot.WPF_VB.sln compiles without any errors here. I can also use
Dim xAxis As DateTimeAxis = New DateTimeAxis()` without getting any compiler errors.

Note that DateTimeAxis is in the OxyPlot.Axes namespace.

Binding question

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

MarcBra wrote at 2012-05-11 02:46:

Hi!

Disclaimer:

I like OxyPlot a lot, thank you very much for your effort!

My question:

I have a fairly simple binding scenario and face some issues at the moment. It's probably simple and I don't expect a detailed answer, but a hint what to look at, best practice, or something similiar would be very helpful.

I have a UserControl which contains a plot and a couple of series, that are databound by their ItemsSource property. It's a MVVM application and the codebehind of the control is blank. If I have several instances of the UserControl bound to different ViewModels, the Plots all display the same data, which is the data of the Plot that is instantiated at first, instead of the data they are actually bound to.

Why is this and what do I have to do? I am aware of the fact that I have to manually update the plots, but it doesn't work in that case and shouldn't be an issue in this case, because the data is existent at the time the control is instantiated.

 

Thank you very much for your work and your help in advance!

 

Cheers, Marc


seveland12 wrote at 2012-05-11 15:05:

Are you setting the DataContext of each UserControl properly? It sounds like your UserControls are all bound to the same data, which, if I understand your situation correctly, is not what you intend.


MarcBra wrote at 2012-05-12 07:56:

Hi seveland, thanks for your reply.

Unfortunately, that is not the problem. This is my UserControl XAML: 

 

<UserControl x:Class="Inca.App.Controls.SpatialStressAnalysisView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf" 
             xmlns:IncaControls_Converter="clr-namespace:Inca.App.GUILogic">
    <UserControl.Resources>
        <IncaControls_Converter:BoolToVisibility x:Key="BoolToVisibility"/>
    </UserControl.Resources>
    <DockPanel> 
        <TabControl Margin="10">
                    <TabItem Header="Laminate coordinate system (LCS)">
                        <Grid Margin="10" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="300">
                                </ColumnDefinition>
                                <ColumnDefinition></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <DockPanel Grid.Column="0">

                                <GroupBox DockPanel.Dock="Top" Header="Plot graphs" Margin="0,0,0,10">
                                    <StackPanel Orientation="Vertical" Margin="5">
                                        <CheckBox Content="XZ shear stress" Name="chkVisibilityXZ" IsChecked="True"></CheckBox>
                                        <CheckBox Content="YZ shear stress" Name="chkVisibilityYZ" IsChecked="True"></CheckBox>
                                        <CheckBox Content="Z normal stress" Name="chkVisibilityZ" IsChecked="True"></CheckBox>
                                <Button Click="Button_Click">Refresh</Button>
                            </StackPanel>
                                </GroupBox>
                            <ScrollViewer Grid.Row="1" >
                                <DataGrid x:Name="grid" ItemsSource="{Binding StressPointsLCS}"></DataGrid>
                            </ScrollViewer>
                            </DockPanel>


                    <oxy:Plot Grid.Column="1" x:Name="plot" Subtitle="{Binding LaminateName}">

                                <oxy:Plot.Axes>
                                    <oxy:LinearAxis Position="Left" MajorGridlineStyle="Solid" MinorGridlineStyle="Solid" MinorGridlineColor="#11000000" Title="Stress [N/mm�]" />
                                    <oxy:LinearAxis Position="Bottom" MajorGridlineStyle="Solid" MinorGridlineStyle="Solid" MinorGridlineColor="#11000000" Title="z [mm]" />
                                </oxy:Plot.Axes>
                                <oxy:Plot.Series>
                                    <oxy:LineSeries Title="XZ Shear Stress" 
                                                        Visibility="{Binding IsChecked, ElementName=chkVisibilityXZ, Mode=OneWay, Converter={StaticResource ResourceKey=BoolToVisibility}}" 
                                                        DataFieldX="ThicknessCoordinate" DataFieldY="ShearStressParallelTransverse" Color="DarkBlue" StrokeThickness="2" ItemsSource="{Binding StressPointsLCS}"/>
                                    <oxy:LineSeries Title="YZ Shear Stress" 
                                                        Visibility="{Binding IsChecked, ElementName=chkVisibilityYZ, Mode=OneWay, Converter={StaticResource ResourceKey=BoolToVisibility}}" 
                                                        DataFieldX="ThicknessCoordinate" DataFieldY="ShearStressTransverseTransverse" Color="LightBlue" StrokeThickness="2" ItemsSource="{Binding StressPointsLCS}"/>
                                    <oxy:LineSeries Title="Z Normal Stress" 
                                                        Visibility="{Binding IsChecked, ElementName=chkVisibilityZ, Mode=OneWay, Converter={StaticResource ResourceKey=BoolToVisibility}}" 
                                                        DataFieldX="ThicknessCoordinate" DataFieldY="NormalStressTransverse" Color="Green" StrokeThickness="2" ItemsSource="{Binding StressPointsLCS}"/>
                                </oxy:Plot.Series>
                            </oxy:Plot>
                        </Grid>
                    </TabItem>           
                </TabControl>
    </DockPanel>
</UserControl>



As you can see the DataGrid in my control displays the same data as the plot. In this table, the datapoints are displayed correctly, so the DataContext is obviously correct! For testing purposes I bound the Subtitle of the Plot to a property on the ViewModel and it is displayed correctly, so the DataContext of the Plot itself is obviously correct as well. This is why I don't really know, what the issue is... The UserControl itself is used within a TabControl again (1 per TabItem). Could that play a role? Or any other ideas?

 

Thanks, Marc

 

I have a DataTemplate for the ViewModel that belongs to the control and bind the ViewModel directly to the content of a ContentPresenter (which all 

objo wrote at 2012-05-13 22:16:

I added some examples in the new Examples/WPF/WpfExamples application. See the three examples at the bottom - the first one (with a UserControl) is working, the two others (using DataTemplates) are not - I think this is related to the problem you are seeing. I have tried debugging, but not found out what is going on yet. I will not have time to look at this the coming week, maybe someone else can figure it out?

I think there is a bug in the OxyPlot.Wpf.ItemsSeries - the OnItemsSourceChanged is only called for the first plot. And it is very strange that the two plots are sharing the same collection of points...


MarcBra wrote at 2012-05-14 02:05:

Thanks, objo! I haven't figured out anything helpful so far, just a minor remark after a first look: The third example is linked to the same window as the second in MainWindow.xaml.cs:

 

new Example(typeof(UserControlDemo.MainWindow), null, "Demonstrates a Plot in a UserControl."),
new Example(typeof(UserControlDemo.MainWindow2), null, "... UserControl in a DataTemplate."),
new Example(typeof(UserControlDemo.MainWindow2), null, "... a DataTemplate.")

Anybody who wants to test it would find out himself quickly, but might make life a little easier, if I mention.


MarcBra wrote at 2012-05-14 04:41:

So, I couldn't figure out a solution yet, but the problem at least:

When specified in a DataTemplate, only one instance of the UserControl is created by the WPF. If you click through the TabItems, you always see the same instance of the UserControl and only the DataContext is changed. This is obviously meant to be and has nothing to do with this particular case. This is why the Title is displayed correctly, but the Series are not updated correctly. To make it work, the control would have to update everything including the Series on the DataContextChanged event. I don''t overlook all of the OxyPlot system yet, so I'm not sure about how.

A possible workaround is using a modified TabControl, which behaves differently or specifying the control as a ressource in a ResourceDictionary and using the x:Shared="false" attribute on the control (haven't tried it yet).

I'm out of time right now, but I'm sure we're getting there sooner or later.

 

Cheers, Marc


tstojano wrote at 2012-09-02 18:27:

I'm seeing the exact same behaviour with my MVVM usage of a oxyplot control defined within a datatemplate.

Oxyplot is always graphing the points from the first oxyplot control instead of the oxyplot control corresponding to the active tab.  As per Marc, my datacontext is definitely set correctly as the graph title is changing as expected.  Also, I verified in snoop that the Series[0].ItemsSource is correct.

I tried with no luck
- latest oxyplot (August 31 - 2012.3.135.1)
- moving the oxyplot control to a resource with x:Shared="false".

I couldn't find any defects raised in the issue tracker either.  Does anyone have a workaround/fix for this?

 

Cheers

Stoj


objo wrote at 2012-09-02 18:34:

thanks for reminding me. It is now added as issue 10000!

http://oxyplot.codeplex.com/workitem/10000

I have not had time to look into this issue myself - I hope someone else has some spare time!

0
À l'étude

Using TrackerHitResult in OxyPlot.WPF.HeatMapSeries

pettertho89 il y a 10 ans mis à jour par Oystein Bjorke il y a 10 ans 4
Hi,

We are able to find this method within oxyplot, but can not find it within oxyplot.wpf.
Is there a reason for this, and how is it possible to use this with a HeatMapSeries in Oxyplot.wpf?

Thanks in advance!

polar coordinate in imageannotation

Oystein Bjorke il y a 10 ans mis à jour par Shobhit Shakya il y a 8 ans 2
This discussion was imported from CodePlex

BlindMonk wrote at 2013-08-27 15:15:

Hi

I want to display a polar image something like:

Image

Can someone give me some pointers where I can start?

thanks a lot.

objo wrote at 2013-08-27 15:26:

The image drawing is restricted to rectangular shapes.
A custom series is required to render this. You should create an image that covers the sector (the pixels outside the sector should be transparent). For each pixel, calculate the polar coordinates, interpolate the value and set the pixel color by the color axis. This sounds like a fun example - should be added to the example library!

BlindMonk wrote at 2013-08-27 16:50:

I am not 100% sure how to do what you said.
I am working on it. Hopefully I will spend enough time to make it work.

Thanks a lot objo for this library. By the way, I hope you checked the bug I posted in imageannotation.

objo wrote at 2013-08-28 01:53:

See the new 'PolarHeatMapSeries' example (under 'Custom series' in the example browser). It is not optimized for performance, but hopefully you can use some of it for your own custom implementation.

BlindMonk wrote at 2013-08-29 11:04:

thanks for the example objo.

Interestingly I need x-y coordinates not polar, on the axes. And still no zoom on polar coordinates. I have to zoom since I have too many points and single points are of significant importance for visualization.

I was thinking may be I can make an oxyimage which looks like polar (example) and render it on XY grid.

objo wrote at 2013-08-29 11:40:

It should be possible to do this with one or two extra lines of code - where you transform from the X/Y coordinates to polar coordinates, which are mapped into the data array (I assume your data is in polar form)

objo wrote at 2013-08-29 11:55:

Added a new example. Not optimized for performance.

BlindMonk wrote at 2013-08-29 14:22:

thanks again objo. deeply appreciate.

but it is rather slow. I have to find a way to use an image instead of a series. I will use your tips and try to get it to work. I will keep posted if I need some guidelines.

BlindMonk wrote at 2013-09-06 12:17:

Using writableBitmapex, i can make a polar image, for about 50k polygons it is pretty fast. Each pixel is brawn as a polygon. Working on how to render it with oxyplot.

EDIT:

Cant make polygons with float coordinates. writablebitmapex cant be used. Square one.

objo wrote at 2013-09-06 21:23:

This was a fun little example to show the functionality of OxyImage and custom series :) I added an ImageSize property to the example series. Set it to >0 and the heat map will be generated at a fixed size, not adjusted to the size of the plot area.
I added some examples with different image sizes under "Custom series" in the example browser.

BlindMonk wrote at 2013-09-09 15:04:

thanks a lot objo.

BlindMonk wrote at 2013-10-03 14:13:

how do i get image coordinates (in XY) by mouse click??

how to just plot PlotArea ;

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

ProCodeMyth wrote at 2012-05-08 08:23:

Hi Objo,

   i want just draw plotArea, if PlotModel contain  axes, the plot will render axe majorLabel;

how i custom plotModel or axis  (ether element) to just render PlotArea in wpf( not measure axis and title) but i need plot gridline?  very thanks

 ////                LegendPosition (LegendPlacement=Outside)
    ////
    //// +               +-----------------------------------+                 +
    ////                 |              Title                |
    ////                 |            Subtitle               |
    ////                 +-----------------------------------+
    ////                 |TopLeft       TopCenter    TopRight|
    ////                 +-----------------------------------+
    ////                 |              Top axis             |
    //// +----------+----+-----------------------------------+-----+-----------+
    //// |LeftTop   |    |                                   |     |RightTop   |
    //// |          |    |                                   |     |           |
    //// |          |Left|                                   |Right|           |
    //// |LeftMiddle|axis|              PlotArea             |axis |RightMiddle|
    //// |          |    |                                   |     |           |
    //// |          |    |                                   |     |           |
    //// |LeftBottom|    |                                   |     |RightBottom|
    //// +----------+----+-----------------------------------+-----+-----------+
    ////                 |             Bottom axis           |
    ////                 +-----------------------------------+
    ////                 |BottomLeft BottomCenter BottomRight|
    //// +               +-----------------------------------+   

 


procodemyth wrote at 2012-05-08 08:59:

axis have ShowMinorTicksProperty, if i add ShowMajorLabelProperty (bool) to decide wether render majorlebal ,it is possible?


objo wrote at 2012-05-12 11:59:

Do you want to hide the axis? Then try IsAxisVisible = false


Tech_Junkie wrote at 2012-07-26 16:31:

I now use this to hide my axes sometimes, but the area used by the plot(model?) is still the same.

Is it possible to expand the plotarea instead of just showing empty space where the axes used to be?


PythagDev wrote at 2012-07-27 14:50:

I'm wondering the same thing as Tech_Junkie.  I'm trying to put a large number of graphs in a vertical stack panel and want the spacing to be as tight as possible.  Ideally, there would be no vertical area outside the plot area - so for the y values plotarea and plotandaxis area would be identical.  Can this be done?


PythagDev wrote at 2012-08-06 19:59:

Tech_Junkie et al,

I was able to eliminate my vertical space by working with both the PlotModel and Axis.  For the PlotModel object, I set:

PlotMargins to (0,0,0,0)
Padding to (0,0,0,0)
TitleFontSize to 0
SubtitleFontSize to 0
TitlePadding to 0

This eliminated the space above the plot that would normally be title and gets rid of some empty space below the plot as well.  To get rid of the rest of the empty space below the plot, I had to derive classes from the axis classes I used for the horizontal axes.  Specifically, I had been using LinearAxis and CategoryAxis for my horizontal axes depending on the kind of plot I was using.  I derived a custom class from each of those and overrode the Measure function:

public override OxySize Measure(IRenderContext

rc) {    return new OxySize (0,0); }

 

 

 I also created constructors to match the base class.  Then I used my new custom class for my plots.  It would be a bit more elegant to put to check if the axis were visible and if so, call the base class measure function.  Otherwise, return 0 size as I did above.  As it is, the base class uses the same amount of room whether the axis is visible or not - that seems like a bug to me, but maybe it's intentional.  My change eliminates all space for the axes. 


Tech_Junkie wrote at 2012-08-07 12:25:

Sounds like this should work, I'll try the oxysize(0,0) out on my axes to see if this is what I need.

Thanks!


Tech_Junkie wrote at 2012-08-10 13:29:

This does indeed work, this is my axis:

 

public class InvisibleAxis : Axis
    {
        public override bool IsXyAxis()
        {
            return true;
        }

        public override OxySize Measure(IRenderContext rc) { return new OxySize(0, 0); }
    }

 

And this is the way I implement it:

 

                Model.PlotMargins = new OxyThickness(0,0,0,0);
                Model.Padding = new OxyThickness(0,0,0,0);
                Model.TitleFontSize = 0;
                Model.SubtitleFontSize = 0;
                Model.TitlePadding = 0;

                Model.Axes.Clear();

                Model.Axes.Add(new InvisibleAxis { Position = AxisPosition.Bottom });
                Model.Axes.Add(new InvisibleAxis { Position = AxisPosition.Left });

objo wrote at 2012-08-23 16:02:

Did you see the "Source\Examples\Silverlight\SparklineDemo"? I don't think it is necessary to create a custom InvisibleAxis, just set IsAxisVisible = false.


jcma86 wrote at 2014-08-07 17:22:

How can I get the actual width of an axis?

Thanks.

objo wrote at 2014-08-08 10:38:

I think you can get the value from ActualPlotMargins or PlotArea. Note that the plot must be updated before these properties can be used.

Change the color of selected points in a scatter series

Oystein Bjorke il y a 10 ans 0
This discussion was imported from CodePlex

Gimly wrote at 2013-09-20 14:01:

I need to display a point in the scatter series with a different color when it is selected.

I can't find any example and any information on how to do it, is it possible?

objo wrote at 2013-09-20 14:53:

Sorry, the scatter series is not currently supporting selection of individual points. You can probably find a work-around by temporary setting special (e.g. high or low) values to the ScatterPoint.Value property.
I think the nicest solution would be to create a custom scatter series with an IsSelected property in the items.

Gimly wrote at 2013-09-20 15:36:

By creating a custom scatter series, you mean in my code? It would mean creating a class inheriting from ScatterSeries that would use a IsSelected property on items?

Or maybe I should do it in a fork? Would it be interesting to add this functionality in the core of OxyPlot?

If so, should it be a new ScatterSeries inheriting from ScatterSeries (like "SelectableScatterSeries") or should I add this functionality directly into the ScatterSeries?

objo wrote at 2013-09-23 21:43:

Yes, let us try to implement the (multi)select functionality into a SelectableScatterSeries first.

I see at least three possible ways to implement the selection
a. create a SelectableScatterPoint class with an IsSelected property
b. keep the selection in a dictionary in the series class
c. add IsSelected to the ScatterPoint class
I guess a) and c) is better for data binding.

My only concern about this is that it may trigger requests for selecting single items of Bar/ColumnSeries, PieSeries, segments of LineSeries etc. etc.... :)

Gimly wrote at 2013-09-24 09:52:

I would go with the c) option, but then does it really make sense to create a "SelectableScatterSeries"? Wouldn't it be more logical to add a "SelectionType" enumerable to the ScatterSeries with these options:
  • Series => the whole series is selected, default value, like now
  • SinglePoint => only one point at a time can be selected, when we select another, it is deselected
  • MultiplePoints => multiple points in the series can be selected
Like that we add the functionality directly to the scatter series without modifying anything.

By the way, ScatterSeries already has a "SelectedIndex", coming from SelectablePlotElement. Wouldn't it make sense to use this? Unfortunately it won't help with the MultiplePoints, but it could be used for the SinglePoint and Series, as it already states that it should use "-1" for all items.

I see that a lot of series type (e.g. line, stairs or candle stick) use this option through the GetSelectableColor method. Is there a reason for which not all series use this option?

Edit: Actually after further research, I see that the GetSelectableColor is always called without the "index", which passes "-1" as a default value, making always the whole series selected. Was this a first implementation of selection that was never finished? Actually, I see no examples of selection, has the selection implementation been finished?

objo wrote at 2013-09-24 13:29:

Yes, this implementation is not finished.

Yes, we should add a selection type property to the SelectablePlotElement, but I suggest to call it SelectionMode
http://msdn.microsoft.com/en-us/library/system.windows.controls.selectionmode.aspx

Note that the SelectablePlotElement is used by both annotations and series.

I suggest to rename GetSelectableColor to GetActualItemColor and replace SelectedIndex by something like
        /// <summary>
        /// Occurs when the selected items is changed.
        /// </summary>
        public event EventHandler SelectedItemsChanged;

        /// <summary>
        /// Gets or sets the selection mode.
        /// </summary>
        /// <value>The selection mode.</value>
        public SelectionMode SelectionMode { get; set; }

        /// <summary>
        /// The selected items.
        /// </summary>
        private Dictionary<int, bool> selectedItems = new Dictionary<int, bool>();

        /// <summary>
        /// Gets the indices of the selected items in this element.
        /// </summary>
        /// <returns>A collection of item indices.</returns>
        public IEnumerable<int> GetSelectedItems()
        {
            return this.selectedItems.Keys;
        }

        /// <summary>
        /// Clears the selected items.
        /// </summary>
        public void ClearSelectedItems()
        {
            this.selectedItems.Clear();
            this.OnSelectedItemsChanged();
        }

        /// <summary>
        /// Determines whether the specified item is selected.
        /// </summary>
        /// <param name="index">The index of the item.</param>
        /// <returns><c>true</c> if the item is selected; otherwise, <c>false</c>.</returns>
        public bool IsItemSelected(int index)
        {
            return this.selectedItems.ContainsKey(index);
        }

        /// <summary>
        /// Selects the specified item.
        /// </summary>
        /// <param name="index">The index.</param>
        public void SelectItem(int index)
        {
            this.selectedItems[index] = true;
            this.OnSelectedItemsChanged();
        }

        /// <summary>
        /// Unselects the specified item.
        /// </summary>
        /// <param name="index">The index.</param>
        public void UnselectItem(int index)
        {
            if (this.selectedItems.ContainsKey(index))
            {
                this.selectedItems.Remove(index);
                this.OnSelectedItemsChanged();
            }
        }

        /// <summary>
        /// Raises the <see cref="E:SelectedItemsChanged" /> event.
        /// </summary>
        /// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void OnSelectedItemsChanged(EventArgs args = null)
        {
            var e = this.SelectedItemsChanged;
            if (e != null)
            {
                e(this, args);
            }
        }
where
    public enum SelectionMode { All, Single, Multiple }
Adding selected/unselected items to the SelectedItemsChanged event args is probably also a good idea.

I keep getting a 404 from codeplex, so cannot push any of these changes.

Agree, we can implement this without creating a sub class.

Gimly wrote at 2013-09-24 14:13:

Seems very good to me!

The only tricky part is that the GetSelectableColor is used in the Render section of most series, but without passing the index since it's calling methods (like DrawClippedLines) that take a series of points. The way the render of most series is implemented now, it's impossible to pass different colors for each point.

Maybe it should be the RenderContext's role to check if the point is selected and select the correct color if the element is selected? But this would mean that the IsSelected should be also on ScreenPoints and I don't know if that makes a lot of sense.

PS: CodePlex gives me also a 404 for both my Fork and OxyPlot, any info on that?

objo wrote at 2013-09-24 19:13:

I don't think we should add more to the ScreenPoints - it should be a lightweight structure.
I see the selection should contain both an item index and an index to what is being selected (e.g. high/low/open/close in a HighLowSeries, or segment/point in a LineSeries).

I think selection can be handled in the Series, and we should avoid adding more complexity to the RenderContext (I want to keep it as simple as possible, to make it easy to port to new platforms). We can add an extension method that does DrawClippedLines on selected segments only.

404: I submitted a notice on the codeplex support form, and there is an issue: https://codeplex.codeplex.com/workitem/26971

Gimly wrote at 2013-09-26 14:08:

So, I went a bit further in my investigation for doing this.

First, about the modification of the SelectablePlotElement:
  • What should we do with the IsSelected property? Is it still valid? For example, for selecting a point, we could imagine that first the series should be selected, and then individual points in the series could be selected as well. Or, it could be valid only if the SelectionMode is "All".
  • Should we keep the Selectable property, or should we add a SelectionMode option to "None".
About the index of what is being selected, are you sure that selection of individual elements (like high/low/open/close for a HighLowSeries or segment in a LineSeries) makes sense? For the LineSeries, I would have guessed that only selection of "Points" (PointMarker) would make sense. Or maybe a selection of a range (like if you would like to change the color of the selected range in the "Select range" example.

In general and about implementing it on the series.
  • The GetSelectableColor methods on the SelectablePlotElement are really awkward and don't really make sense since all selectable element should have the same selection color.
  • Since most points / segments are drawn as a batch through the extension methods, we need to find a way to pass to those extension methods information about which points / segments are actually selected, and what is the "selection" color.
I would say the simplest would be to modify the extension methods to add an enumerable of "selected index" and a selection color (or 2 for example for the marker where there is the stroke and fill color.

What do you think?

Edit:
Another idea I just had, we could do the same as was done with the MarkerSize for the DrawMarkers extension method, make the extension method accept an IList<OxyColor> instead of simply markerFill and markerStroke.

objo wrote at 2013-09-26 14:57:

I think all selected points should be drawn in the same call, this will be better for performance.
Also, it is good that all selected points are drawn on top of the others.

Idea - we could create a new Selection type with a method IsItemSelected(int index, Enum feature)

where index is related to the items and feature describes whether it is a marker, line segment, high, low etc.

Should the Selection be stored on the PlotModel or on each element of the plot?

Gimly wrote at 2013-09-26 15:18:

Aaah, I think I just understood something that I had missed :)

The selected points / segments / whatever should be drawn on top of the "standard" series point / segment / whatever so that we can select even things that are not displayed (like a Marker in a Series that doesn't display a marker).

I was trying to change the color of existing markers whether they are selected or not, but I see now that this doesn't really make sense as we would only see selection if the element is displayed and we might want to display selected items differently...

The difficulty with the Selection type would be that the selection can be very different depending on the series type and even a simple series could have multiple types of selection.

If we look at the LineSeries, here are a few types of selection that we could want:
  • Selection of a range (from x=1 to x=20), on both axes
  • Selection of the whole series (if we have multiple series for example)
  • Selection of individual point(s) in the series
  • Selection of individual segment(s) of the series (would make sense only if the series is not smooth)
And the user could want to display also differently each type. For example, the segment selection, he could want to display or not point markers. You could want to display also selection differently from series to series or want to select multiple Series at the same time.

Storing the Selection on the PlotModel would allow more easily to make only one series selectable at the same time, or having multiple. But the big question... what should the Selection type be? :D

Gimly wrote at 2013-09-26 16:34:

OK, I implemented an example that makes it possible to select the ScatterSeries correctly. The Scatter is the simplest of the series to make the selection since it's only a matter of selecting individual makers. I've simply used the "SelectionColor" that is available in the Plot and used it for both fill and stroke of the selection marker.

The code is visible in my fork.
https://hg.codeplex.com/forks/gimly/oxyplot

I don't want to make a pull request just yet as I think this solution might not be optimal to make the selection work easily with other type of series. It's working for my needs with the scatter, but I think we should find something more global to make it work with any series.


Gimly wrote at 2013-09-27 10:41:

Thanks, fixed.

What do you think? Should I do a pull request or you prefer to find a better solution first?

objo wrote at 2013-09-27 10:45:

It looked good - I pushed it into the default fork with some changes (added a "Selection" field - prepared for selection of features of items + I don't think the rendering needs to know about the SelectionMode)

Gimly wrote at 2013-09-27 12:35:

Nice, thanks!

Found a small bug though, in the SelectablePlotElement.SelectItem method, if the SelectionMode is Single, you should clear the selection before selecting the new one.

The way it works now, Single or Multiple doesn't make any difference.

I would have fixed it myself, but I messed-up my fork and had to delete it.

objo wrote at 2013-09-27 15:33:

I have submitted the change.