I'm trying to make my plot change it's interval type depending on the level of zoom but I'm not sure how to achieve this. I'm using a DateTimeAxis and would like it to start at Days. Then zooming out would change from days to months, finally to years. Zooming in would change from Days to hours, maybe seconds if this type of behavior is even possible.
Currently I have my axes setup as follows:
public DateTimeAxis HorizontalAxis
{
get
{
return new DateTimeAxis
{
Position = AxisPosition.Bottom,
Minimum = DateTimeAxis.ToDouble(Start),
Maximum = DateTimeAxis.ToDouble(End),
MajorStep = double.NaN,
MinimumMajorStep = 0,
MinorStep = double.NaN,
MinimumMinorStep = 0,
AbsoluteMinimum = DateTimeAxis.ToDouble(Start),
AbsoluteMaximum = DateTimeAxis.ToDouble(End),
MinorIntervalType = DateTimeIntervalType.Hours,
IntervalType = DateTimeIntervalType.Days,
Title = " Date Time Axis Title "
};
}
}
public LinearAxis VerticalAxis
{
get
{
return new LinearAxis
{
Position = AxisPosition.Left,
Minimum = SetPoint - 4,
Maximum = SetPoint + 4,
MajorStep = double.NaN,
MinimumMajorStep = 0,
MinorStep = 0.5,
MinimumMinorStep = 0,
AbsoluteMinimum = SetPoint - 4,
AbsoluteMaximum = SetPoint + 4,
MinorTickSize = 0,
Title = " Linear Axis Title "
};
}
}
If this type of behavior is not possible I would also ask if there is a way to get hours to show when zooming in from days. When making a default plot this was the behavior I saw.
Thanks!
I know I just posted this question but perhaps there are other people who are interested in getting this type of behavior.
To dynamically change the axis I used the AxisChanged event described Here
From there I created an output message to see what properties were changing in the axes. I found that the Scale, Minor Step Size, and Major Step Size are what changes on zooming. Implementing a simple if statement to check the scale I was able to get the behavior I desired.
private async void Horizontal_AxisChanged(object sender, AxisChangedEventArgs e)
{
DateTimeAxis horizontal = sender as DateTimeAxis;
if(horizontal.Scale > 100)
{
horizontal.IntervalType = DateTimeIntervalType.Hours;
}
else if(horizontal.Scale < 100)
{
horizontal.IntervalType = DateTimeIntervalType.Days;
}
}
Related
This is my first project in c# and I'm trying to create plots from data.
I'm struggling with drawing minor and major grid lines and labels on a logarithmic scale.
I've set the scale to logarithmic, set the base to 10 and both major and minor intervals to 1, and it works great, however, the interval starts with the minimum value on scale, so for example if data starts at 30M (I'm dealing with frequencies) the next major tick is at 300M and 3G, which is not as it should be.
Is there a way to set major grid to 1, 10, 100 etc, independent of what data is displayed? i've tried changing intervals, base and offset but have not achieved much.
area.AxisX.IsLogarithmic = true;
area.AxisX.LogarithmBase = 10;
area.AxisX.Interval = 1;
//area.AxisX.IntervalOffset = 10000;
area.AxisX.IntervalAutoMode = IntervalAutoMode.FixedCount;
area.AxisX.MajorGrid.Enabled = true;
area.AxisX.MajorTickMark.Enabled = true;
area.AxisX.MinorGrid.Enabled = true;
area.AxisX.MinorGrid.Interval = 1;
area.AxisX.MinorTickMark.Enabled = true;
area.AxisX.MinorTickMark.Interval = 1;
area.AxisX.Minimum = minMaxXY[0]; // in this example 30 M
area.AxisX.Maximum = minMaxXY[1]; // in this example 1 G
here's the link to the current grid
https://ibb.co/3WkxLfc
Thank you for your time and answers!
Thanks to TaW replay I managed to get my program working.
Here is my solution using customLabels location to draw the grid lines.
private void Chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
if (e.Chart.ChartAreas.Count > 0) // I don't yet truly understand when this event occurs,
// so I got plenty of null references.
{
Graphics g = e.ChartGraphics.Graphics;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
Color minorGridColor = Color.Gainsboro;
ChartArea area = e.Chart.ChartAreas[0];
double aymin = area.AxisY.Minimum;
double aymax = area.AxisY.Maximum;
int y0 = (int)area.AxisY.ValueToPixelPosition(aymin);
int y1 = (int)area.AxisY.ValueToPixelPosition(aymax);
foreach (var label in chart1.ChartAreas[0].AxisX.CustomLabels)
{
double xposition = area.AxisX.ValueToPixelPosition(Math.Pow(10, label.FromPosition + 0.1));
if (xposition > area.AxisX.ValueToPixelPosition(minMaxXY[0]) && xposition < area.AxisX.ValueToPixelPosition(minMaxXY[1]))
//this prevents drawing of lines outside of the chart area
{
int x = (int)xposition;
using (Pen dashed_pen = new Pen(Color.FromArgb(10, 0, 0, 0), 1))
{
dashed_pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
g.DrawLine(dashed_pen, x, y0, x, y1);
}
}
}
}
}
I also found the CustomLabel.GridTicks Property, but for some reason it did not work.
Each time I add new data to series, Y axis is panning/zooming automatically in order to fit new data into screen. How can I prevent Oxyplot from touching the axis? I would like to have the scale fixed all the time, no matter what data I feed to plot
As #Taw stated, the properties in oxyplot are the same:
plotModel.Axes.Add(new LinearAxis()
{
Position = AxisPosition.Left,
Minimum = 0,
Maximum = 10,
});
plotModel.Axes.Add(new LinearAxis()
{
Position = AxisPosition.Bottom,
Minimum = 0,
Maximum = 10,
});
I've spent hours trying to solve this silly problem. I create an histogram with asp chart control. All I want to do is have the xaxis label on the left of the column instead of centered on it. Xaxis lable doesn't seem to have a position property like series do, so I can't figure it out and it's frustrating.
Here's a sample code of the type of graphic I'm talking about to show you what I get approximately:
private void Graphique()
{
// Creating the series
Series series2 = new Series("Series2");
// Setting the Chart Types
series2.ChartType = SeriesChartType.Column;
// Adding some points
series2.Points.AddXY(1492, 12);
series2.Points.AddXY(2984, 0);
series2.Points.AddXY(4476, 1);
series2.Points.AddXY(5968, 2);
series2.Points.AddXY(7460, 2);
series2.Points.AddXY(8952, 12);
series2.Points.AddXY(10444, 4);
series2.Points.AddXY(11936, 3);
series2.Points.AddXY(13428, 3);
series2.Points.AddXY(14920, 5);
series2.Points.AddXY(16412, 1);
Chart3.Series.Add(series2);
Chart3.Width = 600;
Chart3.Height = 600;
// Series visual
series2.YValueMembers = "Frequency";
series2.XValueMember = "RoundedValue";
series2.BorderWidth = 1;
series2.ShadowOffset = 0;
series2.IsXValueIndexed = true;
// Setting the X Axis
Chart3.ChartAreas["ChartArea1"].AxisX.IsMarginVisible = true;
Chart3.ChartAreas["ChartArea1"].AxisX.Interval = 1;
Chart3.ChartAreas["ChartArea1"].AxisX.Maximum = Double.NaN;
Chart3.ChartAreas["ChartArea1"].AxisX.Title = "kbps";
// Setting the Y Axis
Chart3.ChartAreas["ChartArea1"].AxisY.Interval = 2;
Chart3.ChartAreas["ChartArea1"].AxisY.Maximum = Double.NaN;
Chart3.ChartAreas["ChartArea1"].AxisY.Title = "Frequency";
}
Now my real chart looks like this, Actual result
I would like something similar to this website :
Desired layout chart
You see, the x label is on the left, which makes way more sense considering that each column of an histogram represents the frequency of a range of values.....
Any help would be appreciated...
Did you try to add CustomLabels to replace the default ones? For example:
for (int i = 0; i <= 10; i++) {
area.AxisX.CustomLabels.Add(i + 0.5, i + 1.5, i, 0, LabelMarkStyle.None);
}
The first two are for positioning and the third would be the text value of the label.
I create a new Plot and its PlotModel with a black BackgroundColor
Then I create a new Axes. The X-Axis doesn't matter, it's invisible.
The Y-Axis is:
var valueAxisY = new OxyPlot.Axes.LinearAxis(AxisPosition.Left, minValue, maxValue)
{
AxislineThickness = 2,
AxislineColor = OxyColors.White,
MinorGridLinethickness = 2,
MajorGridLineThickness = 2,
MinorTickSize = 4,
MajorTickSize = 7,
TicklineColor = OxyColors.White,
FontSize = 40,
TextColor = OxyColors.White
}
Everything works BUT the Y-Axisline. It seems to stay black no matter what. The ticks starting 1-2 pixels on the left of where the line should be are white and have the correct length.
Is this the wrong parameter?
The trick was Undefined.
var valueAxisY = new OxyPlot.Axes.LinearAxis(AxisPosition.Left, minValue, maxValue)
{
LineStyle = LineStyle.Undefined
};
Somehow this is a visible, editable, continuous line.
If you define the axis line you should also hide the border arround plot area, because it is drawn over the axis line.
using model.PlotAreaBorderThickness = 0
I'm trying to draw a threshold (1 line from left to right). To do so I add the threshold value twice and the value 0 and 1 for xValues then set the scale of X to be from 0 to 1.
public static void AddThreshold(Chart xlChart, double value, string name, int color, bool secondary)
{
Series series = xlChart.SeriesCollection().NewSeries();
series.Name = name;
series.XValues = new List<int>() { 0, 1 }.ToArray();
series.Values = new List<double>() { value, value }.ToArray();
Axis xAxis, yAxis;
if (secondary)
{
series.AxisGroup = XlAxisGroup.xlSecondary;
xAxis = (Axis)xlChart.Axes(XlAxisType.xlCategory, XlAxisGroup.xlSecondary);
yAxis = (Axis)xlChart.Axes(XlAxisType.xlValue, XlAxisGroup.xlSecondary);
}
else
{
xAxis = (Axis)xlChart.Axes(XlAxisType.xlCategory, XlAxisGroup.xlPrimary);
yAxis = (Axis)xlChart.Axes(XlAxisType.xlValue, XlAxisGroup.xlPrimary);
}
xAxis.MinimumScale = 0;//getting COM error here
xAxis.MaximumScale = 1;
yAxis.Delete();
series.ChartType = XlChartType.xlXYScatterLinesNoMarkers;
series.MarkerSize = 3;
series.Border.LineStyle = XlMarkerStyle.xlMarkerStyleDash;
series.Border.Color = color;
}
But I'm always getting a COM error and can't figure out the problem. To make things more annoying the exact method was working in a different project (don't ask about it because the code there was partially deleted by mistake and I am not rewriting it).
You can't set min and max of an axis if it's not a value type of axis, and only XY Scatter charts have an X axis that is a value axis. You need to specify the chart type of the added series as XY Scatter before setting the axis scale.
So move this:
series.ChartType = XlChartType.xlXYScatterLinesNoMarkers;
above this:
xAxis.MinimumScale = 0;